Class LambdaConstructor

All Implemented Interfaces:
Serializable, Callable, ConstProperties<Scriptable>, Constructable, DebuggableObject, Function, PropHolder<Scriptable>, Scriptable, SymbolScriptable

public class LambdaConstructor extends LambdaFunction
This class implements a JavaScript function that may be used as a constructor by delegating to an interface that can be easily implemented as a lambda. The LambdaFunction class may be used to add functions to the prototype that are also implemented as lambdas.

In micro benchmarks (as of 2021) using this class to implement a built-in class is about 15% more efficient than using IdScriptableObject, and about 25% faster than using reflection via the ScriptableObject.defineClass() family of methods. Furthermore, it results in code that more directly maps to JavaScript idioms than either methods, it is much easier to implement than IdScriptableObject, and the lambda pattern makes it easier to maintain state in various ways that don't always map directly to the existing concepts.

See Also:
  • Field Details

    • CONSTRUCTOR_FUNCTION

      public static final int CONSTRUCTOR_FUNCTION
      If this flag is set, the constructor may be invoked as an ordinary function
      See Also:
    • CONSTRUCTOR_NEW

      public static final int CONSTRUCTOR_NEW
      If this flag is set, the constructor may be invoked using "new"
      See Also:
    • CONSTRUCTOR_DEFAULT

      public static final int CONSTRUCTOR_DEFAULT
      By default, the constructor may be invoked either way
      See Also:
    • targetConstructor

      protected final SerializableConstructable targetConstructor
  • Constructor Details

    • LambdaConstructor

      public LambdaConstructor(VarScope scope, String name, int length, SerializableConstructable target)
      Create a new function that may be used as a constructor. The new object will have the Function prototype and no parent. The caller is responsible for binding this object to the appropriate scope. The new constructor function can be invoked using "new" or by calling it directly, and in either case will result in a new object being returned and wired to the correct prototype and scope.
      Parameters:
      scope - scope of the calling context
      name - name of the function
      length - the arity of the function
      target - an object that implements the function in Java. Since Constructable is a single-function interface this will typically be implemented as a lambda.
    • LambdaConstructor

      public LambdaConstructor(VarScope scope, String name, int length, int flags, SerializableConstructable target)
      Create a new function that may be used as a constructor. The new object will have the Function prototype and no parent. The caller is responsible for binding this object to the appropriate scope. The "flags" argument controls whether the function may be invoked using "new," via a direct call, or both. If allowed by the flags, then the constructor will have the same effect either way. If not allowed by the flags, then a TypeError will be thrown.
      Parameters:
      scope - scope of the calling context
      name - name of the function
      length - the arity of the function
      flags - which may be a combination of CONSTRUCTOR_NEW and CONSTRUCTOR_FUNCTION
      target - an object that implements the function in Java. Since Constructable is a single-function interface this will typically be implemented as a lambda.
    • LambdaConstructor

      public LambdaConstructor(VarScope scope, String name, int length, SerializableCallable target, SerializableConstructable targetConstructor)
      Create a new function that may be used as a constructor. The new object will have the Function prototype and no parent. The caller is responsible for binding this object to the appropriate scope. The new constructor function will have different behavior depending on whether it is invoked via "new" or via a direct call. In the case of "new", a new object with a prototype and scope chain be returned, but in the case of a direct call, the user must implement whatever they need. This is typically used in the case of functions like the native Date constructor, which has totally different behavior depending on how it's invoked.
      Parameters:
      scope - scope of the calling context
      name - name of the function
      length - the arity of the function
      target - an object that implements the function in Java. Since Constructable is a single-function interface this will typically be implemented as a lambda.
    • LambdaConstructor

      public LambdaConstructor(VarScope scope, String name, int length, Object prototype, SerializableCallable target, SerializableConstructable targetConstructor)
  • Method Details

    • getTargetConstructor

      protected Constructable getTargetConstructor()
    • call

      public Object call(Context cx, Object nt, VarScope scope, Object thisObj, Object[] args)
      Overrides:
      call in class LambdaFunction
    • construct

      public Scriptable construct(Context cx, Object nt, VarScope scope, Object[] args)
      Description copied from interface: Function
      Call the function as a constructor.

      This method is invoked by the runtime in order to satisfy a use of the JavaScript new operator. This method is expected to create a new object and return it.

      If nt is equal to this then this call is equivalent `new f(...arguments), but reflection and super constructor calls may pass in different values.

      Specified by:
      construct in interface Constructable
      Specified by:
      construct in interface Function
      Overrides:
      construct in class LambdaFunction
      Parameters:
      cx - the current Context for this thread
      nt - the new.target for this call,
      scope - an enclosing scope of the caller except when the function is called from a closure.
      args - the array of arguments
      Returns:
      the allocated object
    • definePrototypeMethod

      public void definePrototypeMethod(VarScope scope, String name, int length, SerializableCallable target)
      Define a function property on the prototype of the constructor using a LambdaFunction under the covers.
    • definePrototypeMethod

      public void definePrototypeMethod(VarScope scope, String name, int length, SerializableCallable target, int attributes, int propertyAttributes)
      Define a function property on the prototype of the constructor using a LambdaFunction under the covers.
    • definePrototypeMethod

      public void definePrototypeMethod(VarScope scope, SymbolKey name, int length, SerializableCallable target)
      Define a function property on the prototype of the constructor using a LambdaFunction under the covers.
    • definePrototypeMethod

      public void definePrototypeMethod(VarScope scope, SymbolKey name, int length, SerializableCallable target, int attributes)
    • definePrototypeMethod

      public void definePrototypeMethod(VarScope scope, SymbolKey name, int length, SerializableCallable target, int attributes, int propertyAttributes)
      Define a function property on the prototype of the constructor using a LambdaFunction under the covers.
    • definePrototypeMethod

      public void definePrototypeMethod(VarScope scope, String name, int length, Object prototype, SerializableCallable target, int attributes, int propertyAttributes)
      Define a function property on the prototype of the constructor using a LambdaFunction under the covers.
    • defineKnownBuiltInPrototypeMethod

      public void defineKnownBuiltInPrototypeMethod(Object tag, VarScope scope, String name, int length, Object prototype, SerializableCallable target, int attributes, int propertyAttributes)
      Define a function property on the prototype of the constructor using a KnownBuiltInFunction under the covers.
    • definePrototypeMethod

      public void definePrototypeMethod(VarScope scope, SymbolKey name, int length, Object prototype, SerializableCallable target, int attributes, int propertyAttributes)
      Define a function property on the prototype of the constructor using a LambdaFunction under the covers.
    • definePrototypeProperty

      public void definePrototypeProperty(String name, Object value, int attributes)
      Define a property that may be of any type on the prototype of this constructor.
    • definePrototypeProperty

      public void definePrototypeProperty(Symbol key, Object value, int attributes)
    • definePrototypeProperty

      public void definePrototypeProperty(Context cx, String name, ScriptableObject descriptor)
    • definePrototypeProperty

      public void definePrototypeProperty(Context cx, Symbol key, ScriptableObject descriptor)
    • definePrototypeProperty

      public void definePrototypeProperty(Context cx, String name, ScriptableObject.LambdaGetterFunction getter, int attributes)
      Define a property on the prototype using a function. The function will be wired to a JavaScript function, so the resulting property will look just like one that was defined using "Object.defineOwnProperty" with a property descriptor.
    • defineProperty

      public void defineProperty(Context cx, String name, ScriptableObject.LambdaGetterFunction getter, int attributes)
    • definePrototypeProperty

      public void definePrototypeProperty(Context cx, String name, ScriptableObject.LambdaGetterFunction getter)
    • definePrototypeProperty

      public void definePrototypeProperty(Context cx, Symbol key, ScriptableObject.LambdaGetterFunction getter, int attributes)
    • definePrototypeProperty

      public void definePrototypeProperty(Context cx, String name, ScriptableObject.LambdaGetterFunction getter, ScriptableObject.LambdaSetterFunction setter, int attributes)
      Define a property on the prototype using functions for getter and setter. The function will be wired to a JavaScript function, so the resulting property will look just like one that was defined using "Object.defineOwnProperty" with a property descriptor.
    • definePrototypeProperty

      public void definePrototypeProperty(Context cx, String name, ScriptableObject.LambdaGetterFunction getter, ScriptableObject.LambdaSetterFunction setter)
    • definePrototypeProperty

      public void definePrototypeProperty(Context cx, Symbol key, ScriptableObject.LambdaGetterFunction getter, ScriptableObject.LambdaSetterFunction setter, int attributes)
    • definePrototypeProperty

      public void definePrototypeProperty(Context cx, Symbol name, ScriptableObject.LambdaGetterFunction getter, ScriptableObject.LambdaSetterFunction setter)
    • definePrototypeAlias

      public void definePrototypeAlias(String name, SymbolKey alias, int attributes)
      Define a property on the prototype that has the same value as another property.
    • definePrototypeAlias

      public void definePrototypeAlias(String name, String alias, int attributes)
      Define a property on the prototype that has the same value as another property.
    • defineProperty

      public void defineProperty(Context cx, String name, ScriptableObject.LambdaGetterFunction getter, ScriptableObject.LambdaSetterFunction setter, int attributes)
    • defineConstructorMethod

      public void defineConstructorMethod(VarScope scope, String name, int length, SerializableCallable target)
      Define a function property directly on the constructor that is implemented under the covers by a LambdaFunction.
      Parameters:
      name - the key to use to look up the new function property, and also the value to return for the "name" property of the Function object
      length - the value to return for the "length" property of the Function object
      target - the target to call when the method is invoked
    • defineConstructorMethod

      public void defineConstructorMethod(VarScope scope, Symbol key, String name, int length, SerializableCallable target)
      Define a function property directly on the constructor that is implemented under the covers by a LambdaFunction.
      Parameters:
      key - the Symbol to use to look up the property
      name - the value to return for the "name" property of the Function object
      length - the value to return for the "length" property of the Function object
      target - the target to call when the method is invoked
    • defineConstructorMethod

      public void defineConstructorMethod(VarScope scope, String name, int length, SerializableCallable target, int attributes, int propertyAttributes)
      Define a function property directly on the constructor that is implemented under the covers by a LambdaFunction, and override the properties of its "name", "length", and "arity" properties.
    • defineConstructorMethod

      public void defineConstructorMethod(VarScope scope, String name, int length, Object prototype, SerializableCallable target, int attributes, int propertyAttributes)
      Define a function property directly on the constructor that is implemented under the covers by a LambdaFunction, and override the properties of its "name", "length", "arity", and "protoyupe" properties.
    • setPrototypeScriptable

      public void setPrototypeScriptable(ScriptableObject proto)
      Replace the default "Object" prototype with a prototype of a specific implementation. This is only necessary for a few built-in constructors, like Boolean, that must have their prototype be an object with a specific "internal data slot."
    • convertThisObject

      public static <T> T convertThisObject(Object thisObj, Class<T> targetClass)
      A convenience method to convert JavaScript's "this" object into a target class and throw a TypeError if it does not match. This is useful for implementing lambda functions, as "this" in JavaScript doesn't necessarily map to an instance of the class.
    • isConstructor

      public boolean isConstructor()
      Description copied from interface: Function
      Return whether this function can be called as a constructor.
      Specified by:
      isConstructor in interface Function
      Overrides:
      isConstructor in class LambdaFunction