◐ Shell
clean mode source ↗

Object.getOwnPropertyDescriptor throws on accessor properties of an ObjectWrap class' prototype object

An error is thrown when trying to get the property descriptor of a Napi::ObjectWrap::InstanceAccessor from the class' prototype object.

Suppose you have a class named DemoClass, which was defined by Napi::ObjectWrap::DefineClass. Suppose it has a property named hello, which was defined by Napi::ObjectWrap::InstanceAccessor. If you then try to Object.getOwnPropertyDescriptor(DemoClass.prototype, "hello"), you get an error:

run.js:2
Object.getOwnPropertyDescriptor(DemoClass.prototype, "hello");
       ^

Error: Invalid argument
    at Function.getOwnPropertyDescriptor (<anonymous>)
    at Object.<anonymous> (run.js:2:8)
    at Module._compile (internal/modules/cjs/loader.js:738:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:749:10)
    at Module.load (internal/modules/cjs/loader.js:630:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:570:12)
    at Function.Module._load (internal/modules/cjs/loader.js:562:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:801:12)
    at internal/main/run_main_module.js:21:11

The reason is that Napi::ObjectWrap::InstanceGetterCallbackWrapper attempts to unwrap this, which doesn't work because DemoClass.prototype is not a wrapper!

But why is the callback even being called? Node checks whether native instance methods are called on a valid instance of the class, and doesn't even call the native function if not. Shouldn't it perform the same checks on native instance accessors?

I have prepared a Gist demonstrating the problem. To use:

  1. Download or git clone it.
  2. npm install
  3. node run.js