From 4103b7113795fbc3de6c21498914043a88c82813 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Tue, 26 Sep 2023 00:56:09 +0900 Subject: [PATCH 1/6] test: remove old node versions --- tests/utils/node-versions.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/utils/node-versions.ts b/tests/utils/node-versions.ts index 707b8aac3..0d757a8b2 100644 --- a/tests/utils/node-versions.ts +++ b/tests/utils/node-versions.ts @@ -1,5 +1,4 @@ export const nodeVersions = [ - '18', '20', ...( ( @@ -7,11 +6,7 @@ export const nodeVersions = [ && process.platform !== 'win32' ) ? [ - '12.20.0', // CJS named export detection added - '12', - '14', - '16', - '17', + '18', ] as const : [] as const ), From 189e684c6438ad4bca4c5b1b9335aec042dfbf45 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Tue, 26 Sep 2023 00:57:41 +0900 Subject: [PATCH 2/6] delete deprecated loader code --- src/esm/index.ts | 312 +++++++++++++++++++++++++++++++++- src/esm/loaders-deprecated.ts | 115 ------------- src/esm/loaders.ts | 310 --------------------------------- 3 files changed, 310 insertions(+), 427 deletions(-) delete mode 100644 src/esm/loaders-deprecated.ts delete mode 100644 src/esm/loaders.ts diff --git a/src/esm/index.ts b/src/esm/index.ts index 60a755b73..872db0792 100644 --- a/src/esm/index.ts +++ b/src/esm/index.ts @@ -1,2 +1,310 @@ -export * from './loaders.js'; -export * from './loaders-deprecated.js'; +import type { MessagePort } from 'node:worker_threads'; +import path from 'path'; +import { pathToFileURL, fileURLToPath } from 'url'; +import type { + ResolveFnOutput, ResolveHookContext, LoadHook, GlobalPreloadHook, +} from 'module'; +import type { TransformOptions } from 'esbuild'; +import { compareNodeVersion } from '../utils/compare-node-version'; +import { transform, transformDynamicImport } from '../utils/transform'; +import { resolveTsPath } from '../utils/resolve-ts-path'; +import { + applySourceMap, + tsconfigPathsMatcher, + fileMatcher, + tsExtensionsPattern, + isJsonPattern, + getFormatFromFileUrl, + fileProtocol, + type MaybePromise, + type NodeError, +} from './utils.js'; + +const isDirectoryPattern = /\/(?:$|\?)/; + +type NextResolve = ( + specifier: string, + context?: ResolveHookContext, +) => MaybePromise; + +type resolve = ( + specifier: string, + context: ResolveHookContext, + nextResolve: NextResolve, + recursiveCall?: boolean, +) => MaybePromise; + +const isolatedLoader = compareNodeVersion([20, 0, 0]) >= 0; + +type SendToParent = (data: { + type: 'dependency'; + path: string; +}) => void; + +let sendToParent: SendToParent | undefined = process.send ? process.send.bind(process) : undefined; + +/** + * Technically globalPreload is deprecated so it should be in loaders-deprecated + * but it shares a closure with the new load hook + */ +let mainThreadPort: MessagePort | undefined; +const _globalPreload: GlobalPreloadHook = ({ port }) => { + mainThreadPort = port; + sendToParent = port.postMessage.bind(port); + + return ` + const require = getBuiltin('module').createRequire("${import.meta.url}"); + require('tsx/source-map').installSourceMapSupport(port); + if (process.send) { + port.addListener('message', (message) => { + if (message.type === 'dependency') { + process.send(message); + } + }); + } + port.unref(); // Allows process to exit without waiting for port to close + `; +}; + +export const globalPreload = isolatedLoader ? _globalPreload : undefined; + +const resolveExplicitPath = async ( + defaultResolve: NextResolve, + specifier: string, + context: ResolveHookContext, +) => { + const resolved = await defaultResolve(specifier, context); + + if ( + !resolved.format + && resolved.url.startsWith(fileProtocol) + ) { + resolved.format = await getFormatFromFileUrl(resolved.url); + } + + return resolved; +}; + +const extensions = ['.js', '.json', '.ts', '.tsx', '.jsx'] as const; + +async function tryExtensions( + specifier: string, + context: ResolveHookContext, + defaultResolve: NextResolve, +) { + const [specifierWithoutQuery, query] = specifier.split('?'); + let throwError: Error | undefined; + for (const extension of extensions) { + try { + return await resolveExplicitPath( + defaultResolve, + specifierWithoutQuery + extension + (query ? `?${query}` : ''), + context, + ); + } catch (_error) { + if ( + throwError === undefined + && _error instanceof Error + ) { + const { message } = _error; + _error.message = _error.message.replace(`${extension}'`, "'"); + _error.stack = _error.stack!.replace(message, _error.message); + throwError = _error; + } + } + } + + throw throwError; +} + +async function tryDirectory( + specifier: string, + context: ResolveHookContext, + defaultResolve: NextResolve, +) { + const isExplicitDirectory = isDirectoryPattern.test(specifier); + const appendIndex = isExplicitDirectory ? 'index' : '/index'; + const [specifierWithoutQuery, query] = specifier.split('?'); + + try { + return await tryExtensions( + specifierWithoutQuery + appendIndex + (query ? `?${query}` : ''), + context, + defaultResolve, + ); + } catch (_error) { + if (!isExplicitDirectory) { + try { + return await tryExtensions(specifier, context, defaultResolve); + } catch {} + } + + const error = _error as Error; + const { message } = error; + error.message = error.message.replace(`${appendIndex.replace('/', path.sep)}'`, "'"); + error.stack = error.stack!.replace(message, error.message); + throw error; + } +} + +const isRelativePathPattern = /^\.{1,2}\//; + +const supportsNodePrefix = ( + compareNodeVersion([14, 13, 1]) >= 0 + || compareNodeVersion([12, 20, 0]) >= 0 +); + +export const resolve: resolve = async function ( + specifier, + context, + defaultResolve, + recursiveCall, +) { + // Added in v12.20.0 + // https://nodejs.org/api/esm.html#esm_node_imports + if (!supportsNodePrefix && specifier.startsWith('node:')) { + specifier = specifier.slice(5); + } + + // If directory, can be index.js, index.ts, etc. + if (isDirectoryPattern.test(specifier)) { + return await tryDirectory(specifier, context, defaultResolve); + } + + const isPath = ( + specifier.startsWith(fileProtocol) + || isRelativePathPattern.test(specifier) + ); + + if ( + tsconfigPathsMatcher + && !isPath // bare specifier + && !context.parentURL?.includes('/node_modules/') + ) { + const possiblePaths = tsconfigPathsMatcher(specifier); + for (const possiblePath of possiblePaths) { + try { + return await resolve( + pathToFileURL(possiblePath).toString(), + context, + defaultResolve, + ); + } catch {} + } + } + + /** + * Typescript gives .ts, .cts, or .mts priority over actual .js, .cjs, or .mjs extensions + */ + if ( + // !recursiveCall && + tsExtensionsPattern.test(context.parentURL!) + ) { + const tsPaths = resolveTsPath(specifier); + if (tsPaths) { + for (const tsPath of tsPaths) { + try { + return await resolveExplicitPath(defaultResolve, tsPath, context); + // return await resolve(tsPath, context, defaultResolve, true); + } catch (error) { + const { code } = error as NodeError; + if ( + code !== 'ERR_MODULE_NOT_FOUND' + && code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED' + ) { + throw error; + } + } + } + } + } + + try { + return await resolveExplicitPath(defaultResolve, specifier, context); + } catch (error) { + if ( + error instanceof Error + && !recursiveCall + ) { + const { code } = error as NodeError; + if (code === 'ERR_UNSUPPORTED_DIR_IMPORT') { + try { + return await tryDirectory(specifier, context, defaultResolve); + } catch (error_) { + if ((error_ as NodeError).code !== 'ERR_PACKAGE_IMPORT_NOT_DEFINED') { + throw error_; + } + } + } + + if (code === 'ERR_MODULE_NOT_FOUND') { + try { + return await tryExtensions(specifier, context, defaultResolve); + } catch {} + } + } + + throw error; + } +}; + +export const load: LoadHook = async function ( + url, + context, + defaultLoad, +) { + if (sendToParent) { + sendToParent({ + type: 'dependency', + path: url, + }); + } + + if (isJsonPattern.test(url)) { + if (!context.importAssertions) { + context.importAssertions = {}; + } + context.importAssertions.type = 'json'; + } + + const loaded = await defaultLoad(url, context); + + if (!loaded.source) { + return loaded; + } + + const filePath = url.startsWith('file://') ? fileURLToPath(url) : url; + const code = loaded.source.toString(); + + if ( + // Support named imports in JSON modules + loaded.format === 'json' + || tsExtensionsPattern.test(url) + ) { + const transformed = await transform( + code, + filePath, + { + tsconfigRaw: fileMatcher?.(filePath) as TransformOptions['tsconfigRaw'], + }, + ); + + return { + format: 'module', + source: applySourceMap(transformed, url, mainThreadPort), + }; + } + + if (loaded.format === 'module') { + const dynamicImportTransformed = transformDynamicImport(filePath, code); + if (dynamicImportTransformed) { + loaded.source = applySourceMap( + dynamicImportTransformed, + url, + mainThreadPort, + ); + } + } + + return loaded; +}; diff --git a/src/esm/loaders-deprecated.ts b/src/esm/loaders-deprecated.ts deleted file mode 100644 index 641b38b90..000000000 --- a/src/esm/loaders-deprecated.ts +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Deprecated ESM loaders used in Node v12 & 14 - * https://nodejs.org/docs/latest-v12.x/api/esm.html#esm_hooks - * https://nodejs.org/docs/latest-v14.x/api/esm.html#esm_hooks - */ -import { fileURLToPath } from 'url'; -import type { ModuleFormat } from 'module'; -import type { TransformOptions } from 'esbuild'; -import { transform, transformDynamicImport } from '../utils/transform'; -import { compareNodeVersion } from '../utils/compare-node-version'; -import { - applySourceMap, - fileMatcher, - tsExtensionsPattern, - getFormatFromFileUrl, - fileProtocol, - isJsonPattern, - type MaybePromise, - type NodeError, -} from './utils.js'; - -type getFormat = ( - url: string, - context: Record, - defaultGetFormat: getFormat, -) => MaybePromise<{ format: ModuleFormat }>; - -const _getFormat: getFormat = async function ( - url, - context, - defaultGetFormat, -) { - if (isJsonPattern.test(url)) { - return { format: 'module' }; - } - - try { - return await defaultGetFormat(url, context, defaultGetFormat); - } catch (error) { - if ( - (error as NodeError).code === 'ERR_UNKNOWN_FILE_EXTENSION' - && url.startsWith(fileProtocol) - ) { - const format = await getFormatFromFileUrl(url); - if (format) { - return { format }; - } - } - - throw error; - } -}; - -type Source = string | SharedArrayBuffer | Uint8Array; - -type transformSource = ( - source: Source, - context: { - url: string; - format: ModuleFormat; - }, - defaultTransformSource: transformSource, -) => MaybePromise<{ source: Source }> - -const _transformSource: transformSource = async function ( - source, - context, - defaultTransformSource, -) { - const { url } = context; - const filePath = url.startsWith('file://') ? fileURLToPath(url) : url; - - if (process.send) { - process.send({ - type: 'dependency', - path: url, - }); - } - - if ( - isJsonPattern.test(url) - || tsExtensionsPattern.test(url) - ) { - const transformed = await transform( - source.toString(), - filePath, - { - tsconfigRaw: fileMatcher?.(filePath) as TransformOptions['tsconfigRaw'], - }, - ); - - return { - source: applySourceMap(transformed, url), - }; - } - - const result = await defaultTransformSource(source, context, defaultTransformSource); - - if (context.format === 'module') { - const dynamicImportTransformed = transformDynamicImport(filePath, result.source.toString()); - if (dynamicImportTransformed) { - result.source = applySourceMap( - dynamicImportTransformed, - url, - ); - } - } - - return result; -}; - -const nodeSupportsDeprecatedLoaders = compareNodeVersion([16, 12, 0]) < 0; - -export const getFormat = nodeSupportsDeprecatedLoaders ? _getFormat : undefined; -export const transformSource = nodeSupportsDeprecatedLoaders ? _transformSource : undefined; diff --git a/src/esm/loaders.ts b/src/esm/loaders.ts deleted file mode 100644 index 872db0792..000000000 --- a/src/esm/loaders.ts +++ /dev/null @@ -1,310 +0,0 @@ -import type { MessagePort } from 'node:worker_threads'; -import path from 'path'; -import { pathToFileURL, fileURLToPath } from 'url'; -import type { - ResolveFnOutput, ResolveHookContext, LoadHook, GlobalPreloadHook, -} from 'module'; -import type { TransformOptions } from 'esbuild'; -import { compareNodeVersion } from '../utils/compare-node-version'; -import { transform, transformDynamicImport } from '../utils/transform'; -import { resolveTsPath } from '../utils/resolve-ts-path'; -import { - applySourceMap, - tsconfigPathsMatcher, - fileMatcher, - tsExtensionsPattern, - isJsonPattern, - getFormatFromFileUrl, - fileProtocol, - type MaybePromise, - type NodeError, -} from './utils.js'; - -const isDirectoryPattern = /\/(?:$|\?)/; - -type NextResolve = ( - specifier: string, - context?: ResolveHookContext, -) => MaybePromise; - -type resolve = ( - specifier: string, - context: ResolveHookContext, - nextResolve: NextResolve, - recursiveCall?: boolean, -) => MaybePromise; - -const isolatedLoader = compareNodeVersion([20, 0, 0]) >= 0; - -type SendToParent = (data: { - type: 'dependency'; - path: string; -}) => void; - -let sendToParent: SendToParent | undefined = process.send ? process.send.bind(process) : undefined; - -/** - * Technically globalPreload is deprecated so it should be in loaders-deprecated - * but it shares a closure with the new load hook - */ -let mainThreadPort: MessagePort | undefined; -const _globalPreload: GlobalPreloadHook = ({ port }) => { - mainThreadPort = port; - sendToParent = port.postMessage.bind(port); - - return ` - const require = getBuiltin('module').createRequire("${import.meta.url}"); - require('tsx/source-map').installSourceMapSupport(port); - if (process.send) { - port.addListener('message', (message) => { - if (message.type === 'dependency') { - process.send(message); - } - }); - } - port.unref(); // Allows process to exit without waiting for port to close - `; -}; - -export const globalPreload = isolatedLoader ? _globalPreload : undefined; - -const resolveExplicitPath = async ( - defaultResolve: NextResolve, - specifier: string, - context: ResolveHookContext, -) => { - const resolved = await defaultResolve(specifier, context); - - if ( - !resolved.format - && resolved.url.startsWith(fileProtocol) - ) { - resolved.format = await getFormatFromFileUrl(resolved.url); - } - - return resolved; -}; - -const extensions = ['.js', '.json', '.ts', '.tsx', '.jsx'] as const; - -async function tryExtensions( - specifier: string, - context: ResolveHookContext, - defaultResolve: NextResolve, -) { - const [specifierWithoutQuery, query] = specifier.split('?'); - let throwError: Error | undefined; - for (const extension of extensions) { - try { - return await resolveExplicitPath( - defaultResolve, - specifierWithoutQuery + extension + (query ? `?${query}` : ''), - context, - ); - } catch (_error) { - if ( - throwError === undefined - && _error instanceof Error - ) { - const { message } = _error; - _error.message = _error.message.replace(`${extension}'`, "'"); - _error.stack = _error.stack!.replace(message, _error.message); - throwError = _error; - } - } - } - - throw throwError; -} - -async function tryDirectory( - specifier: string, - context: ResolveHookContext, - defaultResolve: NextResolve, -) { - const isExplicitDirectory = isDirectoryPattern.test(specifier); - const appendIndex = isExplicitDirectory ? 'index' : '/index'; - const [specifierWithoutQuery, query] = specifier.split('?'); - - try { - return await tryExtensions( - specifierWithoutQuery + appendIndex + (query ? `?${query}` : ''), - context, - defaultResolve, - ); - } catch (_error) { - if (!isExplicitDirectory) { - try { - return await tryExtensions(specifier, context, defaultResolve); - } catch {} - } - - const error = _error as Error; - const { message } = error; - error.message = error.message.replace(`${appendIndex.replace('/', path.sep)}'`, "'"); - error.stack = error.stack!.replace(message, error.message); - throw error; - } -} - -const isRelativePathPattern = /^\.{1,2}\//; - -const supportsNodePrefix = ( - compareNodeVersion([14, 13, 1]) >= 0 - || compareNodeVersion([12, 20, 0]) >= 0 -); - -export const resolve: resolve = async function ( - specifier, - context, - defaultResolve, - recursiveCall, -) { - // Added in v12.20.0 - // https://nodejs.org/api/esm.html#esm_node_imports - if (!supportsNodePrefix && specifier.startsWith('node:')) { - specifier = specifier.slice(5); - } - - // If directory, can be index.js, index.ts, etc. - if (isDirectoryPattern.test(specifier)) { - return await tryDirectory(specifier, context, defaultResolve); - } - - const isPath = ( - specifier.startsWith(fileProtocol) - || isRelativePathPattern.test(specifier) - ); - - if ( - tsconfigPathsMatcher - && !isPath // bare specifier - && !context.parentURL?.includes('/node_modules/') - ) { - const possiblePaths = tsconfigPathsMatcher(specifier); - for (const possiblePath of possiblePaths) { - try { - return await resolve( - pathToFileURL(possiblePath).toString(), - context, - defaultResolve, - ); - } catch {} - } - } - - /** - * Typescript gives .ts, .cts, or .mts priority over actual .js, .cjs, or .mjs extensions - */ - if ( - // !recursiveCall && - tsExtensionsPattern.test(context.parentURL!) - ) { - const tsPaths = resolveTsPath(specifier); - if (tsPaths) { - for (const tsPath of tsPaths) { - try { - return await resolveExplicitPath(defaultResolve, tsPath, context); - // return await resolve(tsPath, context, defaultResolve, true); - } catch (error) { - const { code } = error as NodeError; - if ( - code !== 'ERR_MODULE_NOT_FOUND' - && code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED' - ) { - throw error; - } - } - } - } - } - - try { - return await resolveExplicitPath(defaultResolve, specifier, context); - } catch (error) { - if ( - error instanceof Error - && !recursiveCall - ) { - const { code } = error as NodeError; - if (code === 'ERR_UNSUPPORTED_DIR_IMPORT') { - try { - return await tryDirectory(specifier, context, defaultResolve); - } catch (error_) { - if ((error_ as NodeError).code !== 'ERR_PACKAGE_IMPORT_NOT_DEFINED') { - throw error_; - } - } - } - - if (code === 'ERR_MODULE_NOT_FOUND') { - try { - return await tryExtensions(specifier, context, defaultResolve); - } catch {} - } - } - - throw error; - } -}; - -export const load: LoadHook = async function ( - url, - context, - defaultLoad, -) { - if (sendToParent) { - sendToParent({ - type: 'dependency', - path: url, - }); - } - - if (isJsonPattern.test(url)) { - if (!context.importAssertions) { - context.importAssertions = {}; - } - context.importAssertions.type = 'json'; - } - - const loaded = await defaultLoad(url, context); - - if (!loaded.source) { - return loaded; - } - - const filePath = url.startsWith('file://') ? fileURLToPath(url) : url; - const code = loaded.source.toString(); - - if ( - // Support named imports in JSON modules - loaded.format === 'json' - || tsExtensionsPattern.test(url) - ) { - const transformed = await transform( - code, - filePath, - { - tsconfigRaw: fileMatcher?.(filePath) as TransformOptions['tsconfigRaw'], - }, - ); - - return { - format: 'module', - source: applySourceMap(transformed, url, mainThreadPort), - }; - } - - if (loaded.format === 'module') { - const dynamicImportTransformed = transformDynamicImport(filePath, code); - if (dynamicImportTransformed) { - loaded.source = applySourceMap( - dynamicImportTransformed, - url, - mainThreadPort, - ); - } - } - - return loaded; -}; From 6ac8076f1b43b505b0f757b4b0f5d5ebd08f2482 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Tue, 26 Sep 2023 01:14:11 +0900 Subject: [PATCH 3/6] wip --- README.md | 4 +--- src/cjs/index.ts | 12 ------------ src/esm/index.ts | 11 ----------- 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/README.md b/README.md index b7ae8aad2..ae04d44ad 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,9 @@ - Blazing fast on-demand TypeScript & ESM compilation - Works in both [CommonJS and ESM packages](https://nodejs.org/api/packages.html#type) - Supports next-gen TypeScript extensions (`.cts` & `.mts`) -- Supports `node:` import prefixes - Hides experimental feature warnings - TypeScript REPL - Resolves `tsconfig.json` [`paths`](https://www.typescriptlang.org/tsconfig#paths) -- Tested on Linux & Windows with Node.js v12~20 > **💡 Protip: Looking to bundle your TypeScript project?** > @@ -45,7 +43,7 @@ How does it compare to [ts-node](https://github.com/TypeStrong/ts-node)? Checkou tsx strives to: 1. Enhance Node.js with TypeScript compatibility 2. Improve ESM <-> CJS interoperability -3. Support the latest major version of Node.js v12 and up _(likely to change in the future)_ +3. Support the [LTS versions of Node.js](https://endoflife.date/nodejs) ## Install diff --git a/src/cjs/index.ts b/src/cjs/index.ts index f778cfa74..0116fe3c1 100644 --- a/src/cjs/index.ts +++ b/src/cjs/index.ts @@ -137,20 +137,8 @@ Object.defineProperty(extensions, '.mjs', { enumerable: false, }); -const supportsNodePrefix = ( - compareNodeVersion([16, 0, 0]) >= 0 - || compareNodeVersion([14, 18, 0]) >= 0 -); - -// Add support for "node:" protocol const defaultResolveFilename = Module._resolveFilename.bind(Module); Module._resolveFilename = (request, parent, isMain, options) => { - // Added in v12.20.0 - // https://nodejs.org/api/esm.html#esm_node_imports - if (!supportsNodePrefix && request.startsWith('node:')) { - request = request.slice(5); - } - if ( tsconfigPathsMatcher diff --git a/src/esm/index.ts b/src/esm/index.ts index 872db0792..59200d647 100644 --- a/src/esm/index.ts +++ b/src/esm/index.ts @@ -149,23 +149,12 @@ async function tryDirectory( const isRelativePathPattern = /^\.{1,2}\//; -const supportsNodePrefix = ( - compareNodeVersion([14, 13, 1]) >= 0 - || compareNodeVersion([12, 20, 0]) >= 0 -); - export const resolve: resolve = async function ( specifier, context, defaultResolve, recursiveCall, ) { - // Added in v12.20.0 - // https://nodejs.org/api/esm.html#esm_node_imports - if (!supportsNodePrefix && specifier.startsWith('node:')) { - specifier = specifier.slice(5); - } - // If directory, can be index.js, index.ts, etc. if (isDirectoryPattern.test(specifier)) { return await tryDirectory(specifier, context, defaultResolve); From dd73218070fb344899bdce4710e67fc46ca4bdaa Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Tue, 26 Sep 2023 01:21:58 +0900 Subject: [PATCH 4/6] wip --- src/cjs/index.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/cjs/index.ts b/src/cjs/index.ts index 0116fe3c1..b351c2d26 100644 --- a/src/cjs/index.ts +++ b/src/cjs/index.ts @@ -11,7 +11,6 @@ import type { TransformOptions } from 'esbuild'; import { installSourceMapSupport } from '../source-map'; import { transformSync, transformDynamicImport } from '../utils/transform'; import { resolveTsPath } from '../utils/resolve-ts-path'; -import { compareNodeVersion } from '../utils/compare-node-version'; const isRelativePathPattern = /^\.{1,2}\//; const isTsFilePatten = /\.[cm]?tsx?$/; @@ -31,17 +30,6 @@ const tsconfigPathsMatcher = tsconfig && createPathsMatcher(tsconfig); const applySourceMap = installSourceMapSupport(); -const nodeSupportsImport = ( - // v13.2.0 and higher - compareNodeVersion([13, 2, 0]) >= 0 - - // 12.20.0 ~ 13.0.0 - || ( - compareNodeVersion([12, 20, 0]) >= 0 - && compareNodeVersion([13, 0, 0]) < 0 - ) -); - const extensions = Module._extensions; const defaultLoader = extensions['.js']; @@ -77,7 +65,7 @@ const transformer = ( let code = fs.readFileSync(filePath, 'utf8'); - if (filePath.endsWith('.cjs') && nodeSupportsImport) { + if (filePath.endsWith('.cjs')) { const transformed = transformDynamicImport(filePath, code); if (transformed) { code = applySourceMap(transformed, filePath); From 391dae424268be2de8d86c9ef7484a4abf6d5d0b Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Tue, 31 Oct 2023 18:31:40 +0900 Subject: [PATCH 5/6] wip --- src/esm/loaders.ts | 9 --------- src/utils/node-features.ts | 18 ------------------ 2 files changed, 27 deletions(-) diff --git a/src/esm/loaders.ts b/src/esm/loaders.ts index 4f105e88e..6bde3ea38 100644 --- a/src/esm/loaders.ts +++ b/src/esm/loaders.ts @@ -7,9 +7,6 @@ import type { import type { TransformOptions } from 'esbuild'; import { transform, transformDynamicImport } from '../utils/transform'; import { resolveTsPath } from '../utils/resolve-ts-path'; -import { - supportsNodePrefix, -} from '../utils/node-features'; import { applySourceMap, tsconfigPathsMatcher, @@ -164,12 +161,6 @@ export const resolve: resolve = async function ( defaultResolve, recursiveCall, ) { - // Added in v12.20.0 - // https://nodejs.org/api/esm.html#esm_node_imports - if (!supportsNodePrefix && specifier.startsWith('node:')) { - specifier = specifier.slice(5); - } - // If directory, can be index.js, index.ts, etc. if (isDirectoryPattern.test(specifier)) { return await tryDirectory(specifier, context, defaultResolve); diff --git a/src/utils/node-features.ts b/src/utils/node-features.ts index d9c23b14d..825017182 100644 --- a/src/utils/node-features.ts +++ b/src/utils/node-features.ts @@ -8,24 +8,6 @@ const compareNodeVersion = (version: Version) => ( || nodeVersion[2] - version[2] ); -export const nodeSupportsImport = ( - // v13.2.0 and higher - compareNodeVersion([13, 2, 0]) >= 0 - - // 12.20.0 ~ 13.0.0 - || ( - compareNodeVersion([12, 20, 0]) >= 0 - && compareNodeVersion([13, 0, 0]) < 0 - ) -); - -export const supportsNodePrefix = ( - compareNodeVersion([16, 0, 0]) >= 0 - || compareNodeVersion([14, 18, 0]) >= 0 -); - -export const nodeSupportsDeprecatedLoaders = compareNodeVersion([16, 12, 0]) < 0; - /** * Node.js loaders are isolated from v20 * https://github.com/nodejs/node/issues/49455#issuecomment-1703812193 From 449915d9d98748075c30e8e39c59afdf998ad308 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Fri, 3 Nov 2023 23:01:52 +0900 Subject: [PATCH 6/6] engines --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index dae629516..7521db615 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,9 @@ "lint-staged": { "*.{js,ts,mjs,mts,cjs,cts,json}": "pnpm lint" }, + "engines": { + "node": ">=18.0.0" + }, "dependencies": { "esbuild": "~0.18.20", "get-tsconfig": "^4.7.2",