From d0e4911b65d6a9163000cb1d7bafc6288b69f6d9 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 18 Apr 2017 18:02:27 +0200 Subject: [PATCH] domain: support promises Fixes: https://github.com/nodejs/node/issues/10724 --- src/node.cc | 53 ++++++++++++++++++++++++++++ test/parallel/test-domain-promise.js | 12 +++++++ 2 files changed, 65 insertions(+) create mode 100644 test/parallel/test-domain-promise.js diff --git a/src/node.cc b/src/node.cc index 20eea1769aba10..daf37da83a9e6c 100644 --- a/src/node.cc +++ b/src/node.cc @@ -142,6 +142,7 @@ using v8::Number; using v8::Object; using v8::ObjectTemplate; using v8::Promise; +using v8::PromiseHookType; using v8::PromiseRejectMessage; using v8::PropertyCallbackInfo; using v8::ScriptOrigin; @@ -1113,6 +1114,56 @@ bool ShouldAbortOnUncaughtException(Isolate* isolate) { } +void PromiseHook(PromiseHookType type, + Local promise, + Local parent) { + Environment* env = Environment::GetCurrent(Isolate::GetCurrent()); + Local context = env->context(); + + if (type == PromiseHookType::kResolve) return; + if (type == PromiseHookType::kInit && env->in_domain()) { + promise->Set(context, + env->domain_string(), + env->domain_array()->Get(0)).FromJust(); + return; + } + + // Loosely based on node::MakeCallback(). + Local domain_v = + promise->Get(context, env->domain_string()).ToLocalChecked(); + if (!domain_v->IsObject()) + return; + + Local domain = domain_v.As(); + if (domain->Get(context, env->disposed_string()) + .ToLocalChecked()->IsTrue()) { + return; + } + + if (type == PromiseHookType::kBefore) { + Local enter_v = + domain->Get(context, env->enter_string()).ToLocalChecked(); + if (enter_v->IsFunction()) { + if (enter_v.As()->Call(context, domain, 0, nullptr).IsEmpty()) { + FatalError("node::PromiseHook", + "domain enter callback threw, please report this " + "as a bug in Node.js"); + } + } + } else { + Local exit_v = + domain->Get(context, env->exit_string()).ToLocalChecked(); + if (exit_v->IsFunction()) { + if (exit_v.As()->Call(context, domain, 0, nullptr).IsEmpty()) { + FatalError("node::MakeCallback", + "domain exit callback threw, please report this " + "as a bug in Node.js"); + } + } + } +} + + void SetupDomainUse(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -1152,6 +1203,8 @@ void SetupDomainUse(const FunctionCallbackInfo& args) { Local array_buffer = ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count); + env->isolate()->SetPromiseHook(PromiseHook); + args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count)); } diff --git a/test/parallel/test-domain-promise.js b/test/parallel/test-domain-promise.js new file mode 100644 index 00000000000000..e0d5ca4b0dd9e4 --- /dev/null +++ b/test/parallel/test-domain-promise.js @@ -0,0 +1,12 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const domain = require('domain'); + +const d = domain.create(); + +d.run(common.mustCall(() => { + Promise.resolve().then(common.mustCall(() => { + assert.strictEqual(process.domain, d); + })); +}));