-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
Introduce status napi_cannot_call_into_js
#30327
Comments
How would programs treat these two differently? |
@addaleax if we return |
This second failure is treated as a fatal error. |
@addaleax Here's a possible distinction: An exception can be cleared, and calls can once more be made into JS, whereas if an inability to call into JS is reported, then there is no way to clear that up. Good, because, currently that means the environment is shutting down. |
@addaleax I'm starting to think that perhaps this should not be semver-major, nor n-api-semver-major, but rather a bug that requires a semver-minor fix (the introduction of the new status). If you agree I will remove the labels and start a PR. |
@gabrielschulhof is there a reasonable recovery path if you make a call and env->can_call_into_js() is false? In other words is it reasonable for code to make calls in this situation and ignore the failure or is it a bug in the code? If it's a bug I'm wondering if we should call napi_fatal_error() ? |
It’s not a bug in the code, it’s something that an application should handle gracefully (by not making any more N-API calls). |
Right, this is why I believe we should properly inform the application by distinguishing cannot-call-into-JS-anymore with its own status, rather than returning RETURN_STATUS_IF_FALSE((env), \
(env)->last_exception.IsEmpty() && (env)->can_call_into_js(), \
napi_pending_exception); \ is a bug. @mhdawson presumably the addon could silently release whatever resources is holding. I don't believe we should call |
@gabrielschulhof, @addaleax got it. I agree a separate status is needed so that the application knows what to do along with additional documentation in the error handling section which explains this case and what you should do when you see it. From what I understand so far it does share some similarities with pending exceptions in that it's not necessarily a result of the specific call/parameters but instead the state of the runtime. For a pending exception there the case were we return an error, and we say that you may still need to make the call to check if there is a pending exception. From the doc:
Would the same apply to can_call_into_js ? ie if you get something other than napi_ok or the new exception for cannot call into js, you would need to have an API to check if that is the case? Or do we check it first so that regardless of what other error might be reported we'll report that you can't call into js if that is the case? |
In retrospect, I think that is a bug too. In many places we return a To avoid this pattern in the future we need a flavour of our
Currently we are wasting our awareness of the fact that an exception is pending by returning a status other than I don't believe we should introduce two instances of this pattern by making the case of being unable to run JS behave the same way, especially since the inability to run JS is not a state from which we can recover. There's no IMO the pattern we should promote is this: // No preamble
napi_status napi_do_something(napi_env env, ...) {
CHECK_ENV(env);
...
CHECK_TO_OBJECT(...);
...
RETURN_STATUS_IF_FALSE(..., napi_something_not_ok);
...
return napi_clear_last_error(env);
}
// With preamble
napi_status napi_do_something_with_preamble(napi_env env, ...) {
NAPI_PREAMBLE(env);
...
CHECK_MAYBE_EMPTY_WITH_PREAMBLE(...);
...
RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(..., napi_something_not_ok);
...
return GET_RETURN_STATUS(env);
} where in the former case, the last error is set from the status passed into the macro and the status is returned, and in the latter case the last error is set from the status passed into the macro and returned, but only if no exception was caught, otherwise
|
I think we specifically chose to make the pattern to only return pending exception if there was no other specific error and that is how it is documented up front. We might change that but we'd need to change the documentation as well and then we'd have the problem that sometimes you need to check and sometimes you don't |
To add to the discussion we had talked about wether to return the pending exception or the more other return code and chose the other return code as otherwise there would be no way to find out about the other error. For example if you can somehow clear the error and continue (however unlikely that is) how would you know that the call also failed because you passed in invalid parameters. |
One more question is we consider it a breaking change to reverse the earlier decision, ie give priority to pending_exception over other errors versus the original decision to do it the other way around? |
Ping @mhdawson @gabrielschulhof ... was this ever resolved? |
@gabrielschulhof I think we ended up agreeing to try to make the code more consistent with the original intention versus introducing the new status. Is that what you remember ? |
@jasnell I think the state wherein the native side has no ability to execute JS is a genuinely separate state from all others and therefore it warrants its own status. The problem is that there are places where we should be returning such a status code, but we're returning a different one. Since we're ABI-stable we can't change those places to return this status code. That's why I marked the issue as n-api-semver-major. |
@gabrielschulhof but I don't think we are going to make n-api-semver-major changes any time soon if at all, right? Therefore we should close as "won't do" or come up with a solution that is not n-api-semver-major. |
@mhdawson that's actually not a bad idea. The issue will remain tagged even if it is closed, and will not inflate the open issue count unnecessarily. |
Is there a way to check The only way I see to check is to make a bogus call that uses // If this is `napi_invalid_arg`, everything is okay, otherwise there's either an exception or `can_call_into_js` is `false`
napi_typeof(env, NULL, NULL) |
@kjvalencik I think you can do this:
|
Implemented in #47986. |
napi_call_function()
and other N-APIs that useNAPI_PREAMBLE()
returnnapi_pending_exception
whenenv->can_call_into_js()
is no longer true. We should distinguish between a pending exception and an inability to call into JS.Re: nodejs/node-addon-api#591
The text was updated successfully, but these errors were encountered: