node icon indicating copy to clipboard operation
node copied to clipboard

String that looks like a source map comment gets used as a source map comment, but only in ESM

Open nicolo-ribaudo opened this issue 1 year ago • 3 comments

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

nicolo-ribaudo avatar Jan 19 '24 11:01 nicolo-ribaudo

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.

nicolo-ribaudo avatar Jan 19 '24 11:01 nicolo-ribaudo

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 😅

aduh95 avatar Jan 19 '24 13:01 aduh95

V8's GetSourceMappingURL() API is also available on modules.

targos avatar Jan 19 '24 13:01 targos

Fixed in https://github.com/nodejs/node/pull/51690

legendecas avatar Feb 26 '24 03:02 legendecas