Skip to content
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

vm Context literals do not use global constructors #3907

Closed
feugy opened this issue Jun 22, 2022 · 4 comments
Closed

vm Context literals do not use global constructors #3907

feugy opened this issue Jun 22, 2022 · 4 comments

Comments

@feugy
Copy link

feugy commented Jun 22, 2022

Details

When running code inside a V8 context, and as explained in the documentation, the context comes with its own set of built-in constructors, like Array, Object and Function.

Many people got tricked because constructors in context realm are different from the Node.js ones (see resolved discussion #2880):

$ node
> vm.runInNewContext('Array') === Array
false

However, it is possible to override the context built-ins by providing the ones from Node.js realm upon creation:

$ node
> vm.runInNewContext('Array',  { Array }) === Array
true

This works as expected, except in one situation: array/object/function/regexp literals. These ones do not use provided constructors:

$node
> vm.runInNewContext('new Array() instanceof Array',  { Array })
true
> vm.runInNewContext('[] instanceof Array',  { Array })
false

The later is (in my understanding of the spec) a bug:

  1. when parsing the array litteral, the vm set its __proto__ to Array.prototype
  2. Array.prototype comes from the global object
  3. in the example above, global.Array should be the one provided (Node.js realm), and it seems it's not (context realm)
  4. when cheching prototypes, instanceof finds a mismatch whereas they should be the same

Node.js version

since v6 at least

Example code

$ node
> vm.runInNewContext('[] instanceof Array',  { Array })
false

Operating system

OSX

Scope

runtime

Module and version

vm

@addaleax
Copy link
Member

  1. when parsing the array litteral, the vm set its __proto__ to Array.prototype

The wording in the spec is (https://tc39.es/ecma262/#sec-arraycreate):

If proto is not present, set proto to %Array.prototype%.

The % notation is used to refer to language builtins (which are fixed per-realm), not JS expressions (https://tc39.es/ecma262/#sec-well-known-intrinsic-objects):

Within this specification a reference such as %name% means the intrinsic object, associated with the current realm, corresponding to the name. A reference such as %name.a.b% means, as if the "b" property of the value of the "a" property of the intrinsic object %name% was accessed prior to any ECMAScript code being evaluated.

@feugy
Copy link
Author

feugy commented Jun 22, 2022

Thanks for educating @addaleax!
So, are we doomed to use realm's built-in prototypes for literals, while global object are overrideable thanks to context?

@addaleax
Copy link
Member

@feugy Yes, exactly 👍

@feugy
Copy link
Author

feugy commented Jun 22, 2022

Ah, that's a shame 😭
Thanks a lot for the spec-peer-reviewing session.
Hope that it'll help others in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants