node/test/parallel/test-vm-script-after-evaluate.js

67 lines
2.1 KiB
JavaScript

'use strict';
// https://github.com/nodejs/node/issues/59541
//
// Promises created in a context using microtaskMode: "aferEvaluate" (meaning
// it has its own microtask queue), when resolved in the surrounding context,
// will schedule a task back onto the inner context queue. This test checks that
// the async execution progresses normally.
const common = require('../common');
const vm = require('vm');
const microtaskMode = 'afterEvaluate';
(async () => {
const mustNotCall1 = common.mustNotCall();
await vm.runInNewContext(
`Promise.resolve()`,
{}, { microtaskMode });
// Expected behavior: resolving an promise created in the inner context, from
// the outer context results in the execution flow falling through, unless the
// inner context microtask queue is manually drained, which we don't do here.
mustNotCall1();
})().then(common.mustNotCall());
(async () => {
const mustCall1 = common.mustCall();
const mustCall2 = common.mustCall();
const mustCall3 = common.mustCall();
// Create a new context.
const context = vm.createContext({}, { microtaskMode });
setImmediate(() => {
// This will drain the context microtask queue, after the `await` statement
// below, and allow the promise from the inner context, created below, to be
// resolved in the outer context.
vm.runInContext('', context);
mustCall2();
});
const inner_promise = vm.runInContext(
`Promise.resolve()`,
context);
mustCall1();
await inner_promise;
mustCall3();
})().then(common.mustCall());
{
const mustNotCall1 = common.mustNotCall();
const mustCall1 = common.mustCall();
const context = vm.createContext({ setImmediate, mustNotCall1 }, { microtaskMode });
// setImmediate() will be run after runInContext() returns, and since the
// anonymous function passed to `then` is defined in the inner context, the
// thenable job task will be enqueued on the inner context microtask queue,
// but at this point, it will not be drained automatically.
vm.runInContext(`new Promise(setImmediate).then(() => mustNotCall1())`, context);
mustCall1();
}