-
Notifications
You must be signed in to change notification settings - Fork 859
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
rhino/src/test/java/org/mozilla/javascript/FunctionPrototypeSymbolHasInstanceTest.java
Outdated
Show resolved
Hide resolved
rhino/src/main/java/org/mozilla/javascript/IdScriptableObject.java
Outdated
Show resolved
Hide resolved
rhino/src/main/java/org/mozilla/javascript/ScriptableObject.java
Outdated
Show resolved
Hide resolved
rhino/src/main/java/org/mozilla/javascript/IdScriptableObject.java
Outdated
Show resolved
Hide resolved
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).
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.
You were right, those were unnecessary. I've removed them.
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".
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.
Fixed it.
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.
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.
You were right, those were unnecessary. I've removed them.
|
||
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.
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.
Yep, this is way simpler. Changed it to switch on execIdCall.
Thank you. I will try to address these in the coming days. |
680b2a2
to
5e7ebb0
Compare
7f1364e
to
5e7ebb0
Compare
|
||
Utils.runWithAllOptimizationLevels( | ||
(cx) -> { | ||
cx.setLanguageVersion(Context.VERSION_ES6); |
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.
there are now some assertThrows.... methods in the Utils, maybe you can use one of these
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! I've used Utils.assertEcmaErrorES6()
ce2c9af
to
31bb5ea
Compare
- Remove unnecessary code - Simplify implementation to use execIdCall as BaseFunction inherits from IdScriptableObject - Use Utils.assertEcmaErrorES6
31bb5ea
to
6e797d9
Compare
Adds support for
Function.prototype[Symbol.hasInstance]
.