Skip to content

Commit

Permalink
src: do not add .domain to promises in VM contexts
Browse files Browse the repository at this point in the history
The promises are still tracked, and their handlers will still execute in
the correct domain. The creation domain is simply hidden.

Backport-PR-URL: #16074
PR-URL: #15695
Fixes: #15673
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
  • Loading branch information
TimothyGu authored and evanlucas committed Oct 23, 2017
1 parent b1a68f5 commit 0b04869
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 9 deletions.
6 changes: 6 additions & 0 deletions doc/api/domain.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Domain
<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/REPLACEME
description: Any `Promise`s created in VM contexts no longer have a
`.domain` property. Their handlers are still executed in the
proper domain, however, and `Promise`s created in the main
context still possess a `.domain` property.
- version: v8.0.0
pr-url: https://github.com/nodejs/node/pull/12489
description: Handlers for `Promise`s are now invoked in the domain in which
Expand Down
1 change: 1 addition & 0 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class ModuleWrap;
V(npn_buffer_private_symbol, "node:npnBuffer") \
V(processed_private_symbol, "node:processed") \
V(selected_npn_buffer_private_symbol, "node:selectedNpnBuffer") \
V(domain_private_symbol, "node:domain") \

// Strings are per-isolate primitives but Environment proxies them
// for the sake of convenience. Strings should be ASCII-only.
Expand Down
29 changes: 23 additions & 6 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1161,8 +1161,19 @@ bool ShouldAbortOnUncaughtException(Isolate* isolate) {
}


Local<Value> GetDomainProperty(Environment* env, Local<Object> object) {
Local<Value> domain_v =
object->GetPrivate(env->context(), env->domain_private_symbol())
.ToLocalChecked();
if (domain_v->IsObject()) {
return domain_v;
}
return object->Get(env->context(), env->domain_string()).ToLocalChecked();
}


bool DomainEnter(Environment* env, Local<Object> object) {
Local<Value> domain_v = object->Get(env->domain_string());
Local<Value> domain_v = GetDomainProperty(env, object);
if (domain_v->IsObject()) {
Local<Object> domain = domain_v.As<Object>();
if (domain->Get(env->disposed_string())->IsTrue())
Expand All @@ -1180,7 +1191,7 @@ bool DomainEnter(Environment* env, Local<Object> object) {


bool DomainExit(Environment* env, v8::Local<v8::Object> object) {
Local<Value> domain_v = object->Get(env->domain_string());
Local<Value> domain_v = GetDomainProperty(env, object);
if (domain_v->IsObject()) {
Local<Object> domain = domain_v.As<Object>();
if (domain->Get(env->disposed_string())->IsTrue())
Expand All @@ -1205,10 +1216,16 @@ void DomainPromiseHook(PromiseHookType type,
Local<Context> context = env->context();

if (type == PromiseHookType::kInit && env->in_domain()) {
promise->Set(context,
env->domain_string(),
env->domain_array()->Get(context,
0).ToLocalChecked()).FromJust();
Local<Value> domain_obj =
env->domain_array()->Get(context, 0).ToLocalChecked();
if (promise->CreationContext() == context) {
promise->Set(context, env->domain_string(), domain_obj).FromJust();
} else {
// Do not expose object from another context publicly in promises created
// in non-main contexts.
promise->SetPrivate(context, env->domain_private_symbol(), domain_obj)
.FromJust();
}
return;
}

Expand Down
10 changes: 7 additions & 3 deletions test/parallel/test-domain-promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@ common.crashOnUnhandledRejection();
const d = domain.create();

d.run(common.mustCall(() => {
vm.runInNewContext(`Promise.resolve().then(common.mustCall(() => {
assert.strictEqual(process.domain, d);
}));`, { common, assert, process, d });
vm.runInNewContext(`
const promise = Promise.resolve();
assert.strictEqual(promise.domain, undefined);
promise.then(common.mustCall(() => {
assert.strictEqual(process.domain, d);
}));
`, { common, assert, process, d });
}));
}

Expand Down

0 comments on commit 0b04869

Please sign in to comment.