util: add internal bindings for promise handling
Add methods for creating, resolving and rejecting promises using the V8 C++ API that does not require creation of extra `resolve` and `reject` functions to `process.binding('util')`. PR-URL: https://github.com/nodejs/node/pull/12442 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Myles Borins <myles.borins@gmail.com> Reviewed-By: Evan Lucas <evanlucas@me.com> Reviewed-By: William Kapke <william.kapke@gmail.com> Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Teddy Katz <teddy.katz@gmail.com>
This commit is contained in:
parent
f72376d323
commit
059f296050
@ -12,6 +12,7 @@ using v8::Context;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Integer;
|
||||
using v8::Local;
|
||||
using v8::Maybe;
|
||||
using v8::Object;
|
||||
using v8::Private;
|
||||
using v8::Promise;
|
||||
@ -147,6 +148,36 @@ void WatchdogHasPendingSigint(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
|
||||
|
||||
void CreatePromise(const FunctionCallbackInfo<Value>& args) {
|
||||
Local<Context> context = args.GetIsolate()->GetCurrentContext();
|
||||
auto maybe_resolver = Promise::Resolver::New(context);
|
||||
if (!maybe_resolver.IsEmpty())
|
||||
args.GetReturnValue().Set(maybe_resolver.ToLocalChecked());
|
||||
}
|
||||
|
||||
|
||||
void PromiseResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
Local<Context> context = args.GetIsolate()->GetCurrentContext();
|
||||
Local<Value> promise = args[0];
|
||||
CHECK(promise->IsPromise());
|
||||
if (promise.As<Promise>()->State() != Promise::kPending) return;
|
||||
Local<Promise::Resolver> resolver = promise.As<Promise::Resolver>(); // sic
|
||||
Maybe<bool> ret = resolver->Resolve(context, args[1]);
|
||||
args.GetReturnValue().Set(ret.FromMaybe(false));
|
||||
}
|
||||
|
||||
|
||||
void PromiseReject(const FunctionCallbackInfo<Value>& args) {
|
||||
Local<Context> context = args.GetIsolate()->GetCurrentContext();
|
||||
Local<Value> promise = args[0];
|
||||
CHECK(promise->IsPromise());
|
||||
if (promise.As<Promise>()->State() != Promise::kPending) return;
|
||||
Local<Promise::Resolver> resolver = promise.As<Promise::Resolver>(); // sic
|
||||
Maybe<bool> ret = resolver->Reject(context, args[1]);
|
||||
args.GetReturnValue().Set(ret.FromMaybe(false));
|
||||
}
|
||||
|
||||
|
||||
void Initialize(Local<Object> target,
|
||||
Local<Value> unused,
|
||||
Local<Context> context) {
|
||||
@ -192,6 +223,10 @@ void Initialize(Local<Object> target,
|
||||
env->SetMethod(target, "startSigintWatchdog", StartSigintWatchdog);
|
||||
env->SetMethod(target, "stopSigintWatchdog", StopSigintWatchdog);
|
||||
env->SetMethod(target, "watchdogHasPendingSigint", WatchdogHasPendingSigint);
|
||||
|
||||
env->SetMethod(target, "createPromise", CreatePromise);
|
||||
env->SetMethod(target, "promiseResolve", PromiseResolve);
|
||||
env->SetMethod(target, "promiseReject", PromiseReject);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
41
test/parallel/test-promise-internal-creation.js
Normal file
41
test/parallel/test-promise-internal-creation.js
Normal file
@ -0,0 +1,41 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const {
|
||||
createPromise, promiseResolve, promiseReject
|
||||
} = process.binding('util');
|
||||
const { inspect } = require('util');
|
||||
|
||||
common.crashOnUnhandledRejection();
|
||||
|
||||
{
|
||||
const promise = createPromise();
|
||||
assert.strictEqual(inspect(promise), 'Promise { <pending> }');
|
||||
promiseResolve(promise, 42);
|
||||
assert.strictEqual(inspect(promise), 'Promise { 42 }');
|
||||
promise.then(common.mustCall((value) => {
|
||||
assert.strictEqual(value, 42);
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
const promise = createPromise();
|
||||
const error = new Error('foobar');
|
||||
promiseReject(promise, error);
|
||||
assert(inspect(promise).includes('<rejected> Error: foobar'));
|
||||
promise.catch(common.mustCall((value) => {
|
||||
assert.strictEqual(value, error);
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
const promise = createPromise();
|
||||
const error = new Error('foobar');
|
||||
promiseReject(promise, error);
|
||||
assert(inspect(promise).includes('<rejected> Error: foobar'));
|
||||
promiseResolve(promise, 42);
|
||||
assert(inspect(promise).includes('<rejected> Error: foobar'));
|
||||
promise.catch(common.mustCall((value) => {
|
||||
assert.strictEqual(value, error);
|
||||
}));
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user