-
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: add ability to remove a wrapping #14658
Conversation
doc/api/n-api.md
Outdated
|
||
Retrieves a native instance that was previously wrapped in the JavaScript | ||
object `js_object` using `napi_wrap()` and removes the wrapping, thereby | ||
restoring the JavaScript object's prototype chain. |
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.
Does this invoke the finalizer callback of the previous wrapping? Should it?
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.
My intention was that it not call the finalizer callback. I need to test this.
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.
Why shouldn't it?
Either way, the behavior needs to be documented.
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.
If it calls the finalizer callback it's kinda useless to return the pointer, since it's already freed. I guess my concept was that by removing the wrapping, you resume responsibility for freeing the pointer, having previously assigned such responsibility to the VM.
... and I need to update the documentation ...
|
||
- `[in] env`: The environment that the API is invoked under. | ||
- `[in] js_object`: The object associated with the native instance. | ||
- `[out] result`: Pointer to the wrapped native instance. |
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.
Why also return the pointer here? That is already available via napi_wrap()
. Or, maybe these two APIs could be combined, with a boolean parameter that indicates whether to remove it at the same time. (I'm not sure I actually prefer that though.)
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 it's to avoid having to make two API calls. In nodejs/abi-stable-node#266 @sampsongao is trying to do a napi_unwrap()
followed unconditionally by a napi_wrap()
. Knowing that an unconditional napi_wrap()
will follow would allow him to drop in napi_remove_wrap()
instead of napi_unwrap()
.
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.
If you're concerned about performance, why not make it work in one napi_wrap()
call? Maybe a boolean to allow overwriting a previous wrap? Or return a previous wrap value?
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.
@mhdawson wanted an explicit napi_remove_wrap()
, but, I guess an explicit true
/false
parameter is also, well, explicit.
If we do this within napi_unwrap()
, though, we're treading into semver-major territory - which I OK while in experimental, but still, to be discussed, right?
|
||
napi_status napi_remove_wrap(napi_env env, napi_value obj, void** result) { | ||
NAPI_PREAMBLE(env); |
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 a try-catch needed 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.
I took it as a hint from V8 that an exception may be thrown in ->SetPrototype()
because it returns a v8::Maybe<bool>
- much like .
In fact, we should re-examine how we deal with v8::Maybe(Local)?
return values as we concurrently deal with exceptions. I get the impression that an empty/nothing return value happens iff there was an exception. If that's the case then we should perhaps not return napi_generic_failure
if the v8::Maybe(Local)?
is empty, but we should rather check for an exception first and return napi_exception_pending
if we find one, and only return napi_generic_failure
if we don't.
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 don't think a v8::Maybe
return type always means there is a possibility of an exception.
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.
OK, then we need to check whether there is such a possibility.
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.
Most of the Maybe
errors can be triggered through Proxies; for example, SetPrototype()
fails when a setPrototype()
trap throws. It can also throw e.g. when you try to set up a circular prototype chain or something like that, but I don’t think that would happen 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.
@addaleax out of curiosity and AFAUK, does V8 have any APIs which return v8::Maybe
s or v8::MaybeLocal
s even though there is no chance that an exception will be thrown in their execution?
The reason I ask is that the only ones I've seen are property get/set/has/delete and SetPrototype
, all of which can throw exceptions.
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.
Wait, NM. v8::String::NewFromUtf8
.
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 was also thinking of the number APIs like v8::Value::Int32Value(context)
, that returns a maybe but doesn't throw.
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.
@jasongin But that returns a Maybe because it can throw, Symbol.toPrimitive
says hi. ;)
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.
Oh. Good to know. :)
096a29b
to
a164e89
Compare
@jasongin @nodejs/addon-api
Question: Do we want to render the functionality provided by |
During tonight's N-API meeting we decided to avoid the ABI break. Let's keep |
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
Calling napi_wrap() twice on the same object has the result of returning napi_invalid_arg on the second call. However, sometimes it is necessary to replace the native pointer associated with a given object. This new API allows one to remove an existing pointer, returning the object to its pristine, non-wrapped state. Fixes: nodejs/abi-stable-node#266
Mention that pointer ownership returns to the application after napi_remove_wrap() and add test making sure the finalize callback gets called when it needs to, and that it does not get called when it shouldn't.
a164e89
to
24126f4
Compare
AIX issue in CI was know unrelated issue. |
Arm failure was a build failure so likely unrelated, but due to failures on other platforms lets try the CI again: https://ci.nodejs.org/job/node-test-commit/11887/ |
OSX and fips failures in latest run were infra related and they had run/passed in earlier CI runs to validate this PR so I think we are good to land. |
Calling napi_wrap() twice on the same object has the result of returning napi_invalid_arg on the second call. However, sometimes it is necessary to replace the native pointer associated with a given object. This new API allows one to remove an existing pointer, returning the object to its pristine, non-wrapped state. PR-URL: #14658 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Fixes: nodejs/abi-stable-node#266
Landed in 70664bf. |
Calling napi_wrap() twice on the same object has the result of returning napi_invalid_arg on the second call. However, sometimes it is necessary to replace the native pointer associated with a given object. This new API allows one to remove an existing pointer, returning the object to its pristine, non-wrapped state. PR-URL: nodejs/node#14658 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Fixes: nodejs/abi-stable-node#266
Calling napi_wrap() twice on the same object has the result of returning napi_invalid_arg on the second call. However, sometimes it is necessary to replace the native pointer associated with a given object. This new API allows one to remove an existing pointer, returning the object to its pristine, non-wrapped state. PR-URL: nodejs/node#14658 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Fixes: nodejs/abi-stable-node#266
Calling napi_wrap() twice on the same object has the result of returning napi_invalid_arg on the second call. However, sometimes it is necessary to replace the native pointer associated with a given object. This new API allows one to remove an existing pointer, returning the object to its pristine, non-wrapped state. PR-URL: #14658 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Fixes: nodejs/abi-stable-node#266
Calling napi_wrap() twice on the same object has the result of returning napi_invalid_arg on the second call. However, sometimes it is necessary to replace the native pointer associated with a given object. This new API allows one to remove an existing pointer, returning the object to its pristine, non-wrapped state. PR-URL: #14658 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Fixes: nodejs/abi-stable-node#266
Calling napi_wrap() twice on the same object has the result of returning napi_invalid_arg on the second call. However, sometimes it is necessary to replace the native pointer associated with a given object. This new API allows one to remove an existing pointer, returning the object to its pristine, non-wrapped state. PR-URL: nodejs#14658 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Fixes: nodejs/abi-stable-node#266
Calling napi_wrap() twice on the same object has the result of returning napi_invalid_arg on the second call. However, sometimes it is necessary to replace the native pointer associated with a given object. This new API allows one to remove an existing pointer, returning the object to its pristine, non-wrapped state. Backport-PR-URL: #19447 PR-URL: #14658 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Fixes: nodejs/abi-stable-node#266
Calling napi_wrap() twice on the same object has the result of returning
napi_invalid_arg on the second call. However, sometimes it is necessary
to replace the native pointer associated with a given object. This new
API allows one to remove an existing pointer, returning the object to
its pristine, non-wrapped state.
Fixes: nodejs/abi-stable-node#266
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
n-api