Dev server `.map` ignores the source map a custom serializer returns
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 45/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- javascript, react-native
- Lĩnh vực
- backend-api-design, devtools
Hướng nghiên cứu
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.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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.
- Ngôn ngữ chính
- JavaScript
- Star
- 5.7k
- Fork
- 715
- Merge trung bình
- 1 ngày 15 giờ
- Pull request đã merge (30 ngày)
- 96
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của react/metro
-
[metro-file-map] An error a watcher backend reports ends the server, since nothing listens for itCó thể đã có người làm @sorinc03 đã nhận 9 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 42/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
Maintainer thường phản hồi trong vòng 1 ngày
-
metro-file-map gives up on a fallback watcher that is still starting after a fixed 240 s, and leaves it runningCó thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
react/metro#2140 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Published declarations import types from connect, @babel/core and @babel/traverse, whose @types packages are not dependenciesCó thể đã có người làm @sorinc03 đã nhận 9 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày
Issue tương tự
-
ai bug design good first issue
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
neomjs/neo-agent-institution#927 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
gramps-project/gramps-web#1671 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug good first issue priority: P2 status: ready
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
RhinoLink-Tech/data-fabric#502 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Server Submission]: PayStageĐang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 75/100
cline/mcp-marketplace#3708 ·
-
beginner-friendly category:finding-titles community enhancement first-timers-only good first issue help wanted low hanging fruit micro-contribution type: task up-for-grabs
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 85/100
Berserk-hub150/skillhawk#264 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 4 ngày