GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — module: better error for named exports from cjs · nodejs/node@ad86807

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • lib/internal/modules/esm
    • module_job.js
  • test
    • es-module
      • test-esm-cjs-named-error.mjs
    • fixtures/es-modules/package-cjs-named-error
      • bare-import-double.mjs
      • bare-import-single.mjs
      • double-quote.mjs
      • escaped-single-quote.mjs
      • fail.cjs
      • json-hack.mjs
      • json-hack
        • fail.js
        • package.json
      • node_modules/deep-fail
        • index.js
        • package.json
      • oh'no.cjs
      • package.json
      • single-quote.mjs
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎lib/internal/modules/esm/module_job.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/module_job.js
+27Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
'use strict';
22

33
const {
4+
ArrayPrototypeJoin,
45
ObjectSetPrototypeOf,
56
PromiseAll,
67
SafeSet,
78
SafePromise,
9+
StringPrototypeIncludes,
10+
StringPrototypeMatch,
11+
StringPrototypeSplit,
812
} = primordials;
913

1014
const { ModuleWrap } = internalBinding('module_wrap');
@@ -93,6 +97,29 @@ class ModuleJob {
9397
}
9498
} catch (e) {
9599
decorateErrorStack(e);
100+
if (StringPrototypeIncludes(e.message,
101+
' does not provide an export named')) {
102+
const splitStack = StringPrototypeSplit(e.stack, '\n');
103+
const parentFileUrl = splitStack[0];
104+
const childSpecifier = StringPrototypeMatch(e.message, /module '(.*)' does/)[1];
105+
const childFileURL =
106+
await this.loader.resolve(childSpecifier, parentFileUrl);
107+
const format = await this.loader.getFormat(childFileURL);
108+
if (format === 'commonjs') {
109+
const importStatement = splitStack[1];
110+
const namedImports = StringPrototypeMatch(importStatement, /{.*}/)[0];
111+
e.message = `The requested module '${childSpecifier}' is expected ` +
112+
'to be of type CommonJS, which does not support named exports. ' +
113+
'CommonJS modules can be imported by importing the default ' +
114+
'export.\n' +
115+
'For example:\n' +
116+
`import pkg from '${childSpecifier}';\n` +
117+
`const ${namedImports} = pkg;`;
118+
const newStack = StringPrototypeSplit(e.stack, '\n');
119+
newStack[3] = `SyntaxError: ${e.message}`;
120+
e.stack = ArrayPrototypeJoin(newStack, '\n');
121+
}
122+
}
96123
throw e;
97124
}
98125
for (const dependencyJob of jobsInGraph) {
Collapse file

‎test/es-module/test-esm-cjs-named-error.mjs‎

Copy file name to clipboard
+64Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import '../common/index.mjs';
2+
import { rejects } from 'assert';
3+
4+
const fixtureBase = '../fixtures/es-modules/package-cjs-named-error';
5+
6+
const expectedRelative = 'The requested module \'./fail.cjs\' is expected to ' +
7+
'be of type CommonJS, which does not support named exports. CommonJS ' +
8+
'modules can be imported by importing the default export.\n' +
9+
'For example:\n' +
10+
'import pkg from \'./fail.cjs\';\n' +
11+
'const { comeOn } = pkg;';
12+
13+
const expectedPackageHack = 'The requested module \'./json-hack/fail.js\' is ' +
14+
'expected to be of type CommonJS, which does not support named exports. ' +
15+
'CommonJS modules can be imported by importing the default export.\n' +
16+
'For example:\n' +
17+
'import pkg from \'./json-hack/fail.js\';\n' +
18+
'const { comeOn } = pkg;';
19+
20+
const expectedBare = 'The requested module \'deep-fail\' is expected to ' +
21+
'be of type CommonJS, which does not support named exports. CommonJS ' +
22+
'modules can be imported by importing the default export.\n' +
23+
'For example:\n' +
24+
'import pkg from \'deep-fail\';\n' +
25+
'const { comeOn } = pkg;';
26+
27+
rejects(async () => {
28+
await import(`${fixtureBase}/single-quote.mjs`);
29+
}, {
30+
name: 'SyntaxError',
31+
message: expectedRelative
32+
}, 'should support relative specifiers with single quotes');
33+
34+
rejects(async () => {
35+
await import(`${fixtureBase}/double-quote.mjs`);
36+
}, {
37+
name: 'SyntaxError',
38+
message: expectedRelative
39+
}, 'should support relative specifiers with double quotes');
40+
41+
rejects(async () => {
42+
await import(`${fixtureBase}/json-hack.mjs`);
43+
}, {
44+
name: 'SyntaxError',
45+
message: expectedPackageHack
46+
}, 'should respect recursive package.json for module type');
47+
48+
rejects(async () => {
49+
await import(`${fixtureBase}/bare-import-single.mjs`);
50+
}, {
51+
name: 'SyntaxError',
52+
message: expectedBare
53+
}, 'should support bare specifiers with single quotes');
54+
55+
rejects(async () => {
56+
await import(`${fixtureBase}/bare-import-double.mjs`);
57+
}, {
58+
name: 'SyntaxError',
59+
message: expectedBare
60+
}, 'should support bare specifiers with double quotes');
61+
62+
rejects(async () => {
63+
await import(`${fixtureBase}/escaped-single-quote.mjs`);
64+
}, /import pkg from '\.\/oh'no\.cjs'/, 'should support relative specifiers with escaped single quote');
Collapse file

‎test/fixtures/es-modules/package-cjs-named-error/bare-import-double.mjs‎

Copy file name to clipboard
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import { comeOn } from "deep-fail";
Collapse file

‎test/fixtures/es-modules/package-cjs-named-error/bare-import-single.mjs‎

Copy file name to clipboard
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import { comeOn } from 'deep-fail';
Collapse file

‎test/fixtures/es-modules/package-cjs-named-error/double-quote.mjs‎

Copy file name to clipboard
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import { comeOn } from "./fail.cjs";
Collapse file

‎test/fixtures/es-modules/package-cjs-named-error/escaped-single-quote.mjs‎

Copy file name to clipboard
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import { value } from "./oh'no.cjs";
Collapse file

‎test/fixtures/es-modules/package-cjs-named-error/fail.cjs‎

Copy file name to clipboard
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
comeOn: 'fhqwhgads'
3+
};
Collapse file

‎test/fixtures/es-modules/package-cjs-named-error/json-hack.mjs‎

Copy file name to clipboard
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import { comeOn } from './json-hack/fail.js';
Collapse file

‎test/fixtures/es-modules/package-cjs-named-error/json-hack/fail.js‎

Copy file name to clipboard
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
comeOn: 'fhqwhgads'
3+
};
Collapse file

‎test/fixtures/es-modules/package-cjs-named-error/json-hack/package.json‎

Copy file name to clipboard
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"type": "commonjs"
3+
}

0 commit comments

Comments
0 (0)
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.