summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorGuy Bedford <guybedford@gmail.com>2020-05-14 22:40:37 -0700
committerGuy Bedford <guybedford@gmail.com>2020-09-28 18:27:25 -0700
commit1e8cb08edcbbfe01e7ef186a09d4781b33b490cc (patch)
tree3da6f851ef45c6a1a35466d616102d6fdb344f4c /test
parent062b35d4e82663b50898f4f47e74d9d64c031379 (diff)
downloadnode-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.js21
-rw-r--r--test/es-module/test-esm-cjs-named-error.mjs42
-rw-r--r--test/fixtures/es-modules/cjs-exports.mjs34
-rw-r--r--test/fixtures/es-modules/exports-cases.js7
-rw-r--r--test/fixtures/es-modules/exports-cases2.js29
-rw-r--r--test/fixtures/es-modules/exports-cases3.js25
-rw-r--r--test/parallel/test-bootstrap-modules.js1
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',