nodejs / nodejs/node

SourceMap.findEntry() returns a stale name for a final mapping segment that has no name index

未关闭
#63,795 2 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

source maps stale
主要语言
JavaScript
星标
122k
派生
37.4k
平均合并
4 天 3 小时
30 天内合并 PR
272

描述

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.

PR Link: https://github.com/nodejs/node/pull/63801

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

使用报告中的 JavaScript 代码片段重现该问题,然后检查 SourceMap 在 #parseMap 中对可选 name 字段的处理。完成标准是:仅包含位置的最终映射返回 undefined 名称,而不是重新使用前一个名称,并为最小映射示例补充回归覆盖。

由索引模型根据 Issue 内容生成。

评估

技术栈
javascript
领域
tooling
Issue 类型
缺陷
难度
2/5
预计耗时
1-3 小时
活跃度
停滞
描述清晰度
描述清楚
新手友好度
25/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。