node
node copied to clipboard
String that looks like a source map comment gets used as a source map comment, but only in ESM
Version
21.6.0
Platform
Darwin Nics-MacBook-Air.local 23.2.0 Darwin Kernel Version 23.2.0: Wed Nov 15 21:59:33 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T8112 arm64
Subsystem
No response
What steps will reproduce the bug?
Input code:
"use strict";
throw new Error("Hello world!");`
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiaHR0cDovL2xvY2FsaG9zdDo0NTQ1L3J1bi9pbmxpbmVfanNfc291cmNlX21hcF8yLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIjErMTtcbmludGVyZmFjZSBUZXN0IHtcbiAgaGVsbG86IHN0cmluZztcbn1cblxudGhyb3cgbmV3IEVycm9yKFwiSGVsbG8gd29ybGQhXCIgYXMgdW5rbm93biBhcyBzdHJpbmcpO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxDQUFDLEdBQUMsQ0FBQyxDQUFDO0FBS0osTUFBTSxJQUFJLEtBQUssQ0FBQyxjQUErQixDQUFDLENBQUMifQ==
console.log(1);
// `
Output:
➜ node --enable-source-maps main2.mjs
file:///Users/nic/Documents/dev/github.com/tc39/source-map-spec/example/main2.mjs:3
throw new Error("Hello world!");`
^
Error: Hello world!
at <anonymous> (http://localhost:4545/run/inline_js_source_map_2.ts:6:7)
at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:323:24)
at async loadESM (node:internal/process/esm_loader:28:7)
at async handleMainPromise (node:internal/modules/run_main:120:12)
Node.js v21.6.0
As you can see, the stack trace points to a non-existent .ts
file
How often does it reproduce? Is there a required condition?
If you ran that code as CJS rather than ESM, no source map is applied (as expected):
➜ node --enable-source-maps main2.js
/Users/nic/Documents/dev/github.com/tc39/source-map-spec/example/main2.js:3
throw new Error("Hello world!");`
^
Error: Hello world!
at Object.<anonymous> (/Users/nic/Documents/dev/github.com/tc39/source-map-spec/example/main2.js:3:7)
at Module._compile (node:internal/modules/cjs/loader:1378:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1437:10)
at Module.load (node:internal/modules/cjs/loader:1212:32)
at Module._load (node:internal/modules/cjs/loader:1028:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:142:12)
at node:internal/main/run_main_module:28:49
Node.js v21.6.0
Note that source maps in CJS in general work: you can test by deleting the backtick after new Error("Hello world!");
(effectively turning the string-that-looks-like-a-comment into an actual source map comments) and you'll see that the source map is applied
Additional information
Some discussion is happening here: https://github.com/tc39/source-map-rfc/issues/64
I tried reading through the code, and I think the different behavior is because Node.js uses V8's GetSourceMappingURL()
API for scripts, but a simple regexp for modules.
Can this be fixed without adding a full fledge ES parser? IMO the increase in correctness would not be worth the decrease of performance such parser would impose – also I'd expect that no one is affected by this bug, but you never know 😅
V8's GetSourceMappingURL()
API is also available on modules.
Fixed in https://github.com/nodejs/node/pull/51690