src: do not add .domain to promises in VM contexts
The promises are still tracked, and their handlers will still execute in the correct domain. The creation domain is simply hidden. PR-URL: https://github.com/nodejs/node/pull/15695 Fixes: https://github.com/nodejs/node/issues/15673 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
parent
a3cd8ed168
commit
806857712f
@ -1,6 +1,12 @@
|
|||||||
# Domain
|
# Domain
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
changes:
|
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
|
- version: v8.0.0
|
||||||
pr-url: https://github.com/nodejs/node/pull/12489
|
pr-url: https://github.com/nodejs/node/pull/12489
|
||||||
description: Handlers for `Promise`s are now invoked in the domain in which
|
description: Handlers for `Promise`s are now invoked in the domain in which
|
||||||
|
@ -93,6 +93,7 @@ class ModuleWrap;
|
|||||||
V(npn_buffer_private_symbol, "node:npnBuffer") \
|
V(npn_buffer_private_symbol, "node:npnBuffer") \
|
||||||
V(processed_private_symbol, "node:processed") \
|
V(processed_private_symbol, "node:processed") \
|
||||||
V(selected_npn_buffer_private_symbol, "node:selectedNpnBuffer") \
|
V(selected_npn_buffer_private_symbol, "node:selectedNpnBuffer") \
|
||||||
|
V(domain_private_symbol, "node:domain") \
|
||||||
|
|
||||||
// Strings are per-isolate primitives but Environment proxies them
|
// Strings are per-isolate primitives but Environment proxies them
|
||||||
// for the sake of convenience. Strings should be ASCII-only.
|
// for the sake of convenience. Strings should be ASCII-only.
|
||||||
|
29
src/node.cc
29
src/node.cc
@ -1156,8 +1156,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) {
|
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()) {
|
if (domain_v->IsObject()) {
|
||||||
Local<Object> domain = domain_v.As<Object>();
|
Local<Object> domain = domain_v.As<Object>();
|
||||||
Local<Value> enter_v = domain->Get(env->enter_string());
|
Local<Value> enter_v = domain->Get(env->enter_string());
|
||||||
@ -1172,7 +1183,7 @@ void DomainEnter(Environment* env, Local<Object> object) {
|
|||||||
|
|
||||||
|
|
||||||
void DomainExit(Environment* env, v8::Local<v8::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()) {
|
if (domain_v->IsObject()) {
|
||||||
Local<Object> domain = domain_v.As<Object>();
|
Local<Object> domain = domain_v.As<Object>();
|
||||||
Local<Value> exit_v = domain->Get(env->exit_string());
|
Local<Value> exit_v = domain->Get(env->exit_string());
|
||||||
@ -1194,10 +1205,16 @@ void DomainPromiseHook(PromiseHookType type,
|
|||||||
Local<Context> context = env->context();
|
Local<Context> context = env->context();
|
||||||
|
|
||||||
if (type == PromiseHookType::kInit && env->in_domain()) {
|
if (type == PromiseHookType::kInit && env->in_domain()) {
|
||||||
promise->Set(context,
|
Local<Value> domain_obj =
|
||||||
env->domain_string(),
|
env->domain_array()->Get(context, 0).ToLocalChecked();
|
||||||
env->domain_array()->Get(context,
|
if (promise->CreationContext() == context) {
|
||||||
0).ToLocalChecked()).FromJust();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,9 +31,13 @@ common.crashOnUnhandledRejection();
|
|||||||
const d = domain.create();
|
const d = domain.create();
|
||||||
|
|
||||||
d.run(common.mustCall(() => {
|
d.run(common.mustCall(() => {
|
||||||
vm.runInNewContext(`Promise.resolve().then(common.mustCall(() => {
|
vm.runInNewContext(`
|
||||||
assert.strictEqual(process.domain, d);
|
const promise = Promise.resolve();
|
||||||
}));`, { common, assert, process, d });
|
assert.strictEqual(promise.domain, undefined);
|
||||||
|
promise.then(common.mustCall(() => {
|
||||||
|
assert.strictEqual(process.domain, d);
|
||||||
|
}));
|
||||||
|
`, { common, assert, process, d });
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user