diff --git a/packages/playwright-core/src/server/android/android.ts b/packages/playwright-core/src/server/android/android.ts index 1fc6a296bf464..4f7de93939c5d 100644 --- a/packages/playwright-core/src/server/android/android.ts +++ b/packages/playwright-core/src/server/android/android.ts @@ -24,7 +24,6 @@ import { PipeTransport } from '@utils/pipeTransport'; import { createGuid } from '@utils/crypto'; import { isUnderTest } from '@utils/debug'; import { getPackageManagerExecCommand } from '@utils/env'; -import { makeWaitForNextTask } from '@utils/task'; import { RecentLogsCollector } from '@utils/debugLogger'; import { removeFolders } from '@utils/fileUtils'; import { gracefullyCloseSet } from '@utils/processLauncher'; @@ -479,7 +478,6 @@ class AndroidBrowser extends EventEmitter { readonly device: AndroidDevice; private _socket: SocketBackend; private _receiver: stream.Writable; - private _waitForNextTask = makeWaitForNextTask(); onmessage?: (message: any) => void; onclose?: () => void; @@ -489,14 +487,14 @@ class AndroidBrowser extends EventEmitter { this.device = device; this._socket = socket; this._socket.on('close', () => { - this._waitForNextTask(() => { + setImmediate(() => { if (this.onclose) this.onclose(); }); }); this._receiver = new wsReceiver() as stream.Writable; this._receiver.on('message', message => { - this._waitForNextTask(() => { + setImmediate(() => { if (this.onmessage) this.onmessage(JSON.parse(message)); }); diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index c146615162eb5..622c62bf07f06 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -25,7 +25,6 @@ import { LongStandingScope } from '@isomorphic/manualPromise'; import { asLocator } from '@isomorphic/locatorGenerators'; import { assert } from '@isomorphic/assert'; import { constructURLBasedOnBaseURL } from '@isomorphic/urlMatch'; -import { makeWaitForNextTask } from '@utils/task'; import { createGuid } from '@utils/crypto'; import { BrowserContext } from './browserContext'; import * as dom from './dom'; @@ -199,7 +198,7 @@ export class FrameManager { await progress.race(this._page.delegate.inputActionEpilogue()); await barrier.waitFor(progress); // Resolve in the next task, after all waitForNavigations. - await new Promise(makeWaitForNextTask()); + await new Promise(f => setImmediate(f)); return result; } finally { this._signalBarriers.delete(barrier); diff --git a/packages/playwright-core/src/server/pipeTransport.ts b/packages/playwright-core/src/server/pipeTransport.ts index 82ef02143857c..4e8802cbdb275 100644 --- a/packages/playwright-core/src/server/pipeTransport.ts +++ b/packages/playwright-core/src/server/pipeTransport.ts @@ -16,7 +16,6 @@ */ import { debugLogger } from '@utils/debugLogger'; -import { makeWaitForNextTask } from '@utils/task'; import type { ConnectionTransport, ProtocolRequest, ProtocolResponse } from './transport'; @@ -24,7 +23,6 @@ export class PipeTransport implements ConnectionTransport { private _pipeRead: NodeJS.ReadableStream; private _pipeWrite: NodeJS.WritableStream; private _pendingBuffers: Buffer[] = []; - private _waitForNextTask = makeWaitForNextTask(); private _closed = false; private _onclose?: (reason?: string) => void; @@ -73,7 +71,7 @@ export class PipeTransport implements ConnectionTransport { } this._pendingBuffers.push(buffer.slice(0, end)); const message = Buffer.concat(this._pendingBuffers).toString(); - this._waitForNextTask(() => { + setImmediate(() => { if (this.onmessage) this.onmessage.call(null, JSON.parse(message)); }); @@ -82,7 +80,7 @@ export class PipeTransport implements ConnectionTransport { end = buffer.indexOf('\0', start); while (end !== -1) { const message = buffer.toString(undefined, start, end); - this._waitForNextTask(() => { + setImmediate(() => { if (this.onmessage) this.onmessage.call(null, JSON.parse(message)); }); diff --git a/packages/playwright-core/src/server/transport.ts b/packages/playwright-core/src/server/transport.ts index 028da8bd59254..443e3d673b07f 100644 --- a/packages/playwright-core/src/server/transport.ts +++ b/packages/playwright-core/src/server/transport.ts @@ -17,7 +17,6 @@ import ws from 'ws'; import { flattenAggregateError, happyEyeballsOptions } from '@utils/network'; -import { makeWaitForNextTask } from '@utils/task'; import type { WebSocket } from 'ws'; import type { Progress } from './progress'; import type { HeadersArray } from './types'; @@ -153,7 +152,7 @@ export class WebSocketTransport implements ConnectionTransport { // In Web, all IO callbacks (e.g. WebSocket callbacks) // are dispatched into separate tasks, so there's no need // to do anything extra. - const messageWrap: (cb: () => void) => void = makeWaitForNextTask(); + const messageWrap: (cb: () => void) => void = setImmediate; this._ws.addEventListener('message', event => { messageWrap(() => { diff --git a/packages/utils/index.ts b/packages/utils/index.ts index 682d36fc31360..4a1588658d0bf 100644 --- a/packages/utils/index.ts +++ b/packages/utils/index.ts @@ -34,7 +34,6 @@ export * from './socksProxy'; export * from './spawnAsync'; export * from './stackTrace'; export * from './stringWidth'; -export * from './task'; export * from './wsServer'; export * from './zipFile'; export * from './zones'; diff --git a/packages/utils/pipeTransport.ts b/packages/utils/pipeTransport.ts index 64b1d80e8fcb8..6e2e2a5bba530 100644 --- a/packages/utils/pipeTransport.ts +++ b/packages/utils/pipeTransport.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { makeWaitForNextTask } from './task'; interface WritableStream { write(data: Buffer): void; @@ -32,7 +31,6 @@ interface ClosableStream { export class PipeTransport { private _pipeWrite: WritableStream; private _data = Buffer.from([]); - private _waitForNextTask = makeWaitForNextTask(); private _closed = false; private _bytesLeft = 0; @@ -95,7 +93,7 @@ export class PipeTransport { const message = this._data.slice(0, this._bytesLeft); this._data = this._data.slice(this._bytesLeft); this._bytesLeft = 0; - this._waitForNextTask(() => { + setImmediate(() => { if (this.onmessage) this.onmessage(message.toString('utf-8')); }); diff --git a/packages/utils/task.ts b/packages/utils/task.ts deleted file mode 100644 index b00e9f1000965..0000000000000 --- a/packages/utils/task.ts +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// See https://joel.tools/microtasks/ -export function makeWaitForNextTask() { - // As of Mar 2021, Electron v12 doesn't create new task with `setImmediate` despite - // using Node 14 internally, so we fallback to `setTimeout(0)` instead. - // @see https://github.com/electron/electron/issues/28261 - if ((process.versions as any).electron) - return (callback: () => void) => setTimeout(callback, 0); - if (parseInt(process.versions.node, 10) >= 11) - return setImmediate; - - // Unlike Node 11, Node 10 and less have a bug with Task and MicroTask execution order: - // - https://github.com/nodejs/node/issues/22257 - // - // So we can't simply run setImmediate to dispatch code in a following task. - // However, we can run setImmediate from-inside setImmediate to make sure we're getting - // in the following task. - - let spinning = false; - const callbacks: (() => void)[] = []; - const loop = () => { - const callback = callbacks.shift(); - if (!callback) { - spinning = false; - return; - } - setImmediate(loop); - // Make sure to call callback() as the last thing since it's - // untrusted code that might throw. - callback(); - }; - - return (callback: () => void) => { - callbacks.push(callback); - if (!spinning) { - spinning = true; - setImmediate(loop); - } - }; -}