Skip to content

Representation of functions and signatures of Callable and Constructable. #2054

@aardvark179

Description

@aardvark179

We have a few closely connected bugs and features that are hard to implement in compliance with the spec due to our signatures for Callable, Constructable. The problems are essentially as follows:

  1. Callable specifies thisObject as Scriptable but this is not entirely compatible with strict mode in the spec. We fudge it at the moment by handling undefined specially, but there's still a bunch of test cases where we fail on object equality and similar.
  2. Constructable has no way to represent new.target which is needed for classes and inheritance.
  3. Functions tend to conflate the function object and the executable thing that ends up being run (see bug Compiled functions and prototypes #1904).

There is also an issue that scopes probably shouldn't be full Scriptables, but this is currently required for with.

Fixing these issues causes widespread, but largely mechanical, changes to be required within our code base, but they are likely to be very minimal out side of it. I would propose fixing them roughly as follows

  1. Introduce a super interface of Scriptable called Scope.
  2. Redefining Constructable as follows:
public interface Constructable {
    Scriptable construct(Context cx, Scope scope, Object newTarget, Object[] args);
}

newTarget could possibly be a BaseFunction, I'd need to check if anywhere I the spec distinguishes between it be null and undefined.
2. Redefining Callable as follows:

public interface Callable {
    public Object call(Context cx, Scope scope, Object thisObj, Object[] args);
}

With the eventual intention that functions can handle the toObject conversion of this and similar, internally.
3. Refactor out a JavaScriptFunction object to be used for almost all functions, alongside an immutable function descriptor, and Executable objects which can represent the interpretable or compiled code. This not only helps us fix our representation of generators but also makes it much easier to change our representation of function metadata and will help enable features like recompilation of hot functions. I would propose that the Executable interface would look something like:

    public abstract Object execute(
            Context cx,
            JavaScriptFunction functionObject,
            Object newTarget,
            Scope scope,
            Object thisObj,
            Object[] args);

Keen eyed readers may notice this looks quite similar to our current direct call signatures in compiled code in that explicitly pass in the function object. The function object cannot be combined with the newTarget as one represents the function being run, and the other represents the original constructor that was called.
4. Convert interpreted functions to be JavaScriptFunctions
5. Convert compiled function to be JavaScriptFunctions
6. Convert all our lambda based functions to also be JavaScriptFunctions

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions