-
Notifications
You must be signed in to change notification settings - Fork 30k
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: enable napi_wrap() to work with any object #13250
Conversation
doc/api/n-api.md
Outdated
invoked.) Therefore when obtaining a reference a finalize callback is also | ||
[`napi_delete_reference`][] ONLY in response to the finalize callback | ||
invocation. (If it is deleted before then, then the finalize callback may never | ||
be invoked.) Therefore when obtaining a reference a finalize callback is also |
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.
Maybe add a comma after 'Therefore'
doc/api/n-api.md
Outdated
required in order to enable correct proper of the reference. | ||
|
||
Note: This API may modify the prototype chain of the wrapper object. | ||
Afterward, additional manipulation of the wrapper's prototype chain may cause | ||
`napi_unwrap()` to fail. |
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.
Is there some way we can search up the prototype chain so that unless they remove the wrapper object napi_unwrap can still work ? They could still mess it up but I think it would be less likely to happen.
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.
Yes, I'll update the code to do that.
doc/api/n-api.md
Outdated
in case the underlying native resource needs to be cleaned up when the external | ||
JavaScript value gets collected. | ||
|
||
Note: The created value is not an object, and therefore does not support |
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.
s/Note
/*Note*
doc/api/n-api.md
Outdated
required in order to enable correct proper of the reference. | ||
|
||
Note: This API may modify the prototype chain of the wrapper object. |
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... :-)
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.
Looks good to me 👍
Previously, napi_wrap() would only work with objects created from a constructor returned by napi_define_class(). While the N-API team was aware of this limitation, it was not clearly documented and is likely to cause confusion anyway. It's much simpler if addons are allowed to use any JS object. Also, the specific behavior of the limitation is difficult to reimplement on other VMs that work differently from V8. V8 requires object internal fields to be declared on the object prototype (which napi_define_class() used to do). Since it's too late to modify the object prototype by the time napi_wrap() is called, napi_wrap() now inserts a new object (with the internal field) into the supplied object's prototype chain. Then it can be retrieved from there later by napi_unwrap(). This change also includes improvements to the documentation for napi_create_external(), partly to explain how it is different from napi_wrap().
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.
LGTM
Previously, napi_wrap() would only work with objects created from a constructor returned by napi_define_class(). While the N-API team was aware of this limitation, it was not clearly documented and is likely to cause confusion anyway. It's much simpler if addons are allowed to use any JS object. Also, the specific behavior of the limitation is difficult to reimplement on other VMs that work differently from V8. V8 requires object internal fields to be declared on the object prototype (which napi_define_class() used to do). Since it's too late to modify the object prototype by the time napi_wrap() is called, napi_wrap() now inserts a new object (with the internal field) into the supplied object's prototype chain. Then it can be retrieved from there later by napi_unwrap(). This change also includes improvements to the documentation for napi_create_external(), partly to explain how it is different from napi_wrap(). PR-URL: #13250 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
CI is good, except for one failure, a timeout in test-fs-watchfile on AIX that's obviously unrelated. Landed as 8ab8c33 |
Looks like it was landed but not closed. |
@jasongin FWIW I'm now seeing a compiler warning since this PR:
|
@mscdex Thanks for pointing that out. I'll submit another PR to fix it tomorrow if nobody else gets to it earlier. |
Previously, napi_wrap() would only work with objects created from a constructor returned by napi_define_class(). While the N-API team was aware of this limitation, it was not clearly documented and is likely to cause confusion anyway. It's much simpler if addons are allowed to use any JS object. Also, the specific behavior of the limitation is difficult to reimplement on other VMs that work differently from V8. V8 requires object internal fields to be declared on the object prototype (which napi_define_class() used to do). Since it's too late to modify the object prototype by the time napi_wrap() is called, napi_wrap() now inserts a new object (with the internal field) into the supplied object's prototype chain. Then it can be retrieved from there later by napi_unwrap(). This change also includes improvements to the documentation for napi_create_external(), partly to explain how it is different from napi_wrap(). PR-URL: #13250 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Previously, napi_wrap() would only work with objects created from a constructor returned by napi_define_class(). While the N-API team was aware of this limitation, it was not clearly documented and is likely to cause confusion anyway. It's much simpler if addons are allowed to use any JS object. Also, the specific behavior of the limitation is difficult to reimplement on other VMs that work differently from V8. V8 requires object internal fields to be declared on the object prototype (which napi_define_class() used to do). Since it's too late to modify the object prototype by the time napi_wrap() is called, napi_wrap() now inserts a new object (with the internal field) into the supplied object's prototype chain. Then it can be retrieved from there later by napi_unwrap(). This change also includes improvements to the documentation for napi_create_external(), partly to explain how it is different from napi_wrap(). PR-URL: nodejs#13250 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Previously, napi_wrap() would only work with objects created from a constructor returned by napi_define_class(). While the N-API team was aware of this limitation, it was not clearly documented and is likely to cause confusion anyway. It's much simpler if addons are allowed to use any JS object. Also, the specific behavior of the limitation is difficult to reimplement on other VMs that work differently from V8. V8 requires object internal fields to be declared on the object prototype (which napi_define_class() used to do). Since it's too late to modify the object prototype by the time napi_wrap() is called, napi_wrap() now inserts a new object (with the internal field) into the supplied object's prototype chain. Then it can be retrieved from there later by napi_unwrap(). This change also includes improvements to the documentation for napi_create_external(), partly to explain how it is different from napi_wrap(). Backport-PR-URL: #19447 PR-URL: #13250 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Previously,
napi_wrap()
would only work with objects created from a constructor returned bynapi_define_class()
. While the N-API team was aware of this limitation, it was not clearly documented and is likely to cause confusion anyway. It's much simpler if addons are allowed to use any JS object. Also, the specific behavior of the limitation is difficult to reimplement on other VMs that work differently from V8. (ChakraCore doesn't have ObjectPrototypes or object internal fields.)I encountered this problem when testing the N-API port of
node-sass
: it worked on V8, but failed on Node-ChakraCore, because it usednapi_wrap()
in a slightly different way from our existing unit tests and other examples. I also submitted a corresponding PR to Node-ChakraCore to update thenapi_wrap()
implementation there to similarly allow any object. (So then the test case added here will pass there.)Regarding the updated
napi_wrap()
implementation: V8 requires object internal fields to be declared on the object prototype (whichnapi_define_class()
used to do). Since it's too late to modify the object prototype by the timenapi_wrap()
is called, napi_wrap() now inserts a new object (with the internal field) into the supplied object's prototype chain. Then it can be retrieved from there later bynapi_unwrap()
.This change also includes improvements to the documentation for
napi_create_external()
, partly to explain how it is different fromnapi_wrap()
.Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
n-api