Repository navigation
Changed behaviour for instanceof ArrayBuffer #20978
Description
Activity
This is because the
ArrayBufferpassed from the outside is from a different "realm" than the one on the inside.You can reproduce this error by passing any builtin for example if you pass
ErrorthenTypeError instanceof Errorwill evaluate tofalse.> vm.runInNewContext('Error') instanceof Error; // false in REPLThis is correct behaviour - I'm not sure why Node.js 8 behaved differently.
TypeErroris not an instance ofError, butTypeError()should be if bothErrorandTypeErrorare passed.I'm not 100% sure, but it seems to me that @Zirro is right. I couldn't see why their script logs
false. My guess is that in Node v8.11.2 accessingbufferofUint8Array's instance constructs a new array buffer usingglobal.ArrayBufferconstructor, but in Node v10.2.1 it probably calls some internal reference toArrayBufferwhich is in this case different fromglobal.ArrayBuffer@advanceddeveloper thank you for weighing in.
If both
ErrorandTypeErrorwere passed it would still not really catch these cases, namely if an actual error was thrown it would get constructed with the "right" prototype and not the passed in one.In general - I'm not sure what bug we had in Node.js 8 - but the v10 behavior is definitely more correct.
As a tangent - there are several proposals by TC39 to make this into a language (rather than Node.js) feature - https://github.com/tc39/proposal-realms
My expectation is that if you call
new Uint8Array()with the constructor from context A, its internalArrayBuffershould also be from context A. (kind of like when you call an async function created in context A, it returns a Promise from context A).
I'm not certain but it looks like a V8 bug (in Node 10).Reacted by advanceddeveloper and Domenic Denicolabtw if this is a bug, it is fixed in V8 6.7.
Very interesting, thanks for looking into this. Going by the description, this commit seems relevant: v8/v8@c68f863
- added a commit that references this issue
on May 29, 2018 - added a commit that references this issue
on Jun 3, 2018 If we can confirm this as a bug per the above, could this potentially be fixed in a future 10.x release by backporting the relevant commits from V8?
Can you check if it's fixed in Node 10.4.0? We upgraded V8 in this version
Reacted by Benjamin GruenbaumReacted by ZirroThanks, it has indeed been fixed in v10.4.0! I'll leave the issue open in case you want to add documentation about this as well, but otherwise you can close it.
Reacted by Benjamin Gruenbaum- added a commit that references this issue
on Jun 14, 2018 - added a commit that references this issue
on Jun 18, 2018 - added a commit that references this issue
on Dec 23, 2018 - added a commit that references this issue
on May 1, 2019 @targos this is happening again as of Node v11.15.0; inside Jest I'm getting
new Uint8Array().buffer instanceof ArrayBuffer === false. Unfortunately this check is in an indirect dependency so I can't work around it very easily.Reacted by Davi Aquino and hahacium@abonander Unable to reproduce the issue on v11.15.0. Please note that this issue is related to the
instanceofcheck only in case theArrayBufferconstructor of the vm context is replaced with theArrayBuffercontructor from the main context. If you hadn't explicitly passedArrayBufferconstructor to the vm context andinstanceofcheck failed, then it is working as intended. As I can see, authors of issues and PRs that referenced this issue are actually misunderstanding it.Consider the following example:
const vm = require('vm'); const ctx = { console, buffer: new Uint8Array().buffer, f(){ ctx.Uint8Array = Uint8Array; ctx.ArrayBuffer = ArrayBuffer; }, }; vm.createContext(ctx); const script = new vm.Script(` console.log(new Uint8Array().buffer instanceof ArrayBuffer); console.log(buffer instanceof ArrayBuffer); f(); console.log(new Uint8Array().buffer instanceof ArrayBuffer); console.log(buffer instanceof ArrayBuffer); `); script.runInContext(ctx);
Prior to v10.4.0 it printed
true false false trueand after the issue is fixed it prints:
true false true trueNote that it still prints
falsein the second output line, but it is not a bug.Reacted by Anna HenningsenThis sounds like a Jest bug then because it doesn't give the user control over the VM context as far as I know.
This helped me: jestjs/jest#7780 (comment)
Happening in Node 12.14.1.
Reacted by Marius Gundersen and Davi Aquinoand v14.13.0
Reacted by wuwei, Will Madden, Davi Aquino, benpetermorris and Alexander Chekmenev
vmStarting with the release of Node v10, we have seen a new behaviour with
instanceof ArrayBufferin jsdom. Our extensive use of thevmmodule is presumably involved.I have extracted the following test case from the code in jsdom:
In Node v8.11.2, this logs
true. In Node v10.2.1, it logsfalse.I can't say for certain that the new behaviour is wrong - the assignments to
thisin Window were originally added to resolve issues with globals from different contexts, and removing them fixes this particular issue in Node v10. However, doing so reintroduces the previously mentioned issues as well.