-
Notifications
You must be signed in to change notification settings - Fork 1.2k
instanceof returns incorrect result within function after prototype chain has been extended with Object.setPrototypeOf() #5915
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
Comments
Here's a more minimal repro: function Component() {}
function Shape() {}
function Box() {}
Box.prototype = Object.create(Shape.prototype);
Box.prototype.constructor = Box;
function checkInstanceOf(a, b) {
return a instanceof b;
}
console.log(
'Box.prototype instanceof Component:',
Box.prototype instanceof Component);
console.log('checkInstanceOf:',
checkInstanceOf(Box.prototype, Component));
Object.setPrototypeOf(Shape.prototype, Component.prototype);
console.log(
'Box.prototype instanceof Component:',
Box.prototype instanceof Component);
console.log(
'checkInstanceOf:',
checkInstanceOf(Box.prototype, Component)); Results
It appears that the second call to |
I've had a quick look setPrototypeOf does not appear to invalidate the IsInst inline cache and so this case involves an incorrect cache hit. Unfortunately I cannot see an easy way to access the IsInst inline cache from setPrototype of. |
I'd like to tag this for v1.12 BUT I can't work out how to fix it - if anyone would like to dig into this that would be great. |
What about ...? scriptContext->GetThreadContext()->InvalidateAllIsInstInlineCaches(); |
This will invalidate all caches, not just needed ones, so this is a pretty expensive operation to do |
Having had a look, it seems currently IsInst inline caches are stored by function, not by object. InvalidateAllIsInstInlineCaches would dump all of them for all functions whether they relate to the object we're looking at or not. The method to dump a single one is Without creating a new structure the only way to do this would be to iterate over This me a bit messy and involve a lot of iteration and checks BUT no one should be using a change prototype method on a fast path so I figure it's ok. Note we'd need to do not just the object who's prototype is being changed BUT any that inherit from it. |
Uh oh!
There was an error while loading. Please reload this page.
Hey there! I authored / maintain a web framework (https://derbyjs.com/). We use
Object.setPrototypeOf()
in a manner similar to how Node.jsutil.inherits()
is implemented. This pattern is also demonstrated in the MDN docs forObject.setPrototypeOf()
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf.We discovered an issue where an
instanceof
check returns the incorrect result in IE 11, Edge, and Node Chakra only. In our code, this leads to an error being thrown in a case where the instanceof check is supposed to guard against the prototype chain being appended to twice. Here is a simplified repro case that demonstrates the issue:In Chrome, Firefox, and Safari, we get the correct output:

IE11, Edge, and Node Chakra fail:

Some observations:
true
and then instanceof within the function returns the incorrect valuefalse
For now, we're going to work around this issue with some extra checks in the code, but I'm pretty sure this is a bug in Chakra. Please let me know if you determine otherwise.
Best,
Nate
The text was updated successfully, but these errors were encountered: