summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabriel Schulhof <gabriel.schulhof@intel.com>2017-08-24 13:33:26 +0300
committerGabriel Schulhof <gabriel.schulhof@intel.com>2017-08-25 12:02:55 +0300
commit7efb8f7619100973877c660d0ee527ea3d92de8d (patch)
tree7b7d9f319f907713d3fa22cfd3d304ebbeeaac63 /src
parent64f59be62fcf55e6d0e7019ee61c712196c6914f (diff)
downloadandroid-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.cc78
-rw-r--r--src/node_api.h14
-rw-r--r--src/node_api_types.h1
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,