From 764be844ec3aa649f47a798cd3b02fe8d36eeb4e Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 24 Jun 2019 10:18:29 -0700 Subject: [PATCH] fix: override the timers module impls to activate the uv loop (#18948) --- lib/common/init.ts | 21 +++++++++++++-------- spec/node-spec.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/lib/common/init.ts b/lib/common/init.ts index e12a11b9dd01..425efac85d9c 100644 --- a/lib/common/init.ts +++ b/lib/common/init.ts @@ -1,8 +1,9 @@ -import * as timers from 'timers' import * as util from 'util' import { electronBindingSetup } from '@electron/internal/common/electron-binding-setup' +const timers = require('timers') + process.electronBinding = electronBindingSetup(process._linkedBinding, process.type) type AnyFn = (...args: any[]) => any @@ -38,16 +39,20 @@ function wrap (func: T, wrapper: (fn: AnyFn) => T) { process.nextTick = wrapWithActivateUvLoop(process.nextTick) -global.setImmediate = wrapWithActivateUvLoop(timers.setImmediate) +global.setImmediate = timers.setImmediate = wrapWithActivateUvLoop(timers.setImmediate) global.clearImmediate = timers.clearImmediate +// setTimeout needs to update the polling timeout of the event loop, when +// called under Chromium's event loop the node's event loop won't get a chance +// to update the timeout, so we have to force the node's event loop to +// recalculate the timeout in browser process. +timers.setTimeout = wrapWithActivateUvLoop(timers.setTimeout) +timers.setInterval = wrapWithActivateUvLoop(timers.setInterval) + +// Only override the global setTimeout/setInterval impls in the browser process if (process.type === 'browser') { - // setTimeout needs to update the polling timeout of the event loop, when - // called under Chromium's event loop the node's event loop won't get a chance - // to update the timeout, so we have to force the node's event loop to - // recalculate the timeout in browser process. - global.setTimeout = wrapWithActivateUvLoop(timers.setTimeout) - global.setInterval = wrapWithActivateUvLoop(timers.setInterval) + global.setTimeout = timers.setTimeout + global.setInterval = timers.setInterval } if (process.platform === 'win32') { diff --git a/spec/node-spec.js b/spec/node-spec.js index aa7b2dace92d..befab8e9e503 100644 --- a/spec/node-spec.js +++ b/spec/node-spec.js @@ -212,6 +212,16 @@ describe('node feature', () => { }) }) + describe('setTimeout called under blink env in renderer process', () => { + it('can be scheduled in time', (done) => { + setTimeout(done, 10) + }) + + it('works from the timers module', (done) => { + require('timers').setTimeout(done, 10) + }) + }) + describe('setInterval called under Chromium event loop in browser process', () => { it('can be scheduled in time', (done) => { let interval = null @@ -229,6 +239,40 @@ describe('node feature', () => { interval = remote.getGlobal('setInterval')(clear, 10) }) }) + + describe('setInterval called under blink env in renderer process', () => { + it('can be scheduled in time', (done) => { + let interval = null + let clearing = false + const clear = () => { + if (interval === null || clearing) return + + // interval might trigger while clearing (remote is slow sometimes) + clearing = true + clearInterval(interval) + clearing = false + interval = null + done() + } + interval = setInterval(clear, 10) + }) + + it('can be scheduled in time from timers module', (done) => { + let interval = null + let clearing = false + const clear = () => { + if (interval === null || clearing) return + + // interval might trigger while clearing (remote is slow sometimes) + clearing = true + require('timers').clearInterval(interval) + clearing = false + interval = null + done() + } + interval = require('timers').setInterval(clear, 10) + }) + }) }) describe('inspector', () => {