SourceMap.findEntry() returns a stale name for a final mapping segment that has no name index
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 25/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 停滞
- 技術スタック
- javascript
- 領域
- tooling
調査の方向性
報告にある JavaScript スニペットで問題を再現し、その後、SourceMap の #parseMap におけるオプションの name フィールドの処理を調べます。最小のマッピング例に対するリグレッションカバレッジを追加し、位置情報だけを含む最終マッピングが前の名前を再利用せず、undefined の名前を返す状態を完了とします。
索引モデルが issue の本文から書いたものです。
説明
Version
v24.8.0 (present on main; introduced in v15.4.0 / v14.17.1)
Platform
all
Subsystem
module / source maps
What steps will reproduce the bug?
The simplest way to recreate the issue is:
const { SourceMap } = require('node:module');
const sm = new SourceMap({
version: 3, sources: ['a.js'], names: ['foo'], mappings: 'AAAAA,CAAC',
});
console.log(sm.findEntry(0, 1).name); // prints 'foo'
How often does it reproduce? Is there a required condition?
Fails on every run, deterministically.
Required condition: the source map's mappings string must end with a location-only segment (4 fields, no name index), and some earlier segment must have set a name index (i.e. names is non-empty and was referenced before theend). When both hold, findEntry() on that final segment returns the last-seen name instead of undefined
Both conditions are the norm for real minified bundles, so in practice it triggers on essentially every production source map. The minimal repro above (mappings: 'AAAAA,CAAC') is the smallest case that satisfies it.
With --enable-source-maps, the bottom global frame of a stack trace inherits the last-named function instead of being anonymous. Empirically: absent in v14.17.0, appears in v14.17.1 (and v15.4.0), introduced by #36042.
What is the expected behavior? Why is that the expected behavior?
The second segment (CAAC) has only 4 fields and no name index, so findEntry(0, 1).name should be undefined.
What do you see instead?
It returns 'foo', the name from the previous segment.
Additional information
In practice this leads to stack traces being subtly wrong: under --enable-source-maps, the bottom global/anonymous frame is labeled with the last-named function instead of being anonymous. The wrong name is a real identifier from the program, so it looks correct and misleads during debugging rather than being noticed as a defect.
The bug is in SourceMap's #parseMap, it reads the optional 5th (name) VLQ guarded only by !isSeparator(stringCharIterator.peek()). At the end of the mappings string peek() returns '', which is not a separator, so it decodes a phantom VLQ (0), keeps the previous nameIndex, and assigns names[nameIndex] to a segment with no name.
I've implemented a one line fix and I'll open a PR and link it here as soon as it's ready.
- 主要言語
- JavaScript
- スター
- 122k
- フォーク
- 37.4k
- 平均マージ
- 4日 3時間
- マージ済み PR(30日)
- 279
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
nodejs/node のほかの issue
-
doc
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
-
build
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
-
難易度 1/5 1時間未満 初心者へのやさしさ 90/100
-
feature request
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
docToolchain/docToolchain#1705 ·
-
Timezone select lists one option per character; duplicate "Failed" reason; shared tracker popover id オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
nightscout/nocturne#1414 ·
-
bug v2
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
modelcontextprotocol/inspector#2458 · コメント 1 件 ·
-
Mend: dependency security vulnerability status: needs triage 🕵️♀️
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
carbon-design-system/ibm-products#9907 ·