fix: microtasks policy in CreateEnvironment (#29531)
* fix: microtasks policy in CreateEnvironment Microtasks policy should not be updated for the renderer because `NodeBindings::CreateEnvironment` might be entered with or without `UvRunOnce()` on stack. One of the examples of such calls is `window.open()` which is possible to invoke while `uv_run()` is still running (e.g. with `setImmediate()`). All in all, it doesn't matter that much which policy we use since `v8::MicrotasksScope` has a check for the policy in its destructor and no commits will be made if the policy is `kExplicit`. It is important, however, to not change the policy in the middle of `UvRunOnce()` so we should respect whatever we currently have and move on. Fix: #29463 * Move test to a better place * Update spec-main/fixtures/crash-cases/setimmediate-window-open-crash/index.html Co-authored-by: Jeremy Rose <nornagon@nornagon.net> * Update spec-main/fixtures/crash-cases/setimmediate-window-open-crash/index.html Co-authored-by: Jeremy Rose <nornagon@nornagon.net> * simplify crash-case * comment * fix comment Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Co-authored-by: Jeremy Rose <nornagon@nornagon.net> Co-authored-by: Fedor Indutny <indutny@signal.org>
This commit is contained in:
parent
cfc846a337
commit
d4a1b41129
3 changed files with 49 additions and 3 deletions
|
@ -482,9 +482,13 @@ node::Environment* NodeBindings::CreateEnvironment(
|
||||||
// Node.js requires that microtask checkpoints be explicitly invoked.
|
// Node.js requires that microtask checkpoints be explicitly invoked.
|
||||||
is.policy = v8::MicrotasksPolicy::kExplicit;
|
is.policy = v8::MicrotasksPolicy::kExplicit;
|
||||||
} else {
|
} else {
|
||||||
// Match Blink's behavior by allowing microtasks invocation to be controlled
|
// Blink expects the microtasks policy to be kScoped, but Node.js expects it
|
||||||
// by MicrotasksScope objects.
|
// to be kExplicit. In the renderer, there can be many contexts within the
|
||||||
is.policy = v8::MicrotasksPolicy::kScoped;
|
// same isolate, so we don't want to change the existing policy here, which
|
||||||
|
// could be either kExplicit or kScoped depending on whether we're executing
|
||||||
|
// from within a Node.js or a Blink entrypoint. Instead, the policy is
|
||||||
|
// toggled to kExplicit when entering Node.js through UvRunOnce.
|
||||||
|
is.policy = context->GetIsolate()->GetMicrotasksPolicy();
|
||||||
|
|
||||||
// We do not want to use Node.js' message listener as it interferes with
|
// We do not want to use Node.js' message listener as it interferes with
|
||||||
// Blink's.
|
// Blink's.
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
// `setImmediate` schedules a function to be run on the next UV tick, which
|
||||||
|
// ensures that `window.open` is run from `UvRunOnce()`.
|
||||||
|
setImmediate(async () => {
|
||||||
|
if (!location.hash) {
|
||||||
|
const p = new Promise(resolve => {
|
||||||
|
window.addEventListener('message', resolve, { once: true });
|
||||||
|
});
|
||||||
|
window.open('#foo', '', 'nodeIntegration=no,show=no');
|
||||||
|
const e = await p;
|
||||||
|
|
||||||
|
window.close();
|
||||||
|
} else {
|
||||||
|
window.opener.postMessage('foo', '*');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,21 @@
|
||||||
|
const { app, BrowserWindow } = require('electron');
|
||||||
|
|
||||||
|
function createWindow () {
|
||||||
|
const mainWindow = new BrowserWindow({
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
contextIsolation: false,
|
||||||
|
nativeWindowOpen: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mainWindow.on('close', () => {
|
||||||
|
app.quit();
|
||||||
|
});
|
||||||
|
|
||||||
|
mainWindow.loadFile('index.html');
|
||||||
|
}
|
||||||
|
|
||||||
|
app.whenReady().then(() => {
|
||||||
|
createWindow();
|
||||||
|
});
|
Loading…
Reference in a new issue