-
Notifications
You must be signed in to change notification settings - Fork 858
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FEAT: Implement Symbol.hasInstance for Function.prototype #1751
base: master
Are you sure you want to change the base?
FEAT: Implement Symbol.hasInstance for Function.prototype #1751
Conversation
@@ -31,7 +31,8 @@ static void init(Context cx, Scriptable scope, boolean sealed) { | |||
if (cx.getLanguageVersion() >= Context.VERSION_ES6) { | |||
obj.setStandardPropertyAttributes(READONLY | DONTENUM); | |||
} | |||
obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); | |||
IdFunctionObject constructor = obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); | |||
ScriptRuntimeES6.addSymbolHasInstance(cx, scope, constructor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need a language version check here (cx.getLanguageVersion() >= Context.VERSION_ES6)
+ "};\n" | ||
+ "var g = {};\n" | ||
+ "`${f.hasOwnProperty(Symbol.hasInstance)}:${g.hasOwnProperty(Symbol.hasInstance)}`"; | ||
Utils.runWithAllOptimizationLevels( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe you can use assertWithAllOptimizationLevelsES6 here
@@ -265,6 +268,11 @@ protected void fillConstructorProperties(IdFunctionObject ctor) { | |||
|
|||
@Override | |||
protected void initPrototypeId(int id) { | |||
if (id == SymbolId_hasInstance) { | |||
initPrototypeValue(id, SymbolKey.HAS_INSTANCE, makeHasInstance(), 0x0F); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please use the real attributes instead of 0x0F for readability
int instanceIdInfo, Scriptable scope, Object value, int attr) { | ||
if (instanceIdInfo == SymbolId_hasInstance) { | ||
return buildDataDescriptor(scope, value, attr, SymbolKey.HAS_INSTANCE.toString(), 1); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else not requred if you return before
@Override | ||
protected int findPrototypeId(Symbol k) { | ||
if (SymbolKey.HAS_INSTANCE.equals(k)) return SymbolId_hasInstance; | ||
else return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else not required
* | ||
* @return ScriptableObject | ||
*/ | ||
ScriptableObject buildDataDescriptorHelper( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add @OverRide... same for the next and maybe you can also copy the comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed these as they don't actually solve the problem with name and length attributes.
ScriptableObject desc = new NativeObject(); | ||
ScriptRuntime.setBuiltinProtoAndParent(desc, scope, TopLevel.Builtins.Object); | ||
desc.defineProperty("value", value, EMPTY); | ||
desc.setCommonDescriptorProperties(attributes, true); | ||
desc.setCommonDescriptorProperties(attributes, true, name, length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it a good idea to introduce this new function with two (at least for me magic parameters) including all the forwarder for the old calls if we need the additional functionality only at one place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed these as they don't actually solve the problem with name and length attributes.
} | ||
throw ScriptRuntime.typeErrorById( | ||
"msg.instanceof.bad.prototype", getFunctionName()); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else not needed because of the throw before
String name = null; | ||
if (valueArray[nameSlot] instanceof String) | ||
name = (String) valueArray[nameSlot]; | ||
else if (valueArray[nameSlot] instanceof SymbolKey) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be Symbol
and not SymbolKey
I think
732d044
to
5aa5f4a
Compare
013b02b
to
680b2a2
Compare
@0xe thanks for taking care of my comments |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this!
Unless I'm missing something (and in JavaScript I'm usually missing something) there is an existing pattern to add a new symbol-keyed property to a native object -- see the implementation of "SymbolId_Iterator" in NativeString, for instance. This change seems to be doing some of that and some of something else. Can you please try to do it that way? Thanks!
@@ -46,4 +46,15 @@ public static void addSymbolUnscopables( | |||
ScriptableObject.putProperty(unScopablesDescriptor, "writable", false); | |||
constructor.defineOwnProperty(cx, SymbolKey.UNSCOPABLES, unScopablesDescriptor, false); | |||
} | |||
|
|||
/** Registers the symbol <code>[Symbol.hasInstance]</code> on the given constructor function. */ | |||
public static void addSymbolHasInstance( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get what you're trying to do here, but I don't think that we should add a new function to a "ScriptRuntime" class that we're only going to use in one place. I'd suggest that instead of all this, you just call "defineProperty" on the "constructor" object back in BaseFunction and pass it the bitset (I'll put a comment there too).
Context cx = Context.getCurrentContext(); | ||
Object hasInstance = ScriptRuntime.getObjectElem(this, SymbolKey.HAS_INSTANCE, cx); | ||
if (hasInstance instanceof Callable) { | ||
return (boolean) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that I know all the semantics of just casting to boolean here, but if I know anything about JavaScript, it's 90% edge cases.
So, since the function here could literally return anything, you should use "ScriptRuntime.toBoolean" here, which can cast any number of objects correctly to a "boolean".
obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); | ||
IdFunctionObject constructor = obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); | ||
if (cx.getLanguageVersion() >= Context.VERSION_ES6) { | ||
ScriptRuntimeES6.addSymbolHasInstance(cx, scope, constructor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was going to ask why you don't just call "defineProperty" here, but actually I'm wondering why we need this at all -- adding the new symbol case in the other places that you added it should be enough for this to work.
|
||
if (cx != null) { | ||
Scriptable scope = this.getParentScope(); | ||
obj = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's great to use a Lambda function here, but since this class still inherits from "IdScriptableObject", you should be able to make it work by adding a case to the switch in the "exec" function for your new "SymbolId_hasInstance" case.
Thank you. I will try to address these in the coming days. |
680b2a2
to
5e7ebb0
Compare
No description provided.