-
-
Notifications
You must be signed in to change notification settings - Fork 31.7k
n-api: fix inheritance #20267
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
n-api: fix inheritance #20267
Conversation
@nodejs/n-api @nodejs/addon-api PTAL |
src/node_api.cc
Outdated
} | ||
} | ||
}/* | ||
}*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks odd. Bracket just needs to be removed?
src/node_api.cc
Outdated
*result = v8impl::JsValueFromV8LocalValue(scope.Escape(v8_result_value)); | ||
|
||
if (static_property_count > 0) { | ||
if (static_property_count > 0) { */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here code, likely needs to be removed or uncommented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess never mind since I was just looking at a single commit and I think its not there when all commits are reviewed.
Change looks reasonable as long as @TimothyGu @hashseed confirm its correct. |
I think the problem is that V8 does not recognize a subclass as being derived from a superclass for the case where the superclass was declared natively, and it's methods include a signature which normally forces their So, assuming const NativeClass = require('./build/Release/native_class.node');
class Subclass extends NativeClass {};
const x = new Subclass();
x.superclassMethod(); will work, whereas const NativeClass = require('./build/Release/native_class.node');
const Subclass = function() {};
Object.setPrototypeOf(Subclass.prototype, NativeClass.prototype);
const x = new Subclass();
x.superclassMethod(); will throw Yet, in both cases We apply such a On the native side this means that we cannot really implement |
This PR actually drops the |
Yep - as soon as I add the signature back in I get the |
So, alternatively, we could remove the |
@gabrielschulhof can we get together for 15 mins to discuss on Monday? That will help me understand/comment more quickly. |
@mhdawson absolutely. I'll be lurking in the hangout. |
... starting at around 9:15 AM EDT. |
@mhdawson it seems that So, nodejs/node-addon-api#246 is really a feature request. Yet, I'm still not sure whether V8 could be modified to recognize a method call as valid not only when the receiver is an instance of a subclass declared via After all, in both cases @hashseed @TimothyGu please weigh in from the V8 side! |
The reason why
|
Sorry, I just found about this thread now. @verwaest probably knows more about this! |
If I'm not mistaken, you are running into this check. If you have a signature defined, we will iterate the prototype chain in |
Sorry, just found out about this thread as well. I will take a look soon, but my initial hunch is that the invalid invocation due to signature check is hinting at another bug. |
@hashseed Node.js has always had this restriction. As a result, instances subclasses of classes created with If |
@hashseed I checked the way In the former case, it returns before it ever iterates, because it seems that the function template from the signature is also the function template for the subclass as well. IOW, it returns from here. OTOH, when the subclass is constructed via prototype assignment, it also doesn't iterate over the prototype chain, because the following check succeeds and it immediately returns |
Closing this as dropping the signature is not the right way to go. |
In
napi_define_class()
we assign prototype properties toInstanceTemplate
. This seems to cause anIllegal invocation
exception when attempting to call a method on an object which is inherited from its parent class.OTOH if we retrieve the
"prototype"
property of the class and assign prototype properties to the resulting object, following the prototype chain and retrieving the method and invoking it from the parent class' prototype works.This problem has been discussed in nodejs/node-addon-api#246.
Should there be a distinction between assigning properties to a
FunctionTemplate
'sInstanceTemplate
and to the object residing at the resulting function's"prototype"
property?@TimothyGu @hashseed what do you think?
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes