diff options
author | Gabriel Schulhof <gabriel.schulhof@intel.com> | 2017-08-24 13:33:26 +0300 |
---|---|---|
committer | Gabriel Schulhof <gabriel.schulhof@intel.com> | 2017-08-25 12:02:55 +0300 |
commit | 7efb8f7619100973877c660d0ee527ea3d92de8d (patch) | |
tree | 7b7d9f319f907713d3fa22cfd3d304ebbeeaac63 /src | |
parent | 64f59be62fcf55e6d0e7019ee61c712196c6914f (diff) | |
download | android-node-v8-7efb8f7619100973877c660d0ee527ea3d92de8d.tar.gz android-node-v8-7efb8f7619100973877c660d0ee527ea3d92de8d.tar.bz2 android-node-v8-7efb8f7619100973877c660d0ee527ea3d92de8d.zip |
n-api: implement promise
Promise is implemented as a pair of objects. `napi_create_promise()`
returns both a JavaScript promise and a newly allocated "deferred" in
its out-params. The deferred is linked to the promise such that the
deferred can be passed to `napi_resolve_deferred()` or
`napi_reject_deferred()` to reject/resolve the promise.
`napi_is_promise()` can be used to check if a `napi_value` is a native
promise - that is, a promise created by the underlying engine, rather
than a pure JS implementation of a promise.
PR-URL: https://github.com/nodejs/node/pull/14365
Fixes: https://github.com/nodejs/abi-stable-node/issues/242
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/node_api.cc | 78 | ||||
-rw-r--r-- | src/node_api.h | 14 | ||||
-rw-r--r-- | src/node_api_types.h | 1 |
3 files changed, 93 insertions, 0 deletions
diff --git a/src/node_api.cc b/src/node_api.cc index bec98e07ce..7a2b5bc48e 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -218,6 +218,14 @@ V8EscapableHandleScopeFromJsEscapableHandleScope( static_assert(sizeof(v8::Local<v8::Value>) == sizeof(napi_value), "Cannot convert between v8::Local<v8::Value> and napi_value"); +napi_deferred JsDeferredFromV8Persistent(v8::Persistent<v8::Value>* local) { + return reinterpret_cast<napi_deferred>(local); +} + +v8::Persistent<v8::Value>* V8PersistentFromJsDeferred(napi_deferred local) { + return reinterpret_cast<v8::Persistent<v8::Value>*>(local); +} + napi_value JsValueFromV8LocalValue(v8::Local<v8::Value> local) { return reinterpret_cast<napi_value>(*local); } @@ -774,6 +782,33 @@ napi_status Unwrap(napi_env env, return napi_ok; } +napi_status ConcludeDeferred(napi_env env, + napi_deferred deferred, + napi_value result, + bool is_resolved) { + NAPI_PREAMBLE(env); + CHECK_ARG(env, result); + + v8::Local<v8::Context> context = env->isolate->GetCurrentContext(); + v8::Persistent<v8::Value>* deferred_ref = + V8PersistentFromJsDeferred(deferred); + v8::Local<v8::Value> v8_deferred = + v8::Local<v8::Value>::New(env->isolate, *deferred_ref); + + auto v8_resolver = v8::Local<v8::Promise::Resolver>::Cast(v8_deferred); + + v8::Maybe<bool> success = is_resolved ? + v8_resolver->Resolve(context, v8impl::V8LocalValueFromJsValue(result)) : + v8_resolver->Reject(context, v8impl::V8LocalValueFromJsValue(result)); + + deferred_ref->Reset(); + delete deferred_ref; + + RETURN_STATUS_IF_FALSE(env, success.FromMaybe(false), napi_generic_failure); + + return GET_RETURN_STATUS(env); +} + } // end of namespace v8impl // Intercepts the Node-V8 module registration callback. Converts parameters @@ -3332,3 +3367,46 @@ napi_status napi_cancel_async_work(napi_env env, napi_async_work work) { return napi_clear_last_error(env); } + +NAPI_EXTERN napi_status napi_create_promise(napi_env env, + napi_deferred* deferred, + napi_value* promise) { + NAPI_PREAMBLE(env); + CHECK_ARG(env, deferred); + CHECK_ARG(env, promise); + + auto maybe = v8::Promise::Resolver::New(env->isolate->GetCurrentContext()); + CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure); + + auto v8_resolver = maybe.ToLocalChecked(); + auto v8_deferred = new v8::Persistent<v8::Value>(); + v8_deferred->Reset(env->isolate, v8_resolver); + + *deferred = v8impl::JsDeferredFromV8Persistent(v8_deferred); + *promise = v8impl::JsValueFromV8LocalValue(v8_resolver->GetPromise()); + return GET_RETURN_STATUS(env); +} + +NAPI_EXTERN napi_status napi_resolve_deferred(napi_env env, + napi_deferred deferred, + napi_value resolution) { + return v8impl::ConcludeDeferred(env, deferred, resolution, true); +} + +NAPI_EXTERN napi_status napi_reject_deferred(napi_env env, + napi_deferred deferred, + napi_value resolution) { + return v8impl::ConcludeDeferred(env, deferred, resolution, false); +} + +NAPI_EXTERN napi_status napi_is_promise(napi_env env, + napi_value promise, + bool* is_promise) { + CHECK_ENV(env); + CHECK_ARG(env, promise); + CHECK_ARG(env, is_promise); + + *is_promise = v8impl::V8LocalValueFromJsValue(promise)->IsPromise(); + + return napi_clear_last_error(env); +} diff --git a/src/node_api.h b/src/node_api.h index e52e2016d7..6a4b294187 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -543,6 +543,20 @@ NAPI_EXTERN napi_status napi_get_node_version(napi_env env, const napi_node_version** version); +// Promises +NAPI_EXTERN napi_status napi_create_promise(napi_env env, + napi_deferred* deferred, + napi_value* promise); +NAPI_EXTERN napi_status napi_resolve_deferred(napi_env env, + napi_deferred deferred, + napi_value resolution); +NAPI_EXTERN napi_status napi_reject_deferred(napi_env env, + napi_deferred deferred, + napi_value rejection); +NAPI_EXTERN napi_status napi_is_promise(napi_env env, + napi_value promise, + bool* is_promise); + EXTERN_C_END #endif // SRC_NODE_API_H_ diff --git a/src/node_api_types.h b/src/node_api_types.h index 0bdc377c8f..ac8482bf9d 100644 --- a/src/node_api_types.h +++ b/src/node_api_types.h @@ -17,6 +17,7 @@ typedef struct napi_handle_scope__ *napi_handle_scope; typedef struct napi_escapable_handle_scope__ *napi_escapable_handle_scope; typedef struct napi_callback_info__ *napi_callback_info; typedef struct napi_async_work__ *napi_async_work; +typedef struct napi_deferred__ *napi_deferred; typedef enum { napi_default = 0, |