From f94423333bef13d408b94419252b2484397fb4d4 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Wed, 25 May 2022 01:44:46 -0400 Subject: [PATCH 1/7] fix: stricter directory import --- src/loaders.ts | 75 +++++++++++++++++++++++++---------- tests/specs/typescript/cts.ts | 2 + tests/specs/typescript/mts.ts | 5 ++- 3 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/loaders.ts b/src/loaders.ts index 2029140..2f7ff58 100644 --- a/src/loaders.ts +++ b/src/loaders.ts @@ -23,22 +23,63 @@ type Resolved = { format: ModuleFormat; }; +type Context = { + conditions: string[]; + parentURL: string | undefined; +}; + type resolve = ( specifier: string, - context: { - conditions: string[]; - parentURL: string | undefined; - }, + context: Context, defaultResolve: resolve, ) => MaybePromise; const hasExtensionPattern = /\.\w+$/; const extensions = ['.js', '.json', '.ts', '.tsx', '.jsx'] as const; -const possibleSuffixes = [ - ...extensions, - ...extensions.map(extension => `/index${extension}` as const), -]; + +async function tryExtensions( + specifier: string, + context: Context, + defaultResolve: resolve, +) { + let error; + for (const extension of extensions) { + try { + return await resolve( + specifier + extension, + context, + defaultResolve, + ); + } catch (_error: any) { + if (error === undefined) { + const { message } = _error; + _error.message = _error.message.replace(`${extension}'`, "'"); + _error.stack = _error.stack.replace(message, _error.message); + error = _error; + } + } + } + + throw error; +} + +async function tryDirectory( + specifier: string, + context: Context, + defaultResolve: resolve, +) { + const appendIndex = specifier.endsWith('/') ? 'index' : '/index'; + + try { + return await tryExtensions(specifier + appendIndex, context, defaultResolve); + } catch (error: any) { + const { message } = error; + error.message = error.message.replace(`${appendIndex}'`, "'"); + error.stack = error.stack.replace(message, error.message); + throw error; + } +} export const resolve: resolve = async function ( specifier, @@ -53,7 +94,7 @@ export const resolve: resolve = async function ( // If directory, can be index.js, index.ts, etc. if (specifier.endsWith('/')) { - return resolve(`${specifier}index`, context, defaultResolve); + return await tryDirectory(specifier, context, defaultResolve); } /** @@ -79,24 +120,16 @@ export const resolve: resolve = async function ( } catch (error) { if (error instanceof Error) { if ((error as any).code === 'ERR_UNSUPPORTED_DIR_IMPORT') { - return resolve(`${specifier}/index`, context, defaultResolve); + return await tryDirectory(specifier, context, defaultResolve); } if ( (error as any).code === 'ERR_MODULE_NOT_FOUND' && !hasExtensionPattern.test(specifier) ) { - for (const suffix of possibleSuffixes) { - try { - const trySpecifier = specifier + ( - specifier.endsWith('/') && suffix.startsWith('/') - ? suffix.slice(1) - : suffix - ); - - return await resolve(trySpecifier, context, defaultResolve); - } catch {} - } + try { + return await tryExtensions(specifier, context, defaultResolve); + } catch {} } } diff --git a/tests/specs/typescript/cts.ts b/tests/specs/typescript/cts.ts index fb67fb1..49fc40a 100644 --- a/tests/specs/typescript/cts.ts +++ b/tests/specs/typescript/cts.ts @@ -49,6 +49,7 @@ export default testSuite(async ({ describe }, node: NodeApis) => { test('Import', async () => { const nodeProcess = await node.import(importPath); expect(nodeProcess.stderr).toMatch('Cannot find module'); + expect(nodeProcess.stderr).toMatch('/lib/ts-ext-cts/index\''); }); }); @@ -63,6 +64,7 @@ export default testSuite(async ({ describe }, node: NodeApis) => { test('Import', async () => { const nodeProcess = await node.import(importPath); expect(nodeProcess.stderr).toMatch('Cannot find module'); + expect(nodeProcess.stderr).toMatch('/lib/ts-ext-cts\''); }); }); }); diff --git a/tests/specs/typescript/mts.ts b/tests/specs/typescript/mts.ts index acba450..cee0892 100644 --- a/tests/specs/typescript/mts.ts +++ b/tests/specs/typescript/mts.ts @@ -39,16 +39,18 @@ export default testSuite(async ({ describe }, node: NodeApis) => { test('Load', async () => { const nodeProcess = await node.load(importPath); expect(nodeProcess.stderr).toMatch('Cannot find module'); + expect(nodeProcess.stderr).toMatch('/lib/ts-ext-mts/index\''); }); test('Import', async () => { const nodeProcess = await node.import(importPath); expect(nodeProcess.stderr).toMatch('Cannot find module'); + expect(nodeProcess.stderr).toMatch('/lib/ts-ext-mts/index\''); }); }); describe('directory - should not work', ({ test }) => { - const importPath = './lib/ts-ext-mts'; + const importPath = './lib/ts-ext-mts/'; test('Load', async () => { const nodeProcess = await node.load(importPath); @@ -58,6 +60,7 @@ export default testSuite(async ({ describe }, node: NodeApis) => { test('Import', async () => { const nodeProcess = await node.import(importPath); expect(nodeProcess.stderr).toMatch('Cannot find module'); + expect(nodeProcess.stderr).toMatch('/lib/ts-ext-mts/\''); }); }); }); From fa5c1e9d36319c42822a83456f6a15288ba4b5e4 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Wed, 25 May 2022 01:49:28 -0400 Subject: [PATCH 2/7] refactor: remove unnecessary try-catch --- src/loaders.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/loaders.ts b/src/loaders.ts index 2f7ff58..e18bb05 100644 --- a/src/loaders.ts +++ b/src/loaders.ts @@ -127,9 +127,7 @@ export const resolve: resolve = async function ( (error as any).code === 'ERR_MODULE_NOT_FOUND' && !hasExtensionPattern.test(specifier) ) { - try { - return await tryExtensions(specifier, context, defaultResolve); - } catch {} + return await tryExtensions(specifier, context, defaultResolve); } } From ffd6061003c72dbf2981d5981853545dfa35bb43 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Wed, 25 May 2022 01:56:14 -0400 Subject: [PATCH 3/7] test: windows paths --- tests/specs/typescript/cts.ts | 14 ++++++++++++-- tests/specs/typescript/mts.ts | 15 ++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/tests/specs/typescript/cts.ts b/tests/specs/typescript/cts.ts index 49fc40a..fc7c6cb 100644 --- a/tests/specs/typescript/cts.ts +++ b/tests/specs/typescript/cts.ts @@ -1,6 +1,8 @@ import { testSuite, expect } from 'manten'; import type { NodeApis } from '../../utils/node-with-loader'; +const isWin = process.platform === 'win32'; + export default testSuite(async ({ describe }, node: NodeApis) => { describe('.cts extension', ({ describe }) => { describe('full path', ({ test }) => { @@ -49,7 +51,11 @@ export default testSuite(async ({ describe }, node: NodeApis) => { test('Import', async () => { const nodeProcess = await node.import(importPath); expect(nodeProcess.stderr).toMatch('Cannot find module'); - expect(nodeProcess.stderr).toMatch('/lib/ts-ext-cts/index\''); + expect(nodeProcess.stderr).toMatch( + isWin + ? '\\lib\\ts-ext-cts\\index\'' + : '/lib/ts-ext-cts/index\'', + ); }); }); @@ -64,7 +70,11 @@ export default testSuite(async ({ describe }, node: NodeApis) => { test('Import', async () => { const nodeProcess = await node.import(importPath); expect(nodeProcess.stderr).toMatch('Cannot find module'); - expect(nodeProcess.stderr).toMatch('/lib/ts-ext-cts\''); + expect(nodeProcess.stderr).toMatch( + isWin + ? '\\lib\\ts-ext-cts\'' + : '/lib/ts-ext-cts\'', + ); }); }); }); diff --git a/tests/specs/typescript/mts.ts b/tests/specs/typescript/mts.ts index cee0892..2a61ce1 100644 --- a/tests/specs/typescript/mts.ts +++ b/tests/specs/typescript/mts.ts @@ -1,6 +1,8 @@ import { testSuite, expect } from 'manten'; import type { NodeApis } from '../../utils/node-with-loader'; +const isWin = process.platform === 'win32'; + export default testSuite(async ({ describe }, node: NodeApis) => { describe('.mts extension', ({ describe }) => { const output = 'loaded ts-ext-mts/index.mts true true true'; @@ -39,13 +41,16 @@ export default testSuite(async ({ describe }, node: NodeApis) => { test('Load', async () => { const nodeProcess = await node.load(importPath); expect(nodeProcess.stderr).toMatch('Cannot find module'); - expect(nodeProcess.stderr).toMatch('/lib/ts-ext-mts/index\''); }); test('Import', async () => { const nodeProcess = await node.import(importPath); expect(nodeProcess.stderr).toMatch('Cannot find module'); - expect(nodeProcess.stderr).toMatch('/lib/ts-ext-mts/index\''); + expect(nodeProcess.stderr).toMatch( + isWin + ? '\\lib\\ts-ext-mts\\index\'' + : '/lib/ts-ext-mts/index\'' + ); }); }); @@ -60,7 +65,11 @@ export default testSuite(async ({ describe }, node: NodeApis) => { test('Import', async () => { const nodeProcess = await node.import(importPath); expect(nodeProcess.stderr).toMatch('Cannot find module'); - expect(nodeProcess.stderr).toMatch('/lib/ts-ext-mts/\''); + expect(nodeProcess.stderr).toMatch( + isWin + ? '\\lib\\ts-ext-mts\'' + : '/lib/ts-ext-mts/\'' + ); }); }); }); From a1c2bb9083a1e884e06ab93c77d3f7d6e116ab56 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Wed, 25 May 2022 01:58:48 -0400 Subject: [PATCH 4/7] style: lintfix --- tests/specs/typescript/mts.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/specs/typescript/mts.ts b/tests/specs/typescript/mts.ts index 2a61ce1..925a1a5 100644 --- a/tests/specs/typescript/mts.ts +++ b/tests/specs/typescript/mts.ts @@ -49,7 +49,7 @@ export default testSuite(async ({ describe }, node: NodeApis) => { expect(nodeProcess.stderr).toMatch( isWin ? '\\lib\\ts-ext-mts\\index\'' - : '/lib/ts-ext-mts/index\'' + : '/lib/ts-ext-mts/index\'', ); }); }); @@ -68,7 +68,7 @@ export default testSuite(async ({ describe }, node: NodeApis) => { expect(nodeProcess.stderr).toMatch( isWin ? '\\lib\\ts-ext-mts\'' - : '/lib/ts-ext-mts/\'' + : '/lib/ts-ext-mts/\'', ); }); }); From ed861ba68ec5494db88d54b129bbb66fe53f500c Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Wed, 25 May 2022 02:07:25 -0400 Subject: [PATCH 5/7] test: windows paths --- src/loaders.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/loaders.ts b/src/loaders.ts index e18bb05..72c423e 100644 --- a/src/loaders.ts +++ b/src/loaders.ts @@ -1,3 +1,4 @@ +import path from 'path'; import { transform, installSourceMapSupport, @@ -69,7 +70,7 @@ async function tryDirectory( context: Context, defaultResolve: resolve, ) { - const appendIndex = specifier.endsWith('/') ? 'index' : '/index'; + const appendIndex = specifier.endsWith('/') ? 'index' : path.sep + 'index'; try { return await tryExtensions(specifier + appendIndex, context, defaultResolve); From a3dd05e3408a4ce790f1b1c2102b6ab961e46387 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Wed, 25 May 2022 02:09:54 -0400 Subject: [PATCH 6/7] style: lintfix --- src/loaders.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/loaders.ts b/src/loaders.ts index 72c423e..f057416 100644 --- a/src/loaders.ts +++ b/src/loaders.ts @@ -70,7 +70,7 @@ async function tryDirectory( context: Context, defaultResolve: resolve, ) { - const appendIndex = specifier.endsWith('/') ? 'index' : path.sep + 'index'; + const appendIndex = specifier.endsWith('/') ? 'index' : `${path.sep}index`; try { return await tryExtensions(specifier + appendIndex, context, defaultResolve); From 72089af1212cd538def7ebf38d9e134dc578f266 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Wed, 25 May 2022 02:13:16 -0400 Subject: [PATCH 7/7] test: windows paths --- tests/specs/typescript/mts.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/specs/typescript/mts.ts b/tests/specs/typescript/mts.ts index 925a1a5..a22c50f 100644 --- a/tests/specs/typescript/mts.ts +++ b/tests/specs/typescript/mts.ts @@ -67,7 +67,7 @@ export default testSuite(async ({ describe }, node: NodeApis) => { expect(nodeProcess.stderr).toMatch('Cannot find module'); expect(nodeProcess.stderr).toMatch( isWin - ? '\\lib\\ts-ext-mts\'' + ? '\\lib\\ts-ext-mts\\\'' : '/lib/ts-ext-mts/\'', ); });