From 1125e445f3566b786bd2f23b7a06c365ab7722d7 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Wed, 27 Jun 2018 22:51:38 -0400 Subject: [PATCH 1/3] modules: enforce extensions and disallow directories this build on top of the limitations of the package name map proposal. It enforces the use of file extensions and doesn't support index.js or package.json resolution for the default ESM loader implementation. The current approach is naive and has lots of room for improvement but this can serve as a base for discussion Refs: https://github.com/domenic/package-name-maps --- doc/api/errors.md | 5 +++++ lib/internal/errors.js | 3 +++ lib/internal/modules/cjs/loader.js | 7 ++++++- lib/internal/modules/esm/default_resolve.js | 7 ++++++- test/es-module/test-esm-basic-imports.mjs | 3 ++- test/es-module/test-esm-cyclic-dynamic-import.mjs | 5 +++-- test/es-module/test-esm-double-encoding.mjs | 5 +++-- test/es-module/test-esm-encoded-path.mjs | 3 ++- test/es-module/test-esm-forbidden-globals.mjs | 3 ++- test/es-module/test-esm-import-meta.mjs | 3 ++- test/es-module/test-esm-json.mjs | 3 ++- test/es-module/test-esm-live-binding.mjs | 3 ++- test/es-module/test-esm-main-lookup.mjs | 6 ------ test/es-module/test-esm-named-exports.mjs | 3 ++- test/es-module/test-esm-namespace.mjs | 4 +++- .../es-module/test-esm-preserve-symlinks-not-found.mjs | 2 +- test/es-module/test-esm-require-cache.mjs | 3 ++- test/es-module/test-esm-shared-loader-dep.mjs | 3 ++- test/es-module/test-esm-shebang.mjs | 3 ++- test/es-module/test-esm-snapshot.mjs | 7 ++++--- test/es-module/test-esm-symlink-main.js | 2 +- test/es-module/test-esm-symlink.js | 10 ++++------ test/es-module/test-esm-throw-undefined.mjs | 2 +- .../fixtures/es-module-loaders/syntax-error-import.mjs | 2 +- test/fixtures/es-modules/loop.mjs | 2 +- test/fixtures/es-modules/pjson-main/main.js | 1 - test/fixtures/es-modules/pjson-main/package.json | 3 --- .../es-modules/test-esm-double-encoding-native%20.mjs | 6 ++++++ test/message/esm_display_syntax_error_import.mjs | 6 +++--- test/message/esm_display_syntax_error_import.out | 2 +- .../message/esm_display_syntax_error_import_module.mjs | 5 +++-- .../message/esm_display_syntax_error_import_module.out | 4 ++-- test/message/esm_display_syntax_error_module.mjs | 5 +++-- test/parallel/test-module-main-extension-lookup.js | 2 +- 34 files changed, 81 insertions(+), 52 deletions(-) delete mode 100644 test/es-module/test-esm-main-lookup.mjs delete mode 100644 test/fixtures/es-modules/pjson-main/main.js delete mode 100644 test/fixtures/es-modules/pjson-main/package.json create mode 100644 test/fixtures/es-modules/test-esm-double-encoding-native%20.mjs diff --git a/doc/api/errors.md b/doc/api/errors.md index 00e44618ef0d..e9e05224b85a 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1388,6 +1388,11 @@ OpenSSL crypto support. An attempt was made to use features that require [ICU][], but Node.js was not compiled with ICU support. + +### ERR_NON_EXPLICIT_SPECIFIER + +Modules that are imported must use explicit file extensions + ### ERR_NO_LONGER_SUPPORTED diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 24e1f34b25d9..353e712c0afb 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -740,6 +740,9 @@ E('ERR_NAPI_INVALID_TYPEDARRAY_ALIGNMENT', 'start offset of %s should be a multiple of %s', RangeError); E('ERR_NAPI_INVALID_TYPEDARRAY_LENGTH', 'Invalid typed array length', RangeError); +E('ERR_NON_EXPLICIT_SPECIFIER', + 'The file %s does not include an extensionimported modules must declare' + + ' an extension', Error); E('ERR_NO_CRYPTO', 'Node.js is not compiled with OpenSSL crypto support', Error); E('ERR_NO_ICU', diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index c218dc2cac2a..f6106da03078 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -42,6 +42,7 @@ const { const preserveSymlinks = !!process.binding('config').preserveSymlinks; const preserveSymlinksMain = !!process.binding('config').preserveSymlinksMain; const experimentalModules = !!process.binding('config').experimentalModules; +const hasLoader = !!process.binding('config').userLoader; const { ERR_INVALID_ARG_TYPE, @@ -728,7 +729,11 @@ if (experimentalModules) { // bootstrap main module. Module.runMain = function() { // Load the main module--the command line argument. - if (experimentalModules) { + const base = path.basename(process.argv[1]); + const ext = path.extname(base); + const isESM = ext === '.mjs'; + + if (experimentalModules && (isESM || hasLoader)) { if (asyncESM === undefined) lazyLoadESM(); asyncESM.loaderPromise.then((loader) => { return loader.import(getURLFromFilePath(process.argv[1]).pathname); diff --git a/lib/internal/modules/esm/default_resolve.js b/lib/internal/modules/esm/default_resolve.js index b573ce4e8d9e..9e142e97a89e 100644 --- a/lib/internal/modules/esm/default_resolve.js +++ b/lib/internal/modules/esm/default_resolve.js @@ -11,7 +11,8 @@ const preserveSymlinksMain = !!process.binding('config').preserveSymlinksMain; const { ERR_MISSING_MODULE, ERR_MODULE_RESOLUTION_LEGACY, - ERR_UNKNOWN_FILE_EXTENSION + ERR_UNKNOWN_FILE_EXTENSION, + ERR_NON_EXPLICIT_SPECIFIER } = require('internal/errors').codes; const { resolve: moduleWrapResolve } = internalBinding('module_wrap'); const StringStartsWith = Function.call.bind(String.prototype.startsWith); @@ -24,6 +25,10 @@ function search(target, base) { // We cannot search without a base. throw new ERR_MISSING_MODULE(target); } + if ((target[0] === '.' || target[0] === '/') && + (extname(target) <= 1)) { + throw new ERR_NON_EXPLICIT_SPECIFIER(target); + } try { return moduleWrapResolve(target, base); } catch (e) { diff --git a/test/es-module/test-esm-basic-imports.mjs b/test/es-module/test-esm-basic-imports.mjs index 78a4106f9449..d9bb22be0a5f 100644 --- a/test/es-module/test-esm-basic-imports.mjs +++ b/test/es-module/test-esm-basic-imports.mjs @@ -1,5 +1,6 @@ // Flags: --experimental-modules -import '../common'; +/* eslint-disable node-core/required-modules */ +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'; diff --git a/test/es-module/test-esm-cyclic-dynamic-import.mjs b/test/es-module/test-esm-cyclic-dynamic-import.mjs index c8dfff919c2f..a207efc73ecb 100644 --- a/test/es-module/test-esm-cyclic-dynamic-import.mjs +++ b/test/es-module/test-esm-cyclic-dynamic-import.mjs @@ -1,3 +1,4 @@ // Flags: --experimental-modules -import '../common'; -import('./test-esm-cyclic-dynamic-import'); +/* eslint-disable node-core/required-modules */ +import '../common/index.mjs'; +import('./test-esm-cyclic-dynamic-import.mjs'); diff --git a/test/es-module/test-esm-double-encoding.mjs b/test/es-module/test-esm-double-encoding.mjs index c81d0530d332..9366d4bd6bcc 100644 --- a/test/es-module/test-esm-double-encoding.mjs +++ b/test/es-module/test-esm-double-encoding.mjs @@ -1,6 +1,7 @@ // Flags: --experimental-modules -import '../common'; +/* eslint-disable node-core/required-modules */ +import '../common/index.mjs'; // Assert we can import files with `%` in their pathname. -import '../fixtures/es-modules/test-esm-double-encoding-native%2520.js'; +import '../fixtures/es-modules/test-esm-double-encoding-native%2520.mjs'; diff --git a/test/es-module/test-esm-encoded-path.mjs b/test/es-module/test-esm-encoded-path.mjs index 365a425afa50..2cabfdacff39 100644 --- a/test/es-module/test-esm-encoded-path.mjs +++ b/test/es-module/test-esm-encoded-path.mjs @@ -1,5 +1,6 @@ // Flags: --experimental-modules -import '../common'; +/* eslint-disable node-core/required-modules */ +import '../common/index.mjs'; import assert from 'assert'; // ./test-esm-ok.mjs import ok from '../fixtures/es-modules/test-%65%73%6d-ok.mjs'; diff --git a/test/es-module/test-esm-forbidden-globals.mjs b/test/es-module/test-esm-forbidden-globals.mjs index 4e777412a346..cf110ff2900e 100644 --- a/test/es-module/test-esm-forbidden-globals.mjs +++ b/test/es-module/test-esm-forbidden-globals.mjs @@ -1,5 +1,6 @@ // Flags: --experimental-modules -import '../common'; +/* eslint-disable node-core/required-modules */ +import '../common/index.mjs'; // eslint-disable-next-line no-undef if (typeof arguments !== 'undefined') { diff --git a/test/es-module/test-esm-import-meta.mjs b/test/es-module/test-esm-import-meta.mjs index c17e0e20d49b..4c34b337fb89 100644 --- a/test/es-module/test-esm-import-meta.mjs +++ b/test/es-module/test-esm-import-meta.mjs @@ -1,6 +1,7 @@ // Flags: --experimental-modules +/* eslint-disable node-core/required-modules */ -import '../common'; +import '../common/index.mjs'; import assert from 'assert'; assert.strictEqual(Object.getPrototypeOf(import.meta), null); diff --git a/test/es-module/test-esm-json.mjs b/test/es-module/test-esm-json.mjs index a7146d19a9ad..059470d63624 100644 --- a/test/es-module/test-esm-json.mjs +++ b/test/es-module/test-esm-json.mjs @@ -1,5 +1,6 @@ // Flags: --experimental-modules -import '../common'; +/* eslint-disable node-core/required-modules */ +import '../common/index.mjs'; import assert from 'assert'; import ok from '../fixtures/es-modules/test-esm-ok.mjs'; import json from '../fixtures/es-modules/json.json'; diff --git a/test/es-module/test-esm-live-binding.mjs b/test/es-module/test-esm-live-binding.mjs index d151e004dff4..880a6c389b42 100644 --- a/test/es-module/test-esm-live-binding.mjs +++ b/test/es-module/test-esm-live-binding.mjs @@ -1,6 +1,7 @@ // Flags: --experimental-modules +/* eslint-disable node-core/required-modules */ -import '../common'; +import '../common/index.mjs'; import assert from 'assert'; import fs, { readFile, readFileSync } from 'fs'; diff --git a/test/es-module/test-esm-main-lookup.mjs b/test/es-module/test-esm-main-lookup.mjs deleted file mode 100644 index ca313a1d2644..000000000000 --- a/test/es-module/test-esm-main-lookup.mjs +++ /dev/null @@ -1,6 +0,0 @@ -// Flags: --experimental-modules -import '../common'; -import assert from 'assert'; -import main from '../fixtures/es-modules/pjson-main'; - -assert.strictEqual(main, 'main'); diff --git a/test/es-module/test-esm-named-exports.mjs b/test/es-module/test-esm-named-exports.mjs index 3aae9230de36..e235f598cb1d 100644 --- a/test/es-module/test-esm-named-exports.mjs +++ b/test/es-module/test-esm-named-exports.mjs @@ -1,5 +1,6 @@ // Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs -import '../common'; +/* eslint-disable node-core/required-modules */ +import '../common/index.mjs'; import { readFile } from 'fs'; import assert from 'assert'; import ok from '../fixtures/es-modules/test-esm-ok.mjs'; diff --git a/test/es-module/test-esm-namespace.mjs b/test/es-module/test-esm-namespace.mjs index dcd159f6c872..6b58e074ff21 100644 --- a/test/es-module/test-esm-namespace.mjs +++ b/test/es-module/test-esm-namespace.mjs @@ -1,5 +1,7 @@ // Flags: --experimental-modules -import '../common'; +/* eslint-disable node-core/required-modules */ + +import '../common/index.mjs'; import * as fs from 'fs'; import assert from 'assert'; import Module from 'module'; diff --git a/test/es-module/test-esm-preserve-symlinks-not-found.mjs b/test/es-module/test-esm-preserve-symlinks-not-found.mjs index 5119957bae7c..b5be2d7e63b5 100644 --- a/test/es-module/test-esm-preserve-symlinks-not-found.mjs +++ b/test/es-module/test-esm-preserve-symlinks-not-found.mjs @@ -1,3 +1,3 @@ // Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/not-found-assert-loader.mjs /* eslint-disable node-core/required-modules */ -import './not-found'; +import './not-found.mjs'; diff --git a/test/es-module/test-esm-require-cache.mjs b/test/es-module/test-esm-require-cache.mjs index ff32cde36ff2..fc7617930cf9 100644 --- a/test/es-module/test-esm-require-cache.mjs +++ b/test/es-module/test-esm-require-cache.mjs @@ -1,5 +1,6 @@ // Flags: --experimental-modules -import '../common'; +/* eslint-disable node-core/required-modules */ +import '../common/index.mjs'; import '../fixtures/es-module-require-cache/preload.js'; import '../fixtures/es-module-require-cache/counter.js'; import assert from 'assert'; diff --git a/test/es-module/test-esm-shared-loader-dep.mjs b/test/es-module/test-esm-shared-loader-dep.mjs index 5c274d835c8a..879db4431622 100644 --- a/test/es-module/test-esm-shared-loader-dep.mjs +++ b/test/es-module/test-esm-shared-loader-dep.mjs @@ -1,5 +1,6 @@ // Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/loader-shared-dep.mjs -import '../common'; +/* eslint-disable node-core/required-modules */ +import '../common/index.mjs'; import assert from 'assert'; import '../fixtures/es-modules/test-esm-ok.mjs'; import dep from '../fixtures/es-module-loaders/loader-dep.js'; diff --git a/test/es-module/test-esm-shebang.mjs b/test/es-module/test-esm-shebang.mjs index d5faace4792f..486e04dadece 100644 --- a/test/es-module/test-esm-shebang.mjs +++ b/test/es-module/test-esm-shebang.mjs @@ -1,6 +1,7 @@ #! }]) // isn't js // Flags: --experimental-modules -import '../common'; +/* eslint-disable node-core/required-modules */ +import '../common/index.mjs'; const isJs = true; export default isJs; diff --git a/test/es-module/test-esm-snapshot.mjs b/test/es-module/test-esm-snapshot.mjs index 3d4b44bbdd5b..3997e24ed703 100644 --- a/test/es-module/test-esm-snapshot.mjs +++ b/test/es-module/test-esm-snapshot.mjs @@ -1,7 +1,8 @@ // Flags: --experimental-modules -import '../common'; -import '../fixtures/es-modules/esm-snapshot-mutator'; -import one from '../fixtures/es-modules/esm-snapshot'; +/* eslint-disable node-core/required-modules */ +import '../common/index.mjs'; +import '../fixtures/es-modules/esm-snapshot-mutator.js'; +import one from '../fixtures/es-modules/esm-snapshot.js'; import assert from 'assert'; assert.strictEqual(one, 1); diff --git a/test/es-module/test-esm-symlink-main.js b/test/es-module/test-esm-symlink-main.js index f7631ef2e5bd..871180f5ccf4 100644 --- a/test/es-module/test-esm-symlink-main.js +++ b/test/es-module/test-esm-symlink-main.js @@ -9,7 +9,7 @@ const fs = require('fs'); tmpdir.refresh(); const realPath = path.resolve(__dirname, '../fixtures/es-modules/symlink.mjs'); -const symlinkPath = path.resolve(tmpdir.path, 'symlink.js'); +const symlinkPath = path.resolve(tmpdir.path, 'symlink.mjs'); try { fs.symlinkSync(realPath, symlinkPath); diff --git a/test/es-module/test-esm-symlink.js b/test/es-module/test-esm-symlink.js index 232925a52e3f..9b9eb98cd984 100644 --- a/test/es-module/test-esm-symlink.js +++ b/test/es-module/test-esm-symlink.js @@ -12,8 +12,8 @@ const tmpDir = tmpdir.path; const entry = path.join(tmpDir, 'entry.mjs'); const real = path.join(tmpDir, 'index.mjs'); -const link_absolute_path = path.join(tmpDir, 'absolute'); -const link_relative_path = path.join(tmpDir, 'relative'); +const link_absolute_path = path.join(tmpDir, 'absolute.mjs'); +const link_relative_path = path.join(tmpDir, 'relative.mjs'); const link_ignore_extension = path.join(tmpDir, 'ignore_extension.json'); const link_directory = path.join(tmpDir, 'directory'); @@ -22,15 +22,13 @@ fs.writeFileSync(real, 'export default [];'); fs.writeFileSync(entry, ` import assert from 'assert'; import real from './index.mjs'; -import absolute from './absolute'; -import relative from './relative'; +import absolute from './absolute.mjs'; +import relative from './relative.mjs'; import ignoreExtension from './ignore_extension.json'; -import directory from './directory'; assert.strictEqual(absolute, real); assert.strictEqual(relative, real); assert.strictEqual(ignoreExtension, real); -assert.strictEqual(directory, real); `); try { diff --git a/test/es-module/test-esm-throw-undefined.mjs b/test/es-module/test-esm-throw-undefined.mjs index 877728178762..5e8be47d5153 100644 --- a/test/es-module/test-esm-throw-undefined.mjs +++ b/test/es-module/test-esm-throw-undefined.mjs @@ -6,7 +6,7 @@ import assert from 'assert'; async function doTest() { await assert.rejects( async () => { - await import('../fixtures/es-module-loaders/throw-undefined'); + await import('../fixtures/es-module-loaders/throw-undefined.mjs'); }, (e) => e === undefined ); diff --git a/test/fixtures/es-module-loaders/syntax-error-import.mjs b/test/fixtures/es-module-loaders/syntax-error-import.mjs index 9cad68c7ce2a..3a6bc5effc19 100644 --- a/test/fixtures/es-module-loaders/syntax-error-import.mjs +++ b/test/fixtures/es-module-loaders/syntax-error-import.mjs @@ -1 +1 @@ -import { foo, notfound } from './module-named-exports'; +import { foo, notfound } from './module-named-exports.mjs'; diff --git a/test/fixtures/es-modules/loop.mjs b/test/fixtures/es-modules/loop.mjs index 1b5cab10edc7..3d2ddd2eb730 100644 --- a/test/fixtures/es-modules/loop.mjs +++ b/test/fixtures/es-modules/loop.mjs @@ -1,4 +1,4 @@ -import { message } from './message'; +import { message } from './message.mjs'; var t = 1; var k = 1; diff --git a/test/fixtures/es-modules/pjson-main/main.js b/test/fixtures/es-modules/pjson-main/main.js deleted file mode 100644 index dfdd47b87731..000000000000 --- a/test/fixtures/es-modules/pjson-main/main.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 'main'; diff --git a/test/fixtures/es-modules/pjson-main/package.json b/test/fixtures/es-modules/pjson-main/package.json deleted file mode 100644 index c13b8cf6acfd..000000000000 --- a/test/fixtures/es-modules/pjson-main/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "main": "main.js" -} diff --git a/test/fixtures/es-modules/test-esm-double-encoding-native%20.mjs b/test/fixtures/es-modules/test-esm-double-encoding-native%20.mjs new file mode 100644 index 000000000000..a3bfe972e5a8 --- /dev/null +++ b/test/fixtures/es-modules/test-esm-double-encoding-native%20.mjs @@ -0,0 +1,6 @@ +'use strict'; + +// Trivial test to assert we can load files with `%` in their pathname. +// Imported by `test-esm-double-encoding.mjs`. + +export default 42; diff --git a/test/message/esm_display_syntax_error_import.mjs b/test/message/esm_display_syntax_error_import.mjs index 87cedf1d4edd..12d10270e968 100644 --- a/test/message/esm_display_syntax_error_import.mjs +++ b/test/message/esm_display_syntax_error_import.mjs @@ -1,7 +1,7 @@ // Flags: --experimental-modules -/* eslint-disable no-unused-vars */ -import '../common'; +/* eslint-disable no-unused-vars, node-core/required-modules */ +import '../common/index.mjs'; import { foo, notfound -} from '../fixtures/es-module-loaders/module-named-exports'; +} from '../fixtures/es-module-loaders/module-named-exports.mjs'; diff --git a/test/message/esm_display_syntax_error_import.out b/test/message/esm_display_syntax_error_import.out index 31ee2b6f4b11..48f2e2fb7465 100644 --- a/test/message/esm_display_syntax_error_import.out +++ b/test/message/esm_display_syntax_error_import.out @@ -2,5 +2,5 @@ file:///*/test/message/esm_display_syntax_error_import.mjs:6 notfound ^^^^^^^^ -SyntaxError: The requested module '../fixtures/es-module-loaders/module-named-exports' does not provide an export named 'notfound' +SyntaxError: The requested module '../fixtures/es-module-loaders/module-named-exports.mjs' does not provide an export named 'notfound' at ModuleJob._instantiate (internal/modules/esm/module_job.js:*:*) diff --git a/test/message/esm_display_syntax_error_import_module.mjs b/test/message/esm_display_syntax_error_import_module.mjs index 32c0edb35068..a53bbbcd1924 100644 --- a/test/message/esm_display_syntax_error_import_module.mjs +++ b/test/message/esm_display_syntax_error_import_module.mjs @@ -1,3 +1,4 @@ // Flags: --experimental-modules -import '../common'; -import '../fixtures/es-module-loaders/syntax-error-import'; +/* eslint-disable node-core/required-modules */ +import '../common/index.mjs'; +import '../fixtures/es-module-loaders/syntax-error-import.mjs'; diff --git a/test/message/esm_display_syntax_error_import_module.out b/test/message/esm_display_syntax_error_import_module.out index b067a77942fa..3e1024db8aa0 100644 --- a/test/message/esm_display_syntax_error_import_module.out +++ b/test/message/esm_display_syntax_error_import_module.out @@ -1,6 +1,6 @@ (node:*) ExperimentalWarning: The ESM module loader is experimental. file:///*/test/fixtures/es-module-loaders/syntax-error-import.mjs:1 -import { foo, notfound } from './module-named-exports'; +import { foo, notfound } from './module-named-exports.mjs'; ^^^^^^^^ -SyntaxError: The requested module './module-named-exports' does not provide an export named 'notfound' +SyntaxError: The requested module './module-named-exports.mjs' does not provide an export named 'notfound' at ModuleJob._instantiate (internal/modules/esm/module_job.js:*:*) diff --git a/test/message/esm_display_syntax_error_module.mjs b/test/message/esm_display_syntax_error_module.mjs index e74b70bec8cc..5905d2a95478 100644 --- a/test/message/esm_display_syntax_error_module.mjs +++ b/test/message/esm_display_syntax_error_module.mjs @@ -1,3 +1,4 @@ // Flags: --experimental-modules -import '../common'; -import '../fixtures/es-module-loaders/syntax-error'; +/* eslint-disable node-core/required-modules */ +import '../common/index.mjs'; +import '../fixtures/es-module-loaders/syntax-error.mjs'; diff --git a/test/parallel/test-module-main-extension-lookup.js b/test/parallel/test-module-main-extension-lookup.js index 3d20316647c6..9e7eab295e87 100644 --- a/test/parallel/test-module-main-extension-lookup.js +++ b/test/parallel/test-module-main-extension-lookup.js @@ -6,6 +6,6 @@ const { execFileSync } = require('child_process'); const node = process.argv[0]; execFileSync(node, ['--experimental-modules', - fixtures.path('es-modules', 'test-esm-ok')]); + fixtures.path('es-modules', 'test-esm-ok.mjs')]); execFileSync(node, ['--experimental-modules', fixtures.path('es-modules', 'noext')]); From afb45d358f8668e4d3c156796f316850af9857bc Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Thu, 28 Jun 2018 02:41:01 -0400 Subject: [PATCH 2/3] doc: document esm limitations --- doc/api/esm.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/doc/api/esm.md b/doc/api/esm.md index 459f87771815..5586f4018c2e 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -54,6 +54,14 @@ property: ## Notable differences between `import` and `require` +### Mandatory file extensions + +You must provide a file extension when using the `import` keyword. + +### No importing directories + +There is no support for importing directories. + ### No NODE_PATH `NODE_PATH` is not part of resolving `import` specifiers. Please use symlinks @@ -78,8 +86,8 @@ Modules will be loaded multiple times if the `import` specifier used to resolve them have a different query or fragment. ```js -import './foo?query=1'; // loads ./foo with query of "?query=1" -import './foo?query=2'; // loads ./foo with query of "?query=2" +import './foo.mjs?query=1'; // loads ./foo.mjs with query of "?query=1" +import './foo.mjs?query=2'; // loads ./foo.mjs with query of "?query=2" ``` For now, only modules using the `file:` protocol can be loaded. From 9c090eab8b0140dcb167a44de749373627bb60ec Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Thu, 28 Jun 2018 03:31:46 -0400 Subject: [PATCH 3/3] fixup: @vsemozhetbyt notes --- doc/api/errors.md | 2 +- doc/api/esm.md | 2 +- lib/internal/errors.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/api/errors.md b/doc/api/errors.md index e9e05224b85a..326627f70d42 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1391,7 +1391,7 @@ compiled with ICU support. ### ERR_NON_EXPLICIT_SPECIFIER -Modules that are imported must use explicit file extensions +Modules that are imported must use explicit file extensions. ### ERR_NO_LONGER_SUPPORTED diff --git a/doc/api/esm.md b/doc/api/esm.md index 5586f4018c2e..320a534b6e4e 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -56,7 +56,7 @@ property: ### Mandatory file extensions -You must provide a file extension when using the `import` keyword. +File extension must be provided when using the `import` keyword. ### No importing directories diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 353e712c0afb..158881f286bb 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -741,7 +741,7 @@ E('ERR_NAPI_INVALID_TYPEDARRAY_ALIGNMENT', E('ERR_NAPI_INVALID_TYPEDARRAY_LENGTH', 'Invalid typed array length', RangeError); E('ERR_NON_EXPLICIT_SPECIFIER', - 'The file %s does not include an extensionimported modules must declare' + + 'The file %s does not include an extension. Imported modules must declare' + ' an extension', Error); E('ERR_NO_CRYPTO', 'Node.js is not compiled with OpenSSL crypto support', Error);