diff --git a/.github/workflows/tests_primary.yml b/.github/workflows/tests_primary.yml index 74097c4fb712e..142cab8343aff 100644 --- a/.github/workflows/tests_primary.yml +++ b/.github/workflows/tests_primary.yml @@ -73,33 +73,33 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] - node-version: [20] + node-version: [22] shardIndex: [1, 2] shardTotal: [2] shardWeights: ['58:42'] include: - os: windows-latest - node-version: 20 + node-version: 22 shardIndex: 1 shardTotal: 3 shardWeights: '44:33:23' - os: windows-latest - node-version: 20 + node-version: 22 shardIndex: 2 shardTotal: 3 shardWeights: '44:33:23' - os: windows-latest - node-version: 20 + node-version: 22 shardIndex: 3 shardTotal: 3 shardWeights: '44:33:23' - os: ubuntu-latest - node-version: 22 + node-version: 20 shardIndex: 1 shardTotal: 2 shardWeights: '58:42' - os: ubuntu-latest - node-version: 22 + node-version: 20 shardIndex: 2 shardTotal: 2 shardWeights: '58:42' diff --git a/packages/playwright/src/transform/esmLoaderSync.ts b/packages/playwright/src/transform/esmLoaderSync.ts index 13457a7979fce..18c9c93af8361 100644 --- a/packages/playwright/src/transform/esmLoaderSync.ts +++ b/packages/playwright/src/transform/esmLoaderSync.ts @@ -21,15 +21,19 @@ import { currentFileDepsCollector } from './compilationCache'; import { resolveHook, shouldTransform, transformHook } from './transform'; import { fileIsModule } from '../util'; -export function resolve(specifier: string, context: { parentURL?: string }, nextResolve: Function) { +export function resolve(specifier: string, context: { parentURL?: string, conditions?: string[] }, nextResolve: Function) { if (context.parentURL && context.parentURL.startsWith('file://')) { const filename = url.fileURLToPath(context.parentURL); const resolved = resolveHook(filename, specifier); - // Pass the resolved absolute path (not a file:// URL) to nextResolve: unlike the - // ESM-only asynchronous loader, these hooks also serve require(), whose default - // resolver rejects file:// specifiers but accepts absolute paths for both kinds. - if (resolved !== undefined) - specifier = resolved; + if (resolved !== undefined) { + // These hooks serve both require() and import. The two default resolvers disagree on + // what an already-resolved specifier should look like: + // - require()'s resolver wants an absolute path and rejects file:// specifiers; + // - the ESM resolver wants a file:// URL and, on Windows, mistakes an absolute path's + // drive letter for a URL scheme ("Received protocol 'c:'"). + // The `import` condition is present only for ESM resolution, so use it to pick the form. + specifier = context.conditions?.includes('import') ? url.pathToFileURL(resolved).toString() : resolved; + } } const result = nextResolve(specifier, context); if (result?.url && result.url.startsWith('file://'))