diff options
author | Guy Bedford <guybedford@gmail.com> | 2020-05-14 22:40:37 -0700 |
---|---|---|
committer | Guy Bedford <guybedford@gmail.com> | 2020-09-28 18:27:25 -0700 |
commit | 1e8cb08edcbbfe01e7ef186a09d4781b33b490cc (patch) | |
tree | 3da6f851ef45c6a1a35466d616102d6fdb344f4c /test | |
parent | 062b35d4e82663b50898f4f47e74d9d64c031379 (diff) | |
download | node-new-1e8cb08edcbbfe01e7ef186a09d4781b33b490cc.tar.gz |
module: named exports for CJS via static analysis
PR-URL: https://github.com/nodejs/node/pull/35249
Reviewed-By: Mary Marchini <oss@mmarchini.me>
Reviewed-By: Geoffrey Booth <webmaster@geoffreybooth.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Zeyu Yang <himself65@outlook.com>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Diffstat (limited to 'test')
-rw-r--r-- | test/es-module/test-esm-cjs-exports.js | 21 | ||||
-rw-r--r-- | test/es-module/test-esm-cjs-named-error.mjs | 42 | ||||
-rw-r--r-- | test/fixtures/es-modules/cjs-exports.mjs | 34 | ||||
-rw-r--r-- | test/fixtures/es-modules/exports-cases.js | 7 | ||||
-rw-r--r-- | test/fixtures/es-modules/exports-cases2.js | 29 | ||||
-rw-r--r-- | test/fixtures/es-modules/exports-cases3.js | 25 | ||||
-rw-r--r-- | test/parallel/test-bootstrap-modules.js | 1 |
7 files changed, 132 insertions, 27 deletions
diff --git a/test/es-module/test-esm-cjs-exports.js b/test/es-module/test-esm-cjs-exports.js new file mode 100644 index 0000000000..37aa70d388 --- /dev/null +++ b/test/es-module/test-esm-cjs-exports.js @@ -0,0 +1,21 @@ +'use strict'; + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +const { spawn } = require('child_process'); +const assert = require('assert'); + +const entry = fixtures.path('/es-modules/cjs-exports.mjs'); + +const child = spawn(process.execPath, [entry]); +child.stderr.setEncoding('utf8'); +let stdout = ''; +child.stdout.setEncoding('utf8'); +child.stdout.on('data', (data) => { + stdout += data; +}); +child.on('close', common.mustCall((code, signal) => { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + assert.strictEqual(stdout, 'ok\n'); +})); diff --git a/test/es-module/test-esm-cjs-named-error.mjs b/test/es-module/test-esm-cjs-named-error.mjs index e9ddc67c0f..4ef75a22f9 100644 --- a/test/es-module/test-esm-cjs-named-error.mjs +++ b/test/es-module/test-esm-cjs-named-error.mjs @@ -3,37 +3,25 @@ import { rejects } from 'assert'; const fixtureBase = '../fixtures/es-modules/package-cjs-named-error'; -const expectedRelative = 'The requested module \'./fail.cjs\' is expected to ' + - 'be of type CommonJS, which does not support named exports. CommonJS ' + - 'modules can be imported by importing the default export.\n' + - 'For example:\n' + - 'import pkg from \'./fail.cjs\';\n' + - 'const { comeOn } = pkg;'; +const errTemplate = (specifier, name, namedImports) => + `Named export '${name}' not found. The requested module` + + ` '${specifier}' is a CommonJS module, which may not support ` + + 'all module.exports as named exports.\nCommonJS modules can ' + + 'always be imported via the default export, for example using:' + + `\n\nimport pkg from '${specifier}';\n` + (namedImports ? + `const ${namedImports} = pkg;\n` : ''); -const expectedWithoutExample = 'The requested module \'./fail.cjs\' is ' + - 'expected to be of type CommonJS, which does not support named exports. ' + - 'CommonJS modules can be imported by importing the default export.'; +const expectedWithoutExample = errTemplate('./fail.cjs', 'comeOn'); -const expectedRenamed = 'The requested module \'./fail.cjs\' is expected to ' + - 'be of type CommonJS, which does not support named exports. CommonJS ' + - 'modules can be imported by importing the default export.\n' + - 'For example:\n' + - 'import pkg from \'./fail.cjs\';\n' + - 'const { comeOn: comeOnRenamed } = pkg;'; +const expectedRelative = errTemplate('./fail.cjs', 'comeOn', '{ comeOn }'); -const expectedPackageHack = 'The requested module \'./json-hack/fail.js\' is ' + - 'expected to be of type CommonJS, which does not support named exports. ' + - 'CommonJS modules can be imported by importing the default export.\n' + - 'For example:\n' + - 'import pkg from \'./json-hack/fail.js\';\n' + - 'const { comeOn } = pkg;'; +const expectedRenamed = errTemplate('./fail.cjs', 'comeOn', + '{ comeOn: comeOnRenamed }'); -const expectedBare = 'The requested module \'deep-fail\' is expected to ' + - 'be of type CommonJS, which does not support named exports. CommonJS ' + - 'modules can be imported by importing the default export.\n' + - 'For example:\n' + - 'import pkg from \'deep-fail\';\n' + - 'const { comeOn } = pkg;'; +const expectedPackageHack = + errTemplate('./json-hack/fail.js', 'comeOn', '{ comeOn }'); + +const expectedBare = errTemplate('deep-fail', 'comeOn', '{ comeOn }'); rejects(async () => { await import(`${fixtureBase}/single-quote.mjs`); diff --git a/test/fixtures/es-modules/cjs-exports.mjs b/test/fixtures/es-modules/cjs-exports.mjs new file mode 100644 index 0000000000..47bb4926af --- /dev/null +++ b/test/fixtures/es-modules/cjs-exports.mjs @@ -0,0 +1,34 @@ +import { strictEqual, deepEqual } from 'assert'; + +import m, { π, z } from './exports-cases.js'; +import * as ns from './exports-cases.js'; + +deepEqual(Object.keys(ns), ['default', 'isObject', 'z', 'π']); +strictEqual(π, 'yes'); +strictEqual(z, 'yes'); +strictEqual(typeof m.isObject, 'undefined'); +strictEqual(m.π, 'yes'); +strictEqual(m.z, 'yes'); + +import m2, { __esModule as __esModule2, name as name2 } from './exports-cases2.js'; +import * as ns2 from './exports-cases2.js'; + +strictEqual(__esModule2, true); +strictEqual(name2, 'name'); +strictEqual(typeof m2, 'object'); +strictEqual(m2.default, 'the default'); +strictEqual(ns2.__esModule, true); +strictEqual(ns2.name, 'name'); +deepEqual(Object.keys(ns2), ['__esModule', 'case2', 'default', 'name', 'pi']); + +import m3, { __esModule as __esModule3, name as name3 } from './exports-cases3.js'; +import * as ns3 from './exports-cases3.js'; + +strictEqual(__esModule3, true); +strictEqual(name3, 'name'); +deepEqual(Object.keys(m3), ['name', 'default', 'pi', 'case2']); +strictEqual(ns3.__esModule, true); +strictEqual(ns3.name, 'name'); +strictEqual(ns3.case2, 'case2'); + +console.log('ok'); diff --git a/test/fixtures/es-modules/exports-cases.js b/test/fixtures/es-modules/exports-cases.js new file mode 100644 index 0000000000..eec3d31bc7 --- /dev/null +++ b/test/fixtures/es-modules/exports-cases.js @@ -0,0 +1,7 @@ +if (global.maybe) + module.exports = require('../is-object'); +exports['invalid identifier'] = 'no'; +module.exports['?invalid'] = 'no'; +module.exports['π'] = 'yes'; +exports.package = 10; // reserved word -> not used +Object.defineProperty(exports, 'z', { value: 'yes' }); diff --git a/test/fixtures/es-modules/exports-cases2.js b/test/fixtures/es-modules/exports-cases2.js new file mode 100644 index 0000000000..189eebb9f3 --- /dev/null +++ b/test/fixtures/es-modules/exports-cases2.js @@ -0,0 +1,29 @@ +/* + * Transpiled with Babel from: + * + * export { π as pi } from './exports-cases.js'; + * export default 'the default'; + * export const name = 'name'; + */ + +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "pi", { + enumerable: true, + get: function () { + return _exportsCases.π; + } +}); +exports.name = exports.default = void 0; + +var _exportsCases = require("./exports-cases.js"); + +var _default = 'the default'; +exports.default = _default; +const name = 'name'; +exports.name = name; + +exports.case2 = 'case2'; diff --git a/test/fixtures/es-modules/exports-cases3.js b/test/fixtures/es-modules/exports-cases3.js new file mode 100644 index 0000000000..c48b78cc41 --- /dev/null +++ b/test/fixtures/es-modules/exports-cases3.js @@ -0,0 +1,25 @@ +/* + * Transpiled with TypeScript from: + * + * export { π as pi } from './exports-cases.js'; + * export default 'the default'; + * export const name = 'name'; + */ + +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.name = void 0; +exports.default = 'the default'; +exports.name = 'name'; + +var _external = require("./exports-cases2.js"); + +Object.keys(_external).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _external[key]; + } + }); +});
\ No newline at end of file diff --git a/test/parallel/test-bootstrap-modules.js b/test/parallel/test-bootstrap-modules.js index 899d6ce363..ee9a62fbfa 100644 --- a/test/parallel/test-bootstrap-modules.js +++ b/test/parallel/test-bootstrap-modules.js @@ -55,6 +55,7 @@ const expectedModules = new Set([ 'NativeModule internal/modules/cjs/helpers', 'NativeModule internal/modules/cjs/loader', 'NativeModule internal/modules/esm/create_dynamic_module', + 'NativeModule internal/deps/cjs-module-lexer/lexer', 'NativeModule internal/modules/esm/get_format', 'NativeModule internal/modules/esm/get_source', 'NativeModule internal/modules/esm/loader', |