Skip to content

Commit 935cd3b

Browse files
committed
chore: provisional esm deadlock fix
1 parent 011050f commit 935cd3b

File tree

2 files changed

+11
-32
lines changed

2 files changed

+11
-32
lines changed

packages/playwright/src/transform/esmLoader.ts

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,10 @@
1717
import fs from 'fs';
1818
import url from 'url';
1919

20-
import { monotonicTime, raceAgainstDeadline } from 'playwright-core/lib/utils';
21-
2220
import { addToCompilationCache, currentFileDepsCollector, serializeCompilationCache, startCollectingFileDeps, stopCollectingFileDeps } from './compilationCache';
2321
import { PortTransport } from './portTransport';
2422
import { resolveHook, setSingleTSConfig, setTransformConfig, shouldTransform, transformHook } from './transform';
25-
import { debugTest, fileIsModule } from '../util';
26-
27-
// See note on pushToCompilationCache()
28-
// Once we enter a deadlock scenario, we will fallback to unawaited IPC
29-
let workerShouldFallbackCompilationCache = false;
23+
import { fileIsModule } from '../util';
3024

3125
// Node < 18.6: defaultResolve takes 3 arguments.
3226
// Node >= 18.6: nextResolve from the chain takes 2 arguments.
@@ -60,7 +54,7 @@ const kSupportedFormats = new Map([
6054

6155
// Node < 18.6: defaultLoad takes 3 arguments.
6256
// Node >= 18.6: nextLoad from the chain takes 2 arguments.
63-
async function load(moduleUrl: string, context: { format?: string }, defaultLoad: Function) {
57+
function load(moduleUrl: string, context: { format?: string }, defaultLoad: Function) {
6458
// Bail out for wasm, json, etc.
6559
if (!kSupportedFormats.has(context.format))
6660
return defaultLoad(moduleUrl, context, defaultLoad);
@@ -79,7 +73,7 @@ async function load(moduleUrl: string, context: { format?: string }, defaultLoad
7973

8074
// Flush the source maps to the main thread, so that errors during import() are source-mapped.
8175
if (transformed.serializedCache && transport)
82-
await pushToCompilationCache(transport, transformed.serializedCache);
76+
transport.post('pushToCompilationCache', { cache: transformed.serializedCache });
8377

8478
// Output format is required, so we determine it manually when unknown.
8579
// shortCircuit is required by Node >= 18.6 to designate no more loaders should be called.
@@ -90,23 +84,6 @@ async function load(moduleUrl: string, context: { format?: string }, defaultLoad
9084
};
9185
}
9286

93-
// Under certain conditions with ESM -> CJS -> any imports, we can enter deadlock awaiting the
94-
// MessagePort transfer simultaneously with the Node.js worker thread that is performing the load().
95-
// Attempt to await the IPC transfer, and if it takes too long, fallback to a non-awaiting transfer
96-
async function pushToCompilationCache(transport: PortTransport, cache: any) {
97-
if (workerShouldFallbackCompilationCache) {
98-
transport.send('pushToCompilationCache', { cache })
99-
.catch(e => debugTest('Failed to push compilation cache', e));
100-
return;
101-
}
102-
103-
const { timedOut } = await raceAgainstDeadline(() => transport.send('pushToCompilationCache', { cache }), monotonicTime() + 1000);
104-
if (timedOut) {
105-
debugTest('Falling back to unawaited compilation cache');
106-
workerShouldFallbackCompilationCache = true;
107-
}
108-
}
109-
11087
let transport: PortTransport | undefined;
11188

11289
function initialize(data: { port: MessagePort }) {

packages/playwright/src/transform/portTransport.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,27 @@ export class PortTransport {
2424
port.addEventListener('message', async event => {
2525
const message = event.data;
2626
const { id, ackId, method, params, result } = message;
27-
if (id) {
28-
const result = await handler(method, params);
29-
this._port.postMessage({ ackId: id, result });
30-
return;
31-
}
32-
3327
if (ackId) {
3428
const callback = this._callbacks.get(ackId);
3529
this._callbacks.delete(ackId);
3630
this._resetRef();
3731
callback?.(result);
3832
return;
3933
}
34+
35+
const handlerResult = await handler(method, params);
36+
if (id)
37+
this._port.postMessage({ ackId: id, result: handlerResult });
4038
});
4139
// Make sure to unref **after** adding a 'message' event listener.
4240
// https://nodejs.org/api/worker_threads.html#portref
4341
this._resetRef();
4442
}
4543

44+
post(method: string, params: any) {
45+
this._port.postMessage({ method, params });
46+
}
47+
4648
async send(method: string, params: any) {
4749
return await new Promise<any>(f => {
4850
const id = ++this._lastId;

0 commit comments

Comments
 (0)