GeezerVison is showing github.com — domain: fix vm promise tracking while keeping isolation · nodejs/node@6bcd40d
File tree
Expand file treeCollapse file tree
Open diff view settings
Expand file treeCollapse file tree
Open diff view settings
Collapse file
Copy file name to clipboardExpand all lines: lib/domain.js +7Lines changed: 7 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -39,6 +39,7 @@ const { |
39 | 39 | Promise, |
40 | 40 | ReflectApply, |
41 | 41 | SafeMap, |
| 42 | + SafeWeakMap, |
42 | 43 | Symbol, |
43 | 44 | } = primordials; |
44 | 45 |
|
@@ -69,6 +70,7 @@ ObjectDefineProperty(process, 'domain', { |
69 | 70 | } |
70 | 71 | }); |
71 | 72 |
|
| 73 | +const vmPromises = new SafeWeakMap(); |
72 | 74 | const pairing = new SafeMap(); |
73 | 75 | const asyncHook = createHook({ |
74 | 76 | init(asyncId, type, triggerAsyncId, resource) { |
@@ -85,6 +87,11 @@ const asyncHook = createHook({ |
85 | 87 | value: process.domain, |
86 | 88 | writable: true |
87 | 89 | }); |
| 90 | + // Because promises from other contexts don't get a domain field, |
| 91 | + // the domain needs to be held alive another way. Stuffing it in a |
| 92 | + // weakmap connected to the promise lifetime can fix that. |
| 93 | + } else { |
| 94 | + vmPromises.set(resource, process.domain); |
88 | 95 | } |
89 | 96 | } |
90 | 97 | }, |
|
Collapse file
Copy file name to clipboard +28Lines changed: 28 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +'use strict'; |
| 2 | + |
| 3 | +const common = require('../common'); |
| 4 | +const assert = require('assert'); |
| 5 | +const domain = require('domain'); |
| 6 | +const vm = require('vm'); |
| 7 | + |
| 8 | +// A promise created in a VM should not include a domain field but |
| 9 | +// domains should still be able to propagate through them. |
| 10 | +// |
| 11 | +// See; https://github.com/nodejs/node/issues/40999 |
| 12 | + |
| 13 | +const context = vm.createContext({}); |
| 14 | + |
| 15 | +function run(code) { |
| 16 | + const d = domain.createDomain(); |
| 17 | + d.run(common.mustCall(() => { |
| 18 | + const p = vm.runInContext(code, context)(); |
| 19 | + assert.strictEqual(p.domain, undefined); |
| 20 | + p.then(common.mustCall(() => { |
| 21 | + assert.strictEqual(process.domain, d); |
| 22 | + })); |
| 23 | + })); |
| 24 | +} |
| 25 | + |
| 26 | +for (let i = 0; i < 1000; i++) { |
| 27 | + run('async () => null'); |
| 28 | +} |