-
Notifications
You must be signed in to change notification settings - Fork 915
Description
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:
CallablespecifiesthisObjectasScriptablebut this is not entirely compatible with strict mode in the spec. We fudge it at the moment by handlingundefinedspecially, but there's still a bunch of test cases where we fail on object equality and similar.Constructablehas no way to representnew.targetwhich is needed for classes and inheritance.- 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
- Introduce a super interface of
ScriptablecalledScope. - Redefining
Constructableas 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