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::FunctionCallbackInfo;
|
||||||
using v8::Integer;
|
using v8::Integer;
|
||||||
using v8::Local;
|
using v8::Local;
|
||||||
|
using v8::Maybe;
|
||||||
using v8::Object;
|
using v8::Object;
|
||||||
using v8::Private;
|
using v8::Private;
|
||||||
using v8::Promise;
|
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,
|
void Initialize(Local<Object> target,
|
||||||
Local<Value> unused,
|
Local<Value> unused,
|
||||||
Local<Context> context) {
|
Local<Context> context) {
|
||||||
@ -192,6 +223,10 @@ void Initialize(Local<Object> target,
|
|||||||
env->SetMethod(target, "startSigintWatchdog", StartSigintWatchdog);
|
env->SetMethod(target, "startSigintWatchdog", StartSigintWatchdog);
|
||||||
env->SetMethod(target, "stopSigintWatchdog", StopSigintWatchdog);
|
env->SetMethod(target, "stopSigintWatchdog", StopSigintWatchdog);
|
||||||
env->SetMethod(target, "watchdogHasPendingSigint", WatchdogHasPendingSigint);
|
env->SetMethod(target, "watchdogHasPendingSigint", WatchdogHasPendingSigint);
|
||||||
|
|
||||||
|
env->SetMethod(target, "createPromise", CreatePromise);
|
||||||
|
env->SetMethod(target, "promiseResolve", PromiseResolve);
|
||||||
|
env->SetMethod(target, "promiseReject", PromiseReject);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace util
|
} // 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