Skip to content

"in" operator in VM uses [[Get]] instead of [[GetOwnProperty]] #17480

Closed
@TimothyGu

Description

@TimothyGu
  • Version: master
  • Platform: all
  • Subsystem: vm
const globals = {};
const handlers = {};
const realHandlers = Reflect.ownKeys(Reflect).reduce((handlers, p) => {
  handlers[p] = (t, ...args) => {
    // Avoid printing the Receiver argument, which can lead to an infinite loop.
    console.log(p, ...(p === 'get' || p === 'set' ? args.slice(0, -1) : args));
    return Reflect[p](t, ...args);
  };
  return handlers;
}, {});
const proxy = vm.createContext(new Proxy(globals, handlers));

// Indirection needed to mitigate against #17465
// https://github.com/nodejs/node/issues/17465
const globalProxy = vm.runInContext('this', proxy);
for (const k of Reflect.ownKeys(globalProxy)) {
  Object.defineProperty(globals, k, Object.getOwnPropertyDescriptor(globalProxy, k));
}
Object.assign(handlers, realHandlers);

'a' in proxy;
  // prints "has a"
  // returns false

vm.runInContext('"a" in this', proxy);
  // prints "get a"
  // returns true (because of https://github.com/nodejs/node/issues/17465)

By spec, the in operator uses the object's [[HasProperty]] internal method, which I overrode with a Proxy trap. That's why the bare 'a' in proxy prints has a.

On the other hand, V8 doesn't quite support overriding [[HasProperty]] with the modern version of the NamedPropertyHandlerConfiguration constructor, only

  • [[Get]] getter
  • [[Set]] setter
  • [[GetOwnProperty]] descriptor
  • [[Delete]] deleter
  • [[OwnPropertyKeys]] enumerator
  • [[DefineOwnProperty]] definer

Thus I would expect the default [[HasProperty]] internal method to be used, i.e. OrdinaryHasProperty, which in turns calls the object's [[GetOwnProperty]] internal method. I.e. the descriptor should be called. Yet this isn't the case shown above -- only GenericNamedPropertyGetterCallback is called.

/cc @fhinkel @verwaest

Metadata

Metadata

Assignees

No one assigned

    Labels

    v8 engineIssues and PRs related to the V8 dependency.vmIssues and PRs related to the vm subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions