Skip to content

Commit

Permalink
domain: fix vm promise tracking while keeping isolation
Browse files Browse the repository at this point in the history
PR-URL: #43556
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
  • Loading branch information
Qard authored and danielleadams committed Jul 26, 2022
1 parent e4aa50f commit 6bcd40d
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 0 deletions.
7 changes: 7 additions & 0 deletions lib/domain.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const {
Promise,
ReflectApply,
SafeMap,
SafeWeakMap,
Symbol,
} = primordials;

Expand Down Expand Up @@ -69,6 +70,7 @@ ObjectDefineProperty(process, 'domain', {
}
});

const vmPromises = new SafeWeakMap();
const pairing = new SafeMap();
const asyncHook = createHook({
init(asyncId, type, triggerAsyncId, resource) {
Expand All @@ -85,6 +87,11 @@ const asyncHook = createHook({
value: process.domain,
writable: true
});
// Because promises from other contexts don't get a domain field,
// the domain needs to be held alive another way. Stuffing it in a
// weakmap connected to the promise lifetime can fix that.
} else {
vmPromises.set(resource, process.domain);
}
}
},
Expand Down
28 changes: 28 additions & 0 deletions test/parallel/test-domain-vm-promise-isolation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const domain = require('domain');
const vm = require('vm');

// A promise created in a VM should not include a domain field but
// domains should still be able to propagate through them.
//
// See; https://github.com/nodejs/node/issues/40999

const context = vm.createContext({});

function run(code) {
const d = domain.createDomain();
d.run(common.mustCall(() => {
const p = vm.runInContext(code, context)();
assert.strictEqual(p.domain, undefined);
p.then(common.mustCall(() => {
assert.strictEqual(process.domain, d);
}));
}));
}

for (let i = 0; i < 1000; i++) {
run('async () => null');
}

0 comments on commit 6bcd40d

Please # to comment.