Dev server `.map` ignores the source map a custom serializer returns
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 45/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
- 技术栈
- javascript, react-native
调研方向
Read the dev server paths that build .map responses and handle /symbolicate, then compare them with Server.build() and the serializer contract in the issue. Use the ErrorBundle.js integration fixture and the provided custom serializer to reproduce the mismatched source locations. Done means the served map and /symbolicate resolve frames consistently with the served bundle, including when a custom serializer returns a map.
由索引模型根据 Issue 内容生成。
描述
Filing this AI-reported issue related to #1284 for reference:
Summary
When serializer.customSerializer returns {code, map}, the dev server serves the serializer's code for .bundle requests, but it never calls the serializer for .map requests. Instead, .map is built from Metro's default placement: prepend followed by the graph's modules sorted by id. If the serializer lays the bundle out differently from baseJSBundle, the served map doesn't match the served bundle. This happens even when the serializer follows the contract: it treats preModules and graph as read-only and returns a correct map. Server.build() (runBuild, metro build) already uses the returned map, so only the dev server is affected.
The common case is a serializer that adds a module before the app code by prepending it to a copy of preModules. Today, the only way to get such a module into the dev server's .map is to mutate preModules in place. The ReadonlyArray type forbids that, and because preModules is the graph revision's shared prepend array, a serializer that doesn't dedupe adds another copy on every request.
#1284 makes .map use the serializer's map. /symbolicate has the same gap, since it places modules the same way without calling the serializer, and #1284 doesn't change it.
Reproduction
This uses Metro main at d233537, the integration test fixture packages/metro/src/integration_tests/basic_bundle/ErrorBundle.js, and this serializer:
const baseJSBundle = require('metro/private/DeltaBundler/Serializers/baseJSBundle').default;
const {sourceMapString} = require('metro/private/DeltaBundler/Serializers/sourceMapString');
const bundleToString = require('metro/private/lib/bundleToString').default;
const CountingSet = require('metro/private/lib/CountingSet').default;
const code = 'var a = 1;\nvar b = 2;\nvar c = 3;';
const injected = {
path: '__injected__',
dependencies: new Map(),
inverseDependencies: new CountingSet(),
getSource: () => Buffer.from(code),
output: [{type: 'js/script/virtual', data: {code, lineCount: 3, map: []}}],
};
async function customSerializer(entryPoint, preModules, graph, options) {
// A copy: preModules is never mutated.
const pre = [preModules[0], injected, ...preModules.slice(1)];
const modules = [...graph.dependencies.values()].sort(
(a, b) => options.createModuleId(a.path) - options.createModuleId(b.path),
);
return {
code: bundleToString(baseJSBundle(entryPoint, pre, graph, options)).code,
map: sourceMapString([...pre, ...modules], {
excludeSource: false,
processModuleFilter: options.processModuleFilter,
shouldAddToIgnoreList: options.shouldAddToIgnoreList,
getSourceUrl: options.getSourceUrl,
}),
};
}
- Start the dev server with this serializer and fetch
/ErrorBundle.bundle?platform=ios&dev=true&minify=false. - Find the generated position of
new Error('SOURCEMAP:in the response (line 683, column 16). - Look that position up in
/ErrorBundle.map?platform=ios&dev=true&minify=falsewithsource-map, and send the same frame to/symbolicate.
| Expected | main |
With #1284 | |
|---|---|---|---|
.map |
ErrorBundle.js:18 |
ErrorBundle.js:23 |
ErrorBundle.js:18 |
/symbolicate |
ErrorBundle.js:18 |
ErrorBundle.js:23 |
ErrorBundle.js:23 |
Without the custom serializer, both resolve to line 18.
Expected behavior
For a given bundle URL, .map and /symbolicate should agree with the code the dev server serves for that URL. When a custom serializer returns a map, the dev server should use it.
Notes
- A serializer that changes the layout but returns only a string (for example, a banner, or modules emitted in a different order) can't be fixed by using its map, because there isn't one. Those also give wrong
.mapand/symbolicateresults today. Fixing them needs either a rule that a layout-changing serializer must return a map, or a way for serializers to add pre-modules that Metro places itself. - Sentry's serializer prepends modules to a copy of
preModulesin this way. From reading its source (not reproduced), its module-metadata module is also injected in dev whenmoduleMetadatais set, and should shift dev.mapand/symbolicateresults by one line.
- 主要语言
- JavaScript
- 星标
- 5.7k
- 派生
- 715
- 平均合并
- 1 天 15 小时
- 30 天内合并 PR
- 96
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
react/metro 的其他 Issue
-
[metro-file-map] An error a watcher backend reports ends the server, since nothing listens for it可能已有人在做 @sorinc03 于 9 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 82/100
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 42/100
维护者通常 1 天内回复
-
难度 5/5 一周以上 新手友好度 35/100
维护者通常 1 天内回复
-
metro-file-map gives up on a fallback watcher that is still starting after a fixed 240 s, and leaves it running可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭
难度 4/5 3-5 天 新手友好度 48/100
维护者通常 1 天内回复
-
Published declarations import types from connect, @babel/core and @babel/traverse, whose @types packages are not dependencies可能已有人在做 @sorinc03 于 9 天前认领。 未关闭
难度 3/5 1-2 天 新手友好度 72/100
维护者通常 1 天内回复
相似的 Issue
-
maintenance
难度 2/5 1-3 小时 新手友好度 78/100
assistant-ui/assistant-ui#10496 · 1 条评论 · 1 个 reaction ·
维护者通常 1 天内回复
-
ai bug design good first issue
难度 2/5 1-3 小时 新手友好度 82/100
neomjs/neo-agent-institution#927 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
gramps-project/gramps-web#1671 ·
维护者通常 1 天内回复
-
bug good first issue priority: P2 status: ready
难度 2/5 1-3 小时 新手友好度 78/100
RhinoLink-Tech/data-fabric#502 ·
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 75/100
cline/mcp-marketplace#3708 ·