-
Notifications
You must be signed in to change notification settings - Fork 465
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
Object.getOwnPropertyDescriptor throws on accessor properties of an ObjectWrap class' prototype object #485
Comments
To me it seems more that maybe InstanceGetterCallbackWrapper should handle being called when Unwrap fails or that it should check in that is has been called on a wrapper. I don't think we thought anybody would ask for the property or descriptor on the prototype, it's just there so that it is inherited when instances are created for Wrapped objects. I think we've effectively told the runtime that the InstnaceGEtterCallbackWrapper is a property on the prototype so unless I'm missing something it's reasonable for them to be called. This is what it would look like if it figured out that it was not called on a wrapper and just returned undefined: undefined
{
value: undefined,
writable: false,
enumerable: false,
configurable: false
} Not sure if that is useful though. |
With the latest comment this might also have some effect on the behaviour: nodejs/node#27851 (comment) I'd tried the earlier version but it did not resolve the reported issue. |
This is the output of the test case provided once the current version of nodejs/node#27851 is applied: {
get: [Function (anonymous)],
set: undefined,
enumerable: false,
configurable: false
} |
Interestingly the change in f nodejs/node#27851 breaks one of our unit tests. My first guess is a test problem as it depends on the order that the keys are reports by "for in" |
This confirms that depending on ordering is incorrect: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in |
Refs: nodejs#485 The test case was relyingon the ordering of "for in" which is not guarranteed as per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in Update the testcase to check in an way that does not depend on ordering.
Refs: #485 The test case was relyingon the ordering of "for in" which is not guarranteed as per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in Update the testcase to check in an way that does not depend on ordering. PR-URL: #495 Refs: #485 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: NickNaso <[email protected]>
PR-URL: nodejs#27851 Fixes: nodejs#26551 Fixes: nodejs/node-addon-api#485 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Tiancheng "Timothy" Gu <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
PR-URL: #27851 Fixes: #26551 Fixes: nodejs/node-addon-api#485 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Tiancheng "Timothy" Gu <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
PR-URL: #27851 Fixes: #26551 Fixes: nodejs/node-addon-api#485 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Tiancheng "Timothy" Gu <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
PR-URL: #27851 Fixes: #26551 Fixes: nodejs/node-addon-api#485 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Tiancheng "Timothy" Gu <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
PR-URL: #27851 Fixes: #26551 Fixes: nodejs/node-addon-api#485 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Tiancheng "Timothy" Gu <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
Refs: nodejs/node-addon-api#485 The test case was relyingon the ordering of "for in" which is not guarranteed as per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in Update the testcase to check in an way that does not depend on ordering. PR-URL: nodejs/node-addon-api#495 Refs: nodejs/node-addon-api#485 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: NickNaso <[email protected]>
Refs: nodejs/node-addon-api#485 The test case was relyingon the ordering of "for in" which is not guarranteed as per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in Update the testcase to check in an way that does not depend on ordering. PR-URL: nodejs/node-addon-api#495 Refs: nodejs/node-addon-api#485 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: NickNaso <[email protected]>
Refs: nodejs/node-addon-api#485 The test case was relyingon the ordering of "for in" which is not guarranteed as per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in Update the testcase to check in an way that does not depend on ordering. PR-URL: nodejs/node-addon-api#495 Refs: nodejs/node-addon-api#485 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: NickNaso <[email protected]>
I came across this old Issue but couldn't tell if there was a resolution to this. I am getting the same I get the error when trying to access Here is my example code: // MyObject.h
class MyObject : public Napi::ObjectWrap<MyObject> {
private:
int width = 0;
public:
MyObject(const Napi::CallbackInfo& info);
static void Initialize(Napi::Env& env, Napi::Object& target);
static Napi::FunctionReference *constructor;
Napi::Value GetWidth(const Napi::CallbackInfo& info);
void SetWidth(const Napi::CallbackInfo& info, const Napi::Value& value);
}
// MyObject.cc
Napi::FunctionReference* MyObject::constructor = new Napi::FunctionReference();
void MyObject::Initialize(Napi::Env& env, Napi::Object& target) {
Napi::HandleScope scope(env);
Napi::Function ctor = DefineClass(
env,
"MyObject",
{
InstanceAccessor("width", &MyObject::GetWidth, &MyObject::SetWidth),
}
);
*constructor = Napi::Persistent(ctor);
target.Set("MyObject", ctor);
}
MyObject::MyObject(const Napi::CallbackInfo& info) : Napi::ObjectWrap<MyObject>(info) {
Napi::Env env = info.Env();
if(info[0].IsNumber()) this->width = info[0].As<Napi::Number>().Int32Value();
}
Napi::Value MyObject::GetWidth(const Napi::CallbackInfo& info) {
return Napi::Number::New(info.Env(), this->width);
}
void MyObject::SetWidth(const Napi::CallbackInfo& info, const Napi::Value& value) {
if(value.IsNumber()) this->width = value.As<Napi::Number>().Int32Value();
} Here is example of calling it in JavaScript: // Calling from JavaScript
MyObject.prototype.width; Here is the error I am getting: |
Also please feel free to provide any advice or corrections for my code above if there is anything I am missing or have written incorrectly. I am all ears and open to any and all feedback. Thanks! |
Hi @GitMurf , Instance accessors require an instance in order to get the value. When using class MyObject {
constructor(width) {
this._width = width; // roughly equivalent to: this->width = info[0].As<Napi::Number>().Int32Value();
}
get width() {
return this._width; // roughly equivalent to: return Napi::Number::New(info.Env(), this->width);
}
} In order to access the getter, you must have an instance to call the getter from: Object.getOwnPropertyDescriptor(MyObject.prototype, 'width').get.call(new MyObject(5)) // 5 You can do the same thing above on a Node API diff --git a/6_object_wrap/node-addon-api/addon.js b/6_object_wrap/node-addon-api/addon.js
index d7dd6e0..4cec5e6 100644
--- a/6_object_wrap/node-addon-api/addon.js
+++ b/6_object_wrap/node-addon-api/addon.js
@@ -5,9 +5,11 @@ console.log( obj.plusOne() ); // 11
console.log( obj.plusOne() ); // 12
console.log( obj.plusOne() ); // 13
-console.log( obj.multiply().value() ); // 13
-console.log( obj.multiply(10).value() ); // 130
+console.log( obj.multiply().value ); // 13
+console.log( obj.multiply(10).value ); // 130
var newobj = obj.multiply(-1);
-console.log( newobj.value() ); // -13
+console.log( newobj.value ); // -13
console.log( obj === newobj ); // false
+
+console.log( Object.getOwnPropertyDescriptor(addon.MyObject.prototype, 'value').get.call(obj) ); // 13
diff --git a/6_object_wrap/node-addon-api/myobject.cc b/6_object_wrap/node-addon-api/myobject.cc
index 262a705..da8a4ee 100644
--- a/6_object_wrap/node-addon-api/myobject.cc
+++ b/6_object_wrap/node-addon-api/myobject.cc
@@ -5,7 +5,7 @@ Napi::Object MyObject::Init(Napi::Env env, Napi::Object exports) {
DefineClass(env,
"MyObject",
{InstanceMethod("plusOne", &MyObject::PlusOne),
- InstanceMethod("value", &MyObject::GetValue),
+ InstanceAccessor("value", &MyObject::GetValue, nullptr),
InstanceMethod("multiply", &MyObject::Multiply)});
Napi::FunctionReference* constructor = new Napi::FunctionReference(); Hope this helps! |
Refs: nodejs/node-addon-api#485 The test case was relyingon the ordering of "for in" which is not guarranteed as per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in Update the testcase to check in an way that does not depend on ordering. PR-URL: nodejs/node-addon-api#495 Refs: nodejs/node-addon-api#485 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: NickNaso <[email protected]>
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 byNapi::ObjectWrap::DefineClass
. Suppose it has a property namedhello
, which was defined byNapi::ObjectWrap::InstanceAccessor
. If you then try toObject.getOwnPropertyDescriptor(DemoClass.prototype, "hello")
, you get an error:The reason is that
Napi::ObjectWrap::InstanceGetterCallbackWrapper
attempts to unwrapthis
, which doesn't work becauseDemoClass.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:
git clone
it.npm install
node run.js
The text was updated successfully, but these errors were encountered: