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.

PR-URL: nodejs/node#15695
Fixes: nodejs/node#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 addaleax committed Oct 11, 2017
1 parent 0c76f93 commit 8d727f1
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 @@ -1167,8 +1167,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();
}


void 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>();
Local<Value> enter_v = domain->Get(env->enter_string());
Expand All @@ -1183,7 +1194,7 @@ void DomainEnter(Environment* env, Local<Object> object) {


void 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>();
Local<Value> exit_v = domain->Get(env->exit_string());
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 8d727f1

Please sign in to comment.