Skip to content

Commit 621136c

Browse files
committed
feat: add dynamic file-specific ESM warnings
1 parent 732744c commit 621136c

File tree

3 files changed

+21
-13
lines changed

3 files changed

+21
-13
lines changed

src/node_contextify.cc

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,13 +1688,19 @@ static MaybeLocal<Function> CompileFunctionForCJSLoader(
16881688
return scope.Escape(fn);
16891689
}
16901690

1691+
static std::string GetRequireEsmWarning(Local<String> filename) {
1692+
Isolate* isolate = Isolate::GetCurrent();
1693+
Utf8Value filename_utf8(isolate, filename);
1694+
1695+
std::string warning_message =
1696+
"Failed to load the ES module: " + std::string(*filename_utf8) +
1697+
". Make sure to set \"type\": \"module\" in the nearest package.json "
1698+
"file "
1699+
"or use the .mjs extension.";
1700+
return warning_message;
1701+
}
1702+
16911703
static bool warned_about_require_esm = false;
1692-
// TODO(joyeecheung): this was copied from the warning previously emitted in the
1693-
// JS land, but it's not very helpful. There should be specific information
1694-
// about which file or which package.json to update.
1695-
const char* require_esm_warning =
1696-
"To load an ES module, set \"type\": \"module\" in the package.json or use "
1697-
"the .mjs extension.";
16981704

16991705
static bool ShouldRetryAsESM(Realm* realm,
17001706
Local<String> message,
@@ -1780,8 +1786,9 @@ static void CompileFunctionForCJSLoader(
17801786
// This needs to call process.emit('warning') in JS which can throw if
17811787
// the user listener throws. In that case, don't try to throw the syntax
17821788
// error.
1789+
std::string warning_message = GetRequireEsmWarning(filename);
17831790
should_throw =
1784-
ProcessEmitWarningSync(env, require_esm_warning).IsJust();
1791+
ProcessEmitWarningSync(env, warning_message.c_str()).IsJust();
17851792
}
17861793
if (should_throw) {
17871794
isolate->ThrowException(cjs_exception);

test/es-module/test-esm-cjs-load-error-note.mjs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ import assert from 'node:assert';
44
import { execPath } from 'node:process';
55
import { describe, it } from 'node:test';
66

7-
87
// Expect note to be included in the error output
98
// Don't match the following sentence because it can change as features are
109
// added.
11-
const expectedNote = 'Warning: To load an ES module';
10+
const expectedNote = 'Failed to load the ES module';
1211

1312
const mustIncludeMessage = {
1413
getMessage: (stderr) => `${expectedNote} not found in ${stderr}`,

test/es-module/test-typescript-commonjs.mjs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,14 @@ test('require a .ts file with implicit extension fails', async () => {
5959
});
6060

6161
test('expect failure of an .mts file with CommonJS syntax', async () => {
62-
const result = await spawnPromisified(process.execPath, [
63-
fixtures.path('typescript/cts/test-cts-but-module-syntax.cts'),
64-
]);
62+
const testFilePath = fixtures.path('typescript/cts/test-cts-but-module-syntax.cts');
63+
const result = await spawnPromisified(process.execPath, [testFilePath]);
6564

6665
strictEqual(result.stdout, '');
67-
match(result.stderr, /To load an ES module, set "type": "module" in the package\.json or use the \.mjs extension\./);
66+
67+
const expectedWarning = `Failed to load the ES module: ${testFilePath}. Make sure to set "type": "module" in the nearest package.json file or use the .mjs extension.`;
68+
match(result.stderr, new RegExp(expectedWarning));
69+
6870
strictEqual(result.code, 1);
6971
});
7072

0 commit comments

Comments
 (0)