GeezerVison is showing github.com — module: add specific error for dir import · nodejs/node@35aae31
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/errors.md +16Lines changed: 16 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -2045,6 +2045,20 @@ An attempt was made to load a module with an unknown or unsupported format. | 2045 | 2045 | An invalid or unknown process signal was passed to an API expecting a valid | 2046 | 2046 | signal (such as [`subprocess.kill()`][]). | 2047 | 2047 |
| | 2048 | +<a id="ERR_UNSUPPORTED_DIR_IMPORT"></a> | | 2049 | +### `ERR_UNSUPPORTED_DIR_IMPORT` | | 2050 | + | | 2051 | +`import` a directory URL is unsupported. Instead, you can | | 2052 | +[self-reference a package using its name][] and [define a custom subpath][] in | | 2053 | +the `"exports"` field of the `package.json` file. | | 2054 | + | | 2055 | +<!-- eslint-skip --> | | 2056 | +```js | | 2057 | +import './'; // unsupported | | 2058 | +import './index.js'; // supported | | 2059 | +import 'package-name'; // supported | | 2060 | +``` | | 2061 | + | 2048 | 2062 | <a id="ERR_UNSUPPORTED_ESM_URL_SCHEME"></a> | 2049 | 2063 | ### `ERR_UNSUPPORTED_ESM_URL_SCHEME` | 2050 | 2064 |
| @@ -2604,3 +2618,5 @@ such as `process.stdout.on('data')`. | 2604 | 2618 | [Subresource Integrity specification]: https://www.w3.org/TR/SRI/#the-integrity-attribute | 2605 | 2619 | [try-catch]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch | 2606 | 2620 | [vm]: vm.html | | 2621 | +[self-reference a package using its name]: esm.html#esm_self_referencing_a_package_using_its_name | | 2622 | +[define a custom subpath]: esm.html#esm_subpath_exports |
Collapse file Copy file name to clipboardExpand all lines: doc/api/esm.md +3-2Lines changed: 3 additions & 2 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -1603,8 +1603,9 @@ The resolver can throw the following errors: | 1603 | 1603 | > 1. If _resolvedURL_ contains any percent encodings of _"/"_ or _"\\"_ (_"%2f"_ | 1604 | 1604 | > and _"%5C"_ respectively), then | 1605 | 1605 | > 1. Throw an _Invalid Module Specifier_ error. | 1606 | | -> 1. If _resolvedURL_ does not end with a trailing _"/"_ and the file at | 1607 | | -> _resolvedURL_ does not exist, then | | 1606 | +> 1. If the file at _resolvedURL_ is a directory, then | | 1607 | +> 1. Throw an _Unsupported Directory Import_ error. | | 1608 | +> 1. If the file at _resolvedURL_ does not exist, then | 1608 | 1609 | > 1. Throw a _Module Not Found_ error. | 1609 | 1610 | > 1. Set _resolvedURL_ to the real path of _resolvedURL_. | 1610 | 1611 | > 1. Let _format_ be the result of **ESM_FORMAT**(_resolvedURL_). | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/errors.js +2Lines changed: 2 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -1411,6 +1411,8 @@ E('ERR_UNKNOWN_FILE_EXTENSION', | 1411 | 1411 | TypeError); | 1412 | 1412 | E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s', RangeError); | 1413 | 1413 | E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s', TypeError); | | 1414 | +E('ERR_UNSUPPORTED_DIR_IMPORT', "Directory import '%s' is not supported " + | | 1415 | +'resolving ES modules, imported from %s', Error); | 1414 | 1416 | E('ERR_UNSUPPORTED_ESM_URL_SCHEME', 'Only file and data URLs are supported ' + | 1415 | 1417 | 'by the default ESM loader', Error); | 1416 | 1418 |
| |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/resolve.js +12-4Lines changed: 12 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -12,6 +12,7 @@ const { | 12 | 12 | RegExp, | 13 | 13 | SafeMap, | 14 | 14 | SafeSet, | | 15 | + String, | 15 | 16 | StringPrototypeEndsWith, | 16 | 17 | StringPrototypeIncludes, | 17 | 18 | StringPrototypeIndexOf, | @@ -48,6 +49,7 @@ const { | 48 | 49 | ERR_INVALID_PACKAGE_TARGET, | 49 | 50 | ERR_MODULE_NOT_FOUND, | 50 | 51 | ERR_PACKAGE_PATH_NOT_EXPORTED, | | 52 | + ERR_UNSUPPORTED_DIR_IMPORT, | 51 | 53 | ERR_UNSUPPORTED_ESM_URL_SCHEME, | 52 | 54 | } = require('internal/errors').codes; | 53 | 55 |
| @@ -270,10 +272,15 @@ function finalizeResolution(resolved, base) { | 270 | 272 | resolved.pathname, fileURLToPath(base), 'module'); | 271 | 273 | } | 272 | 274 |
| 273 | | - if (StringPrototypeEndsWith(resolved.pathname, '/')) return resolved; | 274 | 275 | const path = fileURLToPath(resolved); | 275 | | - | 276 | | - if (!tryStatSync(path).isFile()) { | | 276 | + const stats = tryStatSync(path); | | 277 | + | | 278 | + if (stats.isDirectory()) { | | 279 | + const err = new ERR_UNSUPPORTED_DIR_IMPORT( | | 280 | + path || resolved.pathname, fileURLToPath(base)); | | 281 | + err.url = String(resolved); | | 282 | + throw err; | | 283 | + } else if (!stats.isFile()) { | 277 | 284 | throw new ERR_MODULE_NOT_FOUND( | 278 | 285 | path || resolved.pathname, fileURLToPath(base), 'module'); | 279 | 286 | } | @@ -749,7 +756,8 @@ function defaultResolve(specifier, context = {}, defaultResolveUnused) { | 749 | 756 | } catch (error) { | 750 | 757 | // Try to give the user a hint of what would have been the | 751 | 758 | // resolved CommonJS module | 752 | | - if (error.code === 'ERR_MODULE_NOT_FOUND') { | | 759 | + if (error.code === 'ERR_MODULE_NOT_FOUND' || | | 760 | + error.code === 'ERR_UNSUPPORTED_DIR_IMPORT') { | 753 | 761 | const found = resolveAsCommonJS(specifier, parentURL); | 754 | 762 | if (found) { | 755 | 763 | // Modify the stack and message string to include the hint | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/translators.js +8-1Lines changed: 8 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
| 5 | 5 | const { | 6 | 6 | JSONParse, | 7 | 7 | ObjectKeys, | | 8 | + PromisePrototypeCatch, | | 9 | + PromiseReject, | 8 | 10 | SafeMap, | 9 | 11 | StringPrototypeReplace, | 10 | 12 | } = primordials; | @@ -58,7 +60,12 @@ function createImportMetaResolve(defaultParentUrl) { | 58 | 60 | if (!esmLoader) { | 59 | 61 | esmLoader = require('internal/process/esm_loader').ESMLoader; | 60 | 62 | } | 61 | | - return esmLoader.resolve(specifier, parentUrl); | | 63 | + return PromisePrototypeCatch( | | 64 | + esmLoader.resolve(specifier, parentUrl), | | 65 | + (error) => ( | | 66 | + error.code === 'ERR_UNSUPPORTED_DIR_IMPORT' ? | | 67 | + error.url : PromiseReject(error)) | | 68 | + ); | 62 | 69 | }; | 63 | 70 | } | 64 | 71 |
| |
Collapse file Copy file name to clipboardExpand all lines: test/es-module/test-esm-exports.mjs +6-2Lines changed: 6 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -141,9 +141,13 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js'; | 141 | 141 | ]); | 142 | 142 |
| 143 | 143 | if (!isRequire) { | | 144 | + const onDirectoryImport = (err) => { | | 145 | + strictEqual(err.code, 'ERR_UNSUPPORTED_DIR_IMPORT'); | | 146 | + assertStartsWith(err.message, 'Directory import'); | | 147 | + }; | 144 | 148 | notFoundExports.set('pkgexports/subpath/file', 'pkgexports/subpath/file'); | 145 | | - notFoundExports.set('pkgexports/subpath/dir1', 'pkgexports/subpath/dir1'); | 146 | | - notFoundExports.set('pkgexports/subpath/dir2', 'pkgexports/subpath/dir2'); | | 149 | + loadFixture('pkgexports/subpath/dir1').catch(mustCall(onDirectoryImport)); | | 150 | + loadFixture('pkgexports/subpath/dir2').catch(mustCall(onDirectoryImport)); | 147 | 151 | } | 148 | 152 |
| 149 | 153 | for (const [specifier, request] of notFoundExports) { | |
Collapse file Copy file name to clipboardExpand all lines: test/es-module/test-esm-main-lookup.mjs +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -6,7 +6,7 @@ async function main() { | 6 | 6 | try { | 7 | 7 | mod = await import('../fixtures/es-modules/pjson-main'); | 8 | 8 | } catch (e) { | 9 | | - assert.strictEqual(e.code, 'ERR_MODULE_NOT_FOUND'); | | 9 | + assert.strictEqual(e.code, 'ERR_UNSUPPORTED_DIR_IMPORT'); | 10 | 10 | } | 11 | 11 |
| 12 | 12 | assert.strictEqual(mod, undefined); | |
Collapse file Copy file name to clipboard +14Lines changed: 14 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +require('../common'); | | 4 | +const fixtures = require('../common/fixtures'); | | 5 | +const assert = require('assert'); | | 6 | +const { pathToFileURL } = require('url'); | | 7 | + | | 8 | +{ | | 9 | + assert.rejects(import('./'), /ERR_UNSUPPORTED_DIR_IMPORT/); | | 10 | + assert.rejects( | | 11 | + import(pathToFileURL(fixtures.path('packages', 'main'))), | | 12 | + /Did you mean/, | | 13 | + ); | | 14 | +} |
|