Skip to content

Commit a482e51

Browse files
committed
fixup! vm: make vm.Module.evaluate() conditionally synchronous
1 parent 4ba35d8 commit a482e51

File tree

4 files changed

+16
-7
lines changed

4 files changed

+16
-7
lines changed

doc/api/vm.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -642,10 +642,12 @@ the specification of [Evaluate() of a Synthetic Module Record][]:
642642
1. If the `evaluateCallback` passed to its constructor throws an exception synchronously, `evaluate()` returns
643643
a promise that will be synchronously rejected with that exception.
644644
2. If the `evaluateCallback` does not throw an exception, `evaluate()` returns a promise that will be
645-
synchronously resolved to `undefined`. This is the case even if the `evaluateCallback` is an
646-
asynchronous function, any asynchronous operations it performs will only have effect after
647-
`evaluate()` has returned. If an `evaluateCallback` rejects asynchronously, that rejection will be
648-
not reflected in the promise returned by `evaluate()`.
645+
synchronously resolved to `undefined`.
646+
647+
The `evaluateCallback` of a `vm.SyntheticModule` is executed synchronously within the `evaluate()` call, and its
648+
return value is discarded. This means if `evaluateCallback` is an asynchronous function, the promise returned by
649+
`evaluate()` will not reflect its asynchronous behavior, and any rejections from an asynchronous
650+
`evaluateCallback` will be lost.
649651

650652
`evaluate()` could also be called again after the module has already been evaluated, in which case:
651653

test/parallel/test-vm-module-evaluate-source-text-module.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ common.allowGlobals(globalThis.callCount);
2626
const promise = mod.evaluate();
2727
assert.strictEqual(globalThis.callCount.syncError, 1);
2828
assert.match(inspect(promise), /rejected/);
29+
assert(mod.error, 'Expected mod.error to be set');
30+
assert.strictEqual(mod.error.message, 'synchronous source text module');
2931

3032
promise.catch(common.mustCall((err) => {
31-
assert.strictEqual(err.message, 'synchronous source text module');
33+
assert.strictEqual(err, mod.error);
3234
// Calling evaluate() again results in the same rejection synchronously.
3335
const promise2 = mod.evaluate();
3436
assert.match(inspect(promise2), /rejected/);
@@ -115,6 +117,7 @@ common.allowGlobals(globalThis.callCount);
115117
assert.match(inspect(promise), /<pending>/);
116118
// Accessing the namespace before the promise is fulfilled throws ReferenceError.
117119
assert.throws(() => mod.namespace.a, { name: 'ReferenceError' });
120+
assert.strictEqual(globalThis.callCount.asyncEvaluation, 1);
118121
promise.then(common.mustCall((value) => {
119122
assert.strictEqual(value, undefined);
120123
assert.strictEqual(globalThis.callCount.asyncEvaluation, 1);
@@ -147,6 +150,7 @@ common.allowGlobals(globalThis.callCount);
147150
// Accessing the namespace before the promise is fulfilled throws ReferenceError.
148151
assert.throws(() => mod.namespace.a, { name: 'ReferenceError' });
149152
promise.catch(common.mustCall((err) => {
153+
assert.strictEqual(err, mod.error);
150154
assert.strictEqual(err.message, 'asynchronous source text module');
151155
assert.strictEqual(globalThis.callCount.asyncRejection, 1);
152156

test/parallel/test-vm-module-evaluate-synthethic-module-rejection.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ process.on('unhandledRejection', common.mustCall((err) => {
2222
}));
2323

2424
const mod = new vm.SyntheticModule(['a'], common.mustCall(async () => {
25-
await Promise.reject(new Error('asynchronous source text module'));
25+
throw new Error('asynchronous source text module');
2626
}));
2727

2828
const promise = mod.evaluate();

test/parallel/test-vm-module-evaluate-synthethic-module.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,11 @@ const vm = require('vm');
6666
}));
6767
const promise = mod.evaluate();
6868
assert.match(inspect(promise), /rejected/);
69+
assert(mod.error, 'Expected mod.error to be set');
70+
assert.strictEqual(mod.error.message, 'synchronous synthethic module');
71+
6972
promise.catch(common.mustCall((err) => {
70-
assert.strictEqual(err.message, 'synchronous synthethic module');
73+
assert.strictEqual(err, mod.error);
7174

7275
// Calling evaluate() again results in a promise _synchronously_ rejected
7376
// with the same reason.

0 commit comments

Comments
 (0)