diff --git a/src/node_util.cc b/src/node_util.cc index 5f3de643d4c2f3..3424739cc96688 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -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& args) { } +void CreatePromise(const FunctionCallbackInfo& args) { + Local 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& args) { + Local context = args.GetIsolate()->GetCurrentContext(); + Local promise = args[0]; + CHECK(promise->IsPromise()); + if (promise.As()->State() != Promise::kPending) return; + Local resolver = promise.As(); // sic + Maybe ret = resolver->Resolve(context, args[1]); + args.GetReturnValue().Set(ret.FromMaybe(false)); +} + + +void PromiseReject(const FunctionCallbackInfo& args) { + Local context = args.GetIsolate()->GetCurrentContext(); + Local promise = args[0]; + CHECK(promise->IsPromise()); + if (promise.As()->State() != Promise::kPending) return; + Local resolver = promise.As(); // sic + Maybe ret = resolver->Reject(context, args[1]); + args.GetReturnValue().Set(ret.FromMaybe(false)); +} + + void Initialize(Local target, Local unused, Local context) { @@ -192,6 +223,10 @@ void Initialize(Local 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 diff --git a/test/parallel/test-promise-internal-creation.js b/test/parallel/test-promise-internal-creation.js new file mode 100644 index 00000000000000..7142c872d9452e --- /dev/null +++ b/test/parallel/test-promise-internal-creation.js @@ -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 { }'); + 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(' 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(' Error: foobar')); + promiseResolve(promise, 42); + assert(inspect(promise).includes(' Error: foobar')); + promise.catch(common.mustCall((value) => { + assert.strictEqual(value, error); + })); +}