From b54edaf8d3f81a26d1e935751d96222fc0f611f9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 17 Apr 2020 05:11:57 -0500 Subject: [PATCH] fix: use Node's microtasks policy in node_main.cc Fixes #21515. --- shell/app/node_main.cc | 4 ++++ spec-main/node-spec.ts | 13 ++++++++++++ spec/fixtures/module/node-promise-timer.js | 23 ++++++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 spec/fixtures/module/node-promise-timer.js diff --git a/shell/app/node_main.cc b/shell/app/node_main.cc index 5e8c1c2aaaa1c..c9dcd64cdb68e 100644 --- a/shell/app/node_main.cc +++ b/shell/app/node_main.cc @@ -146,6 +146,10 @@ int NodeMain(int argc, char* argv[]) { JavascriptEnvironment gin_env(loop); v8::Isolate* isolate = gin_env.isolate(); + // TODO(ckerr) and/or TODO(codebytere) use node::SetIsolateMiscHandlers() + node::IsolateSettings is; + isolate->SetMicrotasksPolicy(is.policy); + v8::Isolate::Scope isolate_scope(isolate); v8::Locker locker(isolate); node::Environment* env = nullptr; diff --git a/spec-main/node-spec.ts b/spec-main/node-spec.ts index d6030e76f7b7a..50811de6eeb59 100644 --- a/spec-main/node-spec.ts +++ b/spec-main/node-spec.ts @@ -307,4 +307,17 @@ describe('node feature', () => { const result = childProcess.spawnSync(process.execPath, [path.resolve(fixtures, 'api', 'electron-main-module', 'app.asar')]); expect(result.status).to.equal(0); }); + + it('handles Promise timeouts correctly', (done) => { + const scriptPath = path.join(fixtures, 'module', 'node-promise-timer.js'); + const child = childProcess.spawn(process.execPath, [scriptPath], { + env: { ELECTRON_RUN_AS_NODE: 'true' } + }); + emittedOnce(child, 'exit').then(([code, signal]) => { + expect(code).to.equal(0); + expect(signal).to.equal(null); + child.kill(); + done(); + }); + }); }); diff --git a/spec/fixtures/module/node-promise-timer.js b/spec/fixtures/module/node-promise-timer.js new file mode 100644 index 0000000000000..b21c24f5dfc36 --- /dev/null +++ b/spec/fixtures/module/node-promise-timer.js @@ -0,0 +1,23 @@ +const waitMs = (msec) => new Promise((resolve) => setTimeout(resolve, msec)); + +const intervalMsec = 100; +const numIterations = 2; +let curIteration = 0; +let promise; + +for (let i = 0; i < numIterations; i++) { + promise = (promise || waitMs(intervalMsec)).then(() => { + ++curIteration; + return waitMs(intervalMsec); + }); +} + +// https://github.com/electron/electron/issues/21515 was about electron +// exiting before promises finished. This test sets the pending exitCode +// to failure, then resets it to success only if all promises finish. +process.exitCode = 1; +promise.then(() => { + if (curIteration === numIterations) { + process.exitCode = 0; + } +});