fix(esm+tsconfig): allow mapped ts files in esm mode (#17862)

Fixes https://github.com/microsoft/playwright/issues/17840
This commit is contained in:
Pavel Feldman 2022-10-05 17:00:49 -08:00 committed by GitHub
parent f2685cab95
commit c0e4caa604
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 14 deletions

View File

@ -23,7 +23,7 @@ import { transformHook, resolveHook, belongsToNodeModules } from './transform';
async function resolve(specifier: string, context: { parentURL?: string }, defaultResolve: Function) {
if (context.parentURL && context.parentURL.startsWith('file://')) {
const filename = url.fileURLToPath(context.parentURL);
const resolved = resolveHook(filename, specifier);
const resolved = resolveHook(true, filename, specifier);
if (resolved !== undefined)
specifier = url.pathToFileURL(resolved).toString();
}

View File

@ -92,7 +92,7 @@ const scriptPreprocessor = process.env.PW_TEST_SOURCE_TRANSFORM ?
require(process.env.PW_TEST_SOURCE_TRANSFORM) : undefined;
const builtins = new Set(Module.builtinModules);
export function resolveHook(filename: string, specifier: string): string | undefined {
export function resolveHook(isModule: boolean, filename: string, specifier: string): string | undefined {
if (builtins.has(specifier))
return;
const isTypeScript = filename.endsWith('.ts') || filename.endsWith('.tsx');
@ -132,11 +132,21 @@ export function resolveHook(filename: string, specifier: string): string | undef
if (value.includes('*'))
candidate = candidate.replace('*', matchedPartOfSpecifier);
candidate = path.resolve(tsconfig.absoluteBaseUrl, candidate.replace(/\//g, path.sep));
for (const ext of ['', '.js', '.ts', '.mjs', '.cjs', '.jsx', '.tsx', '.cjs', '.mts', '.cts']) {
if (fs.existsSync(candidate + ext)) {
if (isModule) {
const transformed = js2ts(candidate);
if (transformed || fs.existsSync(candidate)) {
if (keyPrefix.length > longestPrefixLength) {
longestPrefixLength = keyPrefix.length;
pathMatchedByLongestPrefix = candidate;
pathMatchedByLongestPrefix = transformed || candidate;
}
}
} else {
for (const ext of ['', '.js', '.ts', '.mjs', '.cjs', '.jsx', '.tsx', '.cjs', '.mts', '.cts']) {
if (fs.existsSync(candidate + ext)) {
if (keyPrefix.length > longestPrefixLength) {
longestPrefixLength = keyPrefix.length;
pathMatchedByLongestPrefix = candidate;
}
}
}
}
@ -145,13 +155,17 @@ export function resolveHook(filename: string, specifier: string): string | undef
if (pathMatchedByLongestPrefix)
return pathMatchedByLongestPrefix;
}
if (specifier.endsWith('.js')) {
const resolved = path.resolve(path.dirname(filename), specifier);
if (resolved.endsWith('.js')) {
const tsResolved = resolved.substring(0, resolved.length - 3) + '.ts';
if (!fs.existsSync(resolved) && fs.existsSync(tsResolved))
return tsResolved;
}
if (isModule)
return js2ts(path.resolve(path.dirname(filename), specifier));
}
export function js2ts(resolved: string): string | undefined {
const match = resolved.match(/(.*)(\.js|\.jsx|\.mjs)$/);
if (match) {
const tsResolved = match[1] + match[2].replace('j', 't');
if (!fs.existsSync(resolved) && fs.existsSync(tsResolved))
return tsResolved;
}
}
@ -197,7 +211,7 @@ export function installTransform(): () => void {
const originalResolveFilename = (Module as any)._resolveFilename;
function resolveFilename(this: any, specifier: string, parent: Module, ...rest: any[]) {
if (!reverted && parent) {
const resolved = resolveHook(parent.filename, specifier);
const resolved = resolveHook(false, parent.filename, specifier);
if (resolved !== undefined)
specifier = resolved;
}

View File

@ -109,7 +109,7 @@ test('should respect path resolver in experimental mode', async ({ runInlineTest
},
}`,
'a.test.ts': `
import { foo } from 'util/b.ts';
import { foo } from 'util/b.js';
const { test } = pwt;
test('check project name', ({}, testInfo) => {
expect(testInfo.project.name).toBe(foo);