From afde82a5f267e92ea20a9740b305dd9724e51c73 Mon Sep 17 00:00:00 2001 From: Bradley Farias Date: Fri, 11 Mar 2022 11:20:57 -0600 Subject: [PATCH 01/10] esm: make extension-less errors in type:module actionable --- lib/internal/errors.js | 10 ++++-- lib/internal/modules/esm/formats.js | 2 +- lib/internal/modules/esm/get_format.js | 35 +++++++++++++------ lib/internal/modules/esm/resolve.js | 4 +++ .../test-esm-unknown-or-no-extension.js | 6 +++- 5 files changed, 41 insertions(+), 16 deletions(-) diff --git a/lib/internal/errors.js b/lib/internal/errors.js index c0834aab9c070c..dce159b94cc198 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -1594,9 +1594,13 @@ E('ERR_UNHANDLED_ERROR', E('ERR_UNKNOWN_BUILTIN_MODULE', 'No such built-in module: %s', Error); E('ERR_UNKNOWN_CREDENTIAL', '%s identifier does not exist: %s', Error); E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s', TypeError); -E('ERR_UNKNOWN_FILE_EXTENSION', - 'Unknown file extension "%s" for %s', - TypeError); +E('ERR_UNKNOWN_FILE_EXTENSION', (ext, path, suggestion) => { + let msg = `Unknown file extension "${ext}" for ${path}`; + if (suggestion) { + msg += `. ${suggestion}`; + } + return msg; +}, TypeError); E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s for URL %s', RangeError); E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s', TypeError); diff --git a/lib/internal/modules/esm/formats.js b/lib/internal/modules/esm/formats.js index f9da01402e7f62..fc991156832cba 100644 --- a/lib/internal/modules/esm/formats.js +++ b/lib/internal/modules/esm/formats.js @@ -30,7 +30,7 @@ if (experimentalWasmModules) { } /** - * @param {string} mime + * @param {string} mime * @returns {string | null} */ function mimeToFormat(mime) { diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index 91f3c9edeb10f5..a4c8164311ff68 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -7,7 +7,7 @@ const { PromisePrototypeThen, PromiseResolve, } = primordials; -const { extname } = require('path'); +const { extname, basename } = require('path'); const { getOptionValue } = require('internal/options'); const { fetchModule } = require('internal/modules/esm/fetch_module'); const { @@ -20,7 +20,7 @@ const experimentalNetworkImports = getOptionValue('--experimental-network-imports'); const experimentalSpecifierResolution = getOptionValue('--experimental-specifier-resolution'); -const { getPackageType } = require('internal/modules/esm/resolve'); +const { getPackageType, getPackageScopeConfig } = require('internal/modules/esm/resolve'); const { URL, fileURLToPath } = require('internal/url'); const { ERR_UNKNOWN_FILE_EXTENSION } = require('internal/errors').codes; @@ -33,7 +33,8 @@ const protocolHandlers = ObjectAssign(ObjectCreate(null), { }); /** - * @param {URL} parsed + * @param {URL} parsed + * @param {{parentURL: string}} context * @returns {string | null} */ function getDataProtocolModuleFormat(parsed) { @@ -46,13 +47,14 @@ function getDataProtocolModuleFormat(parsed) { } /** - * @param {URL} url - * @param {{parentURL: string}} context - * @param {boolean} ignoreErrors + * @param {URL} url + * @param {{parentURL: string}} context + * @param {boolean} ignoreErrors * @returns {string} */ function getFileProtocolModuleFormat(url, context, ignoreErrors) { - const ext = extname(url.pathname); + const filepath = fileURLToPath(url); + const ext = extname(filepath); if (ext === '.js') { return getPackageType(url) === 'module' ? 'module' : 'commonjs'; } @@ -63,14 +65,25 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) { if (experimentalSpecifierResolution !== 'node') { // Explicit undefined return indicates load hook should rerun format check if (ignoreErrors) return undefined; - throw new ERR_UNKNOWN_FILE_EXTENSION(ext, fileURLToPath(url)); + let suggestion = ''; + if (getPackageType(url) === 'module' && ext === '') { + const config = getPackageScopeConfig(url); + const fileBasename = basename(filepath); + suggestion = 'Extension-less files are disabled inside of ' + + '"type":"module" package.json contexts. The package.json file ' + + `${config.pjsonPath} caused this "type":"module" context. Try ` + + `changing ${filepath} to have a file extension. Note the "bin" ` + + 'field of package.json can point to a file with an extension E.G. ' + + `{"type":"module","bin":{"${fileBasename}":"${fileBasename}.js"}}` + } + throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath, suggestion); } return getLegacyExtensionFormat(ext) ?? null; } /** - * @param {URL} url + * @param {URL} url * @param {{parentURL: string}} context * @returns {Promise | undefined} only works when enabled */ @@ -86,7 +99,7 @@ function getHttpProtocolModuleFormat(url, context) { } /** - * @param {URL | URL['href']} url + * @param {URL | URL['href']} url * @param {{parentURL: string}} context * @returns {Promise | string | undefined} only works when enabled */ @@ -98,7 +111,7 @@ function defaultGetFormatWithoutErrors(url, context) { } /** - * @param {URL | URL['href']} url + * @param {URL | URL['href']} url * @param {{parentURL: string}} context * @returns {Promise | string | undefined} only works when enabled */ diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js index 5e00b53a65f7f5..1dd6de82e0b6c2 100644 --- a/lib/internal/modules/esm/resolve.js +++ b/lib/internal/modules/esm/resolve.js @@ -222,6 +222,10 @@ function getPackageConfig(path, specifier, base) { return packageConfig; } +function getPackageScopePath(resolved) { + +} + /** * @param {URL | string} resolved * @returns {PackageConfig} diff --git a/test/es-module/test-esm-unknown-or-no-extension.js b/test/es-module/test-esm-unknown-or-no-extension.js index 3b1802a4dcedbd..470400d0cd63d5 100644 --- a/test/es-module/test-esm-unknown-or-no-extension.js +++ b/test/es-module/test-esm-unknown-or-no-extension.js @@ -31,6 +31,10 @@ const assert = require('assert'); assert.strictEqual(code, 1); assert.strictEqual(signal, null); assert.strictEqual(stdout, ''); - assert.ok(stderr.indexOf('ERR_UNKNOWN_FILE_EXTENSION') !== -1); + assert.ok(stderr.includes('ERR_UNKNOWN_FILE_EXTENSION')); + if (fixturePath.includes('noext')) { + // check for explaination to users + assert.ok(stderr.includes('Extension-less')); + } })); }); From 8cba2a8b2adbb5a55cb036718a54ae11c0c1d151 Mon Sep 17 00:00:00 2001 From: Bradley Farias Date: Fri, 11 Mar 2022 11:25:54 -0600 Subject: [PATCH 02/10] fixup: linter --- lib/internal/modules/esm/formats.js | 2 +- lib/internal/modules/esm/get_format.js | 17 ++++++++--------- lib/internal/modules/esm/resolve.js | 4 ---- .../test-esm-unknown-or-no-extension.js | 2 +- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/lib/internal/modules/esm/formats.js b/lib/internal/modules/esm/formats.js index fc991156832cba..f9da01402e7f62 100644 --- a/lib/internal/modules/esm/formats.js +++ b/lib/internal/modules/esm/formats.js @@ -30,7 +30,7 @@ if (experimentalWasmModules) { } /** - * @param {string} mime + * @param {string} mime * @returns {string | null} */ function mimeToFormat(mime) { diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index a4c8164311ff68..b1c0427870a4dc 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -33,8 +33,7 @@ const protocolHandlers = ObjectAssign(ObjectCreate(null), { }); /** - * @param {URL} parsed - * @param {{parentURL: string}} context + * @param {URL} parsed * @returns {string | null} */ function getDataProtocolModuleFormat(parsed) { @@ -47,9 +46,9 @@ function getDataProtocolModuleFormat(parsed) { } /** - * @param {URL} url - * @param {{parentURL: string}} context - * @param {boolean} ignoreErrors + * @param {URL} url + * @param {{parentURL: string}} context + * @param {boolean} ignoreErrors * @returns {string} */ function getFileProtocolModuleFormat(url, context, ignoreErrors) { @@ -74,7 +73,7 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) { `${config.pjsonPath} caused this "type":"module" context. Try ` + `changing ${filepath} to have a file extension. Note the "bin" ` + 'field of package.json can point to a file with an extension E.G. ' + - `{"type":"module","bin":{"${fileBasename}":"${fileBasename}.js"}}` + `{"type":"module","bin":{"${fileBasename}":"${fileBasename}.js"}}`; } throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath, suggestion); } @@ -83,7 +82,7 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) { } /** - * @param {URL} url + * @param {URL} url * @param {{parentURL: string}} context * @returns {Promise | undefined} only works when enabled */ @@ -99,7 +98,7 @@ function getHttpProtocolModuleFormat(url, context) { } /** - * @param {URL | URL['href']} url + * @param {URL | URL['href']} url * @param {{parentURL: string}} context * @returns {Promise | string | undefined} only works when enabled */ @@ -111,7 +110,7 @@ function defaultGetFormatWithoutErrors(url, context) { } /** - * @param {URL | URL['href']} url + * @param {URL | URL['href']} url * @param {{parentURL: string}} context * @returns {Promise | string | undefined} only works when enabled */ diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js index 1dd6de82e0b6c2..5e00b53a65f7f5 100644 --- a/lib/internal/modules/esm/resolve.js +++ b/lib/internal/modules/esm/resolve.js @@ -222,10 +222,6 @@ function getPackageConfig(path, specifier, base) { return packageConfig; } -function getPackageScopePath(resolved) { - -} - /** * @param {URL | string} resolved * @returns {PackageConfig} diff --git a/test/es-module/test-esm-unknown-or-no-extension.js b/test/es-module/test-esm-unknown-or-no-extension.js index 470400d0cd63d5..29c4f55e4f7eb6 100644 --- a/test/es-module/test-esm-unknown-or-no-extension.js +++ b/test/es-module/test-esm-unknown-or-no-extension.js @@ -33,7 +33,7 @@ const assert = require('assert'); assert.strictEqual(stdout, ''); assert.ok(stderr.includes('ERR_UNKNOWN_FILE_EXTENSION')); if (fixturePath.includes('noext')) { - // check for explaination to users + // Check for explaination to users assert.ok(stderr.includes('Extension-less')); } })); From 47188720352c50b8b43a87ba7d7f39d3afcd0e06 Mon Sep 17 00:00:00 2001 From: Bradley Farias Date: Fri, 11 Mar 2022 13:45:52 -0600 Subject: [PATCH 03/10] fixup: Update lib/internal/modules/esm/get_format.js Co-authored-by: Antoine du Hamel --- lib/internal/modules/esm/get_format.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index b1c0427870a4dc..1c7a3d266fc17a 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -72,7 +72,7 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) { '"type":"module" package.json contexts. The package.json file ' + `${config.pjsonPath} caused this "type":"module" context. Try ` + `changing ${filepath} to have a file extension. Note the "bin" ` + - 'field of package.json can point to a file with an extension E.G. ' + + 'field of package.json can point to a file with an extension E.G. ' + `{"type":"module","bin":{"${fileBasename}":"${fileBasename}.js"}}`; } throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath, suggestion); From 33af85889d787919480802e7354d989d04b0e6c5 Mon Sep 17 00:00:00 2001 From: Bradley Farias Date: Fri, 11 Mar 2022 17:07:44 -0600 Subject: [PATCH 04/10] fixup: Update test/es-module/test-esm-unknown-or-no-extension.js Co-authored-by: Mohammed Keyvanzadeh --- test/es-module/test-esm-unknown-or-no-extension.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/es-module/test-esm-unknown-or-no-extension.js b/test/es-module/test-esm-unknown-or-no-extension.js index 29c4f55e4f7eb6..c43fa16d658bdc 100644 --- a/test/es-module/test-esm-unknown-or-no-extension.js +++ b/test/es-module/test-esm-unknown-or-no-extension.js @@ -33,7 +33,7 @@ const assert = require('assert'); assert.strictEqual(stdout, ''); assert.ok(stderr.includes('ERR_UNKNOWN_FILE_EXTENSION')); if (fixturePath.includes('noext')) { - // Check for explaination to users + // Check for explanation to users assert.ok(stderr.includes('Extension-less')); } })); From 8a9b2b348fcb2ca98ddf20adfca364cd01df5b03 Mon Sep 17 00:00:00 2001 From: Bradley Farias Date: Sat, 12 Mar 2022 08:29:39 -0600 Subject: [PATCH 05/10] fixup: Update lib/internal/modules/esm/get_format.js Co-authored-by: Geoffrey Booth <456802+GeoffreyBooth@users.noreply.github.com> --- lib/internal/modules/esm/get_format.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index 1c7a3d266fc17a..41ec3f2e9c8f8d 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -72,7 +72,7 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) { '"type":"module" package.json contexts. The package.json file ' + `${config.pjsonPath} caused this "type":"module" context. Try ` + `changing ${filepath} to have a file extension. Note the "bin" ` + - 'field of package.json can point to a file with an extension E.G. ' + + 'field of package.json can point to a file with an extension, for example ' + `{"type":"module","bin":{"${fileBasename}":"${fileBasename}.js"}}`; } throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath, suggestion); From 091e5a3b08d1b3148e9d53160d7780f96d9f6915 Mon Sep 17 00:00:00 2001 From: Bradley Farias Date: Sat, 12 Mar 2022 08:58:52 -0600 Subject: [PATCH 06/10] fixup: reviews and make suggestion copy paste friendly --- lib/internal/modules/esm/formats.js | 4 --- lib/internal/modules/esm/get_format.js | 33 ++++------------------- lib/internal/modules/esm/resolve.js | 1 - test/es-module/test-esm-basic-imports.mjs | 7 ++--- 4 files changed, 7 insertions(+), 38 deletions(-) diff --git a/lib/internal/modules/esm/formats.js b/lib/internal/modules/esm/formats.js index f9da01402e7f62..6f145931a1eed4 100644 --- a/lib/internal/modules/esm/formats.js +++ b/lib/internal/modules/esm/formats.js @@ -29,10 +29,6 @@ if (experimentalWasmModules) { extensionFormatMap['.wasm'] = legacyExtensionFormatMap['.wasm'] = 'wasm'; } -/** - * @param {string} mime - * @returns {string | null} - */ function mimeToFormat(mime) { if ( RegExpPrototypeTest( diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index 41ec3f2e9c8f8d..95c91db369fdac 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -6,8 +6,9 @@ const { ObjectPrototypeHasOwnProperty, PromisePrototypeThen, PromiseResolve, + StringPrototypeSlice, } = primordials; -const { extname, basename } = require('path'); +const { basename, extname, relative } = require('path'); const { getOptionValue } = require('internal/options'); const { fetchModule } = require('internal/modules/esm/fetch_module'); const { @@ -32,10 +33,6 @@ const protocolHandlers = ObjectAssign(ObjectCreate(null), { 'node:'() { return 'builtin'; }, }); -/** - * @param {URL} parsed - * @returns {string | null} - */ function getDataProtocolModuleFormat(parsed) { const { 1: mime } = RegExpPrototypeExec( /^([^/]+\/[^;,]+)(?:[^,]*?)(;base64)?,/, @@ -45,12 +42,6 @@ function getDataProtocolModuleFormat(parsed) { return mimeToFormat(mime); } -/** - * @param {URL} url - * @param {{parentURL: string}} context - * @param {boolean} ignoreErrors - * @returns {string} - */ function getFileProtocolModuleFormat(url, context, ignoreErrors) { const filepath = fileURLToPath(url); const ext = extname(filepath); @@ -68,12 +59,13 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) { if (getPackageType(url) === 'module' && ext === '') { const config = getPackageScopeConfig(url); const fileBasename = basename(filepath); - suggestion = 'Extension-less files are disabled inside of ' + + const relativePath = StringPrototypeSlice(relative(config.pjsonPath, filepath), 1); + suggestion = 'Extension-less files are unsupported inside of ' + '"type":"module" package.json contexts. The package.json file ' + `${config.pjsonPath} caused this "type":"module" context. Try ` + `changing ${filepath} to have a file extension. Note the "bin" ` + 'field of package.json can point to a file with an extension, for example ' + - `{"type":"module","bin":{"${fileBasename}":"${fileBasename}.js"}}`; + `{"type":"module","bin":{"${fileBasename}":"${relativePath}.js"}}`; } throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath, suggestion); } @@ -81,11 +73,6 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) { return getLegacyExtensionFormat(ext) ?? null; } -/** - * @param {URL} url - * @param {{parentURL: string}} context - * @returns {Promise | undefined} only works when enabled - */ function getHttpProtocolModuleFormat(url, context) { if (experimentalNetworkImports) { return PromisePrototypeThen( @@ -97,11 +84,6 @@ function getHttpProtocolModuleFormat(url, context) { } } -/** - * @param {URL | URL['href']} url - * @param {{parentURL: string}} context - * @returns {Promise | string | undefined} only works when enabled - */ function defaultGetFormatWithoutErrors(url, context) { const parsed = new URL(url); if (!ObjectPrototypeHasOwnProperty(protocolHandlers, parsed.protocol)) @@ -109,11 +91,6 @@ function defaultGetFormatWithoutErrors(url, context) { return protocolHandlers[parsed.protocol](parsed, context, true); } -/** - * @param {URL | URL['href']} url - * @param {{parentURL: string}} context - * @returns {Promise | string | undefined} only works when enabled - */ function defaultGetFormat(url, context) { const parsed = new URL(url); return ObjectPrototypeHasOwnProperty(protocolHandlers, parsed.protocol) ? diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js index 5e00b53a65f7f5..7751fa756e198b 100644 --- a/lib/internal/modules/esm/resolve.js +++ b/lib/internal/modules/esm/resolve.js @@ -79,7 +79,6 @@ const DEFAULT_CONDITIONS_SET = new SafeSet(DEFAULT_CONDITIONS); * @typedef {string | string[] | Record} Exports * @typedef {'module' | 'commonjs'} PackageType * @typedef {{ - * pjsonPath: string, * exports?: ExportConfig; * name?: string; * main?: string; diff --git a/test/es-module/test-esm-basic-imports.mjs b/test/es-module/test-esm-basic-imports.mjs index 173f80ac955ff1..5009fbadb39657 100644 --- a/test/es-module/test-esm-basic-imports.mjs +++ b/test/es-module/test-esm-basic-imports.mjs @@ -1,10 +1,7 @@ import '../common/index.mjs'; import assert from 'assert'; import ok from '../fixtures/es-modules/test-esm-ok.mjs'; -import * as okShebangNs from './test-esm-shebang.mjs'; -// encode the '.' -import * as okShebangPercentNs from './test-esm-shebang%2emjs'; +import okShebang from './test-esm-shebang.mjs'; assert(ok); -assert(okShebangNs.default); -assert.strict.equal(okShebangNs, okShebangPercentNs); +assert(okShebang); From 5f5af00cbbbccdde950b0923dbfae188e7a4773a Mon Sep 17 00:00:00 2001 From: Bradley Farias Date: Mon, 14 Mar 2022 13:32:41 -0500 Subject: [PATCH 07/10] Update lib/internal/modules/esm/get_format.js Co-authored-by: Antoine du Hamel --- lib/internal/modules/esm/get_format.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index 95c91db369fdac..55e73f6ca53033 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -60,7 +60,7 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) { const config = getPackageScopeConfig(url); const fileBasename = basename(filepath); const relativePath = StringPrototypeSlice(relative(config.pjsonPath, filepath), 1); - suggestion = 'Extension-less files are unsupported inside of ' + + suggestion = 'Loading extension-less files is not supported inside of ' + '"type":"module" package.json contexts. The package.json file ' + `${config.pjsonPath} caused this "type":"module" context. Try ` + `changing ${filepath} to have a file extension. Note the "bin" ` + From efc80ce8eb4bae95cd3b2dfd65245918a167f1ec Mon Sep 17 00:00:00 2001 From: Bradley Farias Date: Mon, 14 Mar 2022 13:54:20 -0500 Subject: [PATCH 08/10] Update lib/internal/modules/esm/get_format.js Co-authored-by: Jordan Harband --- lib/internal/modules/esm/get_format.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index 55e73f6ca53033..a7b2fa35f34372 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -60,7 +60,7 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) { const config = getPackageScopeConfig(url); const fileBasename = basename(filepath); const relativePath = StringPrototypeSlice(relative(config.pjsonPath, filepath), 1); - suggestion = 'Loading extension-less files is not supported inside of ' + + suggestion = 'Loading extensionless files is not supported inside of ' + '"type":"module" package.json contexts. The package.json file ' + `${config.pjsonPath} caused this "type":"module" context. Try ` + `changing ${filepath} to have a file extension. Note the "bin" ` + From 57b980d50c45c49d5d95b1c238e07b8a67acbe7d Mon Sep 17 00:00:00 2001 From: Bradley Farias Date: Mon, 14 Mar 2022 13:54:57 -0500 Subject: [PATCH 09/10] fixup: extensionless --- doc/api/esm.md | 2 +- test/es-module/test-esm-unknown-or-no-extension.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/esm.md b/doc/api/esm.md index 85cf281370dcc0..90cca55946b1af 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -1091,7 +1091,7 @@ async function getPackageType(url) { // required by the spec // this simple truthy check for whether `url` contains a file extension will // work for most projects but does not cover some edge-cases (such as - // extension-less files or a url ending in a trailing space) + // extensionless files or a url ending in a trailing space) const isFilePath = !!extname(url); // If it is a file path, get the directory it's in const dir = isFilePath ? diff --git a/test/es-module/test-esm-unknown-or-no-extension.js b/test/es-module/test-esm-unknown-or-no-extension.js index c43fa16d658bdc..40f840ad670cf3 100644 --- a/test/es-module/test-esm-unknown-or-no-extension.js +++ b/test/es-module/test-esm-unknown-or-no-extension.js @@ -34,7 +34,7 @@ const assert = require('assert'); assert.ok(stderr.includes('ERR_UNKNOWN_FILE_EXTENSION')); if (fixturePath.includes('noext')) { // Check for explanation to users - assert.ok(stderr.includes('Extension-less')); + assert.ok(stderr.includes('extensionless')); } })); }); From 6c334d74e08ebe12490ae8149c47cfcf31f54ab6 Mon Sep 17 00:00:00 2001 From: Bradley Farias Date: Mon, 14 Mar 2022 14:28:22 -0500 Subject: [PATCH 10/10] fix rebase --- lib/internal/modules/esm/formats.js | 4 ++++ lib/internal/modules/esm/get_format.js | 25 +++++++++++++++++++++++ lib/internal/modules/esm/resolve.js | 9 ++++---- test/es-module/test-esm-basic-imports.mjs | 7 +++++-- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/lib/internal/modules/esm/formats.js b/lib/internal/modules/esm/formats.js index 6f145931a1eed4..f9da01402e7f62 100644 --- a/lib/internal/modules/esm/formats.js +++ b/lib/internal/modules/esm/formats.js @@ -29,6 +29,10 @@ if (experimentalWasmModules) { extensionFormatMap['.wasm'] = legacyExtensionFormatMap['.wasm'] = 'wasm'; } +/** + * @param {string} mime + * @returns {string | null} + */ function mimeToFormat(mime) { if ( RegExpPrototypeTest( diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index a7b2fa35f34372..950a769227c03f 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -33,6 +33,10 @@ const protocolHandlers = ObjectAssign(ObjectCreate(null), { 'node:'() { return 'builtin'; }, }); +/** + * @param {URL} parsed + * @returns {string | null} + */ function getDataProtocolModuleFormat(parsed) { const { 1: mime } = RegExpPrototypeExec( /^([^/]+\/[^;,]+)(?:[^,]*?)(;base64)?,/, @@ -42,6 +46,12 @@ function getDataProtocolModuleFormat(parsed) { return mimeToFormat(mime); } +/** + * @param {URL} url + * @param {{parentURL: string}} context + * @param {boolean} ignoreErrors + * @returns {string} + */ function getFileProtocolModuleFormat(url, context, ignoreErrors) { const filepath = fileURLToPath(url); const ext = extname(filepath); @@ -73,6 +83,11 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) { return getLegacyExtensionFormat(ext) ?? null; } +/** + * @param {URL} url + * @param {{parentURL: string}} context + * @returns {Promise | undefined} only works when enabled + */ function getHttpProtocolModuleFormat(url, context) { if (experimentalNetworkImports) { return PromisePrototypeThen( @@ -84,6 +99,11 @@ function getHttpProtocolModuleFormat(url, context) { } } +/** + * @param {URL | URL['href']} url + * @param {{parentURL: string}} context + * @returns {Promise | string | undefined} only works when enabled + */ function defaultGetFormatWithoutErrors(url, context) { const parsed = new URL(url); if (!ObjectPrototypeHasOwnProperty(protocolHandlers, parsed.protocol)) @@ -91,6 +111,11 @@ function defaultGetFormatWithoutErrors(url, context) { return protocolHandlers[parsed.protocol](parsed, context, true); } +/** + * @param {URL | URL['href']} url + * @param {{parentURL: string}} context + * @returns {Promise | string | undefined} only works when enabled + */ function defaultGetFormat(url, context) { const parsed = new URL(url); return ObjectPrototypeHasOwnProperty(protocolHandlers, parsed.protocol) ? diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js index 7751fa756e198b..59d3bc1723e074 100644 --- a/lib/internal/modules/esm/resolve.js +++ b/lib/internal/modules/esm/resolve.js @@ -79,10 +79,11 @@ const DEFAULT_CONDITIONS_SET = new SafeSet(DEFAULT_CONDITIONS); * @typedef {string | string[] | Record} Exports * @typedef {'module' | 'commonjs'} PackageType * @typedef {{ - * exports?: ExportConfig; - * name?: string; - * main?: string; - * type?: PackageType; + * pjsonPath: string, + * exports?: ExportConfig, + * name?: string, + * main?: string, + * type?: PackageType, * }} PackageConfig */ diff --git a/test/es-module/test-esm-basic-imports.mjs b/test/es-module/test-esm-basic-imports.mjs index 5009fbadb39657..173f80ac955ff1 100644 --- a/test/es-module/test-esm-basic-imports.mjs +++ b/test/es-module/test-esm-basic-imports.mjs @@ -1,7 +1,10 @@ import '../common/index.mjs'; import assert from 'assert'; import ok from '../fixtures/es-modules/test-esm-ok.mjs'; -import okShebang from './test-esm-shebang.mjs'; +import * as okShebangNs from './test-esm-shebang.mjs'; +// encode the '.' +import * as okShebangPercentNs from './test-esm-shebang%2emjs'; assert(ok); -assert(okShebang); +assert(okShebangNs.default); +assert.strict.equal(okShebangNs, okShebangPercentNs);