diff options
author | Jason Ginchereau <jasongin@microsoft.com> | 2017-04-19 14:58:58 -0700 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2017-04-25 22:02:56 +0200 |
commit | b7a341d7e5868cd1279c33e9f62c388a1e886110 (patch) | |
tree | 2b06bae6d8cc0aec5b2b7db919eb32d3bc54ba3d /src | |
parent | 42dca99cd73eb26c24327e3c7e8162d150a91162 (diff) | |
download | android-node-v8-b7a341d7e5868cd1279c33e9f62c388a1e886110.tar.gz android-node-v8-b7a341d7e5868cd1279c33e9f62c388a1e886110.tar.bz2 android-node-v8-b7a341d7e5868cd1279c33e9f62c388a1e886110.zip |
n-api: Enable scope and ref APIs during exception
N-API is somewhat strict about blocking calls to many APIs while there
is a pending exception. The NAPI_PREAMBLE macro at the beginning of
many API implementations checks for a pending exception. However, a
subset of the APIs (which don't call back into JavaScript) still need
to work while in a pending-exception state. This changes the reference
APIs (equivalent to v8::Persistent) and handle scope APIs so that they
can be used for cleanup up while an exception is pending.
We may decide to similarly enable a few other APIs later, (which would
be a non-breaking change) but we know at least these are needed now
to unblock some specific scenarios.
Fixes: https://github.com/nodejs/abi-stable-node/issues/122
Fixes: https://github.com/nodejs/abi-stable-node/issues/228
PR-URL: https://github.com/nodejs/node/pull/12524
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/node_api.cc | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/src/node_api.cc b/src/node_api.cc index 5fdd879d6f..e1a5f1fdcb 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -2043,7 +2043,9 @@ napi_status napi_create_reference(napi_env env, napi_value value, uint32_t initial_refcount, napi_ref* result) { - NAPI_PREAMBLE(env); + // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw + // JS exceptions. + CHECK_ENV(env); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -2051,7 +2053,7 @@ napi_status napi_create_reference(napi_env env, env, v8impl::V8LocalValueFromJsValue(value), initial_refcount, false); *result = reinterpret_cast<napi_ref>(reference); - return GET_RETURN_STATUS(env); + return napi_clear_last_error(env); } // Deletes a reference. The referenced value is released, and may be GC'd unless @@ -2073,7 +2075,9 @@ napi_status napi_delete_reference(napi_env env, napi_ref ref) { // Calling this when the refcount is 0 and the object is unavailable // results in an error. napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) { - NAPI_PREAMBLE(env); + // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw + // JS exceptions. + CHECK_ENV(env); CHECK_ARG(env, ref); v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref); @@ -2083,7 +2087,7 @@ napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) { *result = count; } - return GET_RETURN_STATUS(env); + return napi_clear_last_error(env); } // Decrements the reference count, optionally returning the resulting count. If @@ -2091,7 +2095,9 @@ napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) { // time if there are no other references. Calling this when the refcount is // already 0 results in an error. napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result) { - NAPI_PREAMBLE(env); + // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw + // JS exceptions. + CHECK_ENV(env); CHECK_ARG(env, ref); v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref); @@ -2106,7 +2112,7 @@ napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result) { *result = count; } - return GET_RETURN_STATUS(env); + return napi_clear_last_error(env); } // Attempts to get a referenced value. If the reference is weak, the value might @@ -2115,59 +2121,71 @@ napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result) { napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value* result) { - NAPI_PREAMBLE(env); + // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw + // JS exceptions. + CHECK_ENV(env); CHECK_ARG(env, ref); CHECK_ARG(env, result); v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref); *result = v8impl::JsValueFromV8LocalValue(reference->Get()); - return GET_RETURN_STATUS(env); + return napi_clear_last_error(env); } napi_status napi_open_handle_scope(napi_env env, napi_handle_scope* result) { - NAPI_PREAMBLE(env); + // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw + // JS exceptions. + CHECK_ENV(env); CHECK_ARG(env, result); *result = v8impl::JsHandleScopeFromV8HandleScope( new v8impl::HandleScopeWrapper(env->isolate)); - return GET_RETURN_STATUS(env); + return napi_clear_last_error(env); } napi_status napi_close_handle_scope(napi_env env, napi_handle_scope scope) { - NAPI_PREAMBLE(env); + // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw + // JS exceptions. + CHECK_ENV(env); CHECK_ARG(env, scope); delete v8impl::V8HandleScopeFromJsHandleScope(scope); - return GET_RETURN_STATUS(env); + return napi_clear_last_error(env); } napi_status napi_open_escapable_handle_scope( napi_env env, napi_escapable_handle_scope* result) { - NAPI_PREAMBLE(env); + // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw + // JS exceptions. + CHECK_ENV(env); CHECK_ARG(env, result); *result = v8impl::JsEscapableHandleScopeFromV8EscapableHandleScope( new v8impl::EscapableHandleScopeWrapper(env->isolate)); - return GET_RETURN_STATUS(env); + return napi_clear_last_error(env); } napi_status napi_close_escapable_handle_scope( napi_env env, napi_escapable_handle_scope scope) { - NAPI_PREAMBLE(env); + // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw + // JS exceptions. + CHECK_ENV(env); CHECK_ARG(env, scope); delete v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope); - return GET_RETURN_STATUS(env); + return napi_clear_last_error(env); } napi_status napi_escape_handle(napi_env env, napi_escapable_handle_scope scope, napi_value escapee, napi_value* result) { - NAPI_PREAMBLE(env); + // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw + // JS exceptions. + CHECK_ENV(env); CHECK_ARG(env, scope); CHECK_ARG(env, escapee); CHECK_ARG(env, result); @@ -2176,7 +2194,7 @@ napi_status napi_escape_handle(napi_env env, v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope); *result = v8impl::JsValueFromV8LocalValue( s->Escape(v8impl::V8LocalValueFromJsValue(escapee))); - return GET_RETURN_STATUS(env); + return napi_clear_last_error(env); } napi_status napi_new_instance(napi_env env, @@ -2386,7 +2404,6 @@ napi_status napi_create_buffer(napi_env env, void** data, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(env, data); CHECK_ARG(env, result); auto maybe = node::Buffer::New(env->isolate, length); @@ -2396,7 +2413,10 @@ napi_status napi_create_buffer(napi_env env, v8::Local<v8::Object> buffer = maybe.ToLocalChecked(); *result = v8impl::JsValueFromV8LocalValue(buffer); - *data = node::Buffer::Data(buffer); + + if (data != nullptr) { + *data = node::Buffer::Data(buffer); + } return GET_RETURN_STATUS(env); } |