Skip to content

Commit ad4ecb6

Browse files
authored
[DevTools] Fix symbolication with Index Source Maps (#34300)
1 parent 26e87b5 commit ad4ecb6

File tree

2 files changed

+35
-61
lines changed

2 files changed

+35
-61
lines changed

packages/react-devtools-shared/src/hooks/SourceMapConsumer.js

Lines changed: 34 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ function BasicSourceMapConsumer(sourceMapJSON: BasicSourceMap) {
136136
}
137137

138138
type Section = {
139-
+generatedColumn: number,
140-
+generatedLine: number,
141-
+map: MixedSourceMap,
139+
+offsetColumn0: number,
140+
+offsetLine0: number,
141+
+map: BasicSourceMap,
142142

143143
// Lazily parsed only when/as the section is needed.
144144
sourceMapConsumer: SourceMapConsumerType | null,
@@ -160,22 +160,21 @@ function IndexedSourceMapConsumer(sourceMapJSON: IndexSourceMap) {
160160
column: number,
161161
...
162162
} = section.offset;
163-
const offsetLine = offset.line;
164-
const offsetColumn = offset.column;
163+
const offsetLine0 = offset.line;
164+
const offsetColumn0 = offset.column;
165165

166166
if (
167-
offsetLine < lastOffset.line ||
168-
(offsetLine === lastOffset.line && offsetColumn < lastOffset.column)
167+
offsetLine0 < lastOffset.line ||
168+
(offsetLine0 === lastOffset.line && offsetColumn0 < lastOffset.column)
169169
) {
170170
throw new Error('Section offsets must be ordered and non-overlapping.');
171171
}
172172

173173
lastOffset = offset;
174174

175175
return {
176-
// The offset fields are 0-based, but we use 1-based indices when encoding/decoding from VLQ.
177-
generatedLine: offsetLine + 1,
178-
generatedColumn: offsetColumn + 1,
176+
offsetLine0,
177+
offsetColumn0,
179178
map: section.map,
180179
sourceMapConsumer: null,
181180
};
@@ -186,55 +185,29 @@ function IndexedSourceMapConsumer(sourceMapJSON: IndexSourceMap) {
186185
lineNumber,
187186
}: SearchPosition): ResultPosition {
188187
// Error.prototype.stack columns are 1-based (like most IDEs) but ASTs are 0-based.
189-
const targetColumnNumber = columnNumber - 1;
190-
191-
let section = null;
192-
193-
let startIndex = 0;
194-
let stopIndex = sections.length - 1;
195-
let index = -1;
196-
while (startIndex <= stopIndex) {
197-
index = Math.floor((stopIndex + startIndex) / 2);
198-
section = sections[index];
199-
200-
const currentLine = section.generatedLine;
201-
if (currentLine === lineNumber) {
202-
const currentColumn = section.generatedColumn;
203-
if (currentColumn === lineNumber) {
204-
break;
205-
} else {
206-
if (currentColumn > targetColumnNumber) {
207-
if (stopIndex - index > 0) {
208-
stopIndex = index;
209-
} else {
210-
index = stopIndex;
211-
break;
212-
}
213-
} else {
214-
if (index - startIndex > 0) {
215-
startIndex = index;
216-
} else {
217-
index = startIndex;
218-
break;
219-
}
220-
}
221-
}
188+
const column0 = columnNumber - 1;
189+
const line0 = lineNumber - 1;
190+
191+
// Sections must not overlap and must be sorted: https://tc39.es/source-map/#section-object
192+
// Therefore the last section that has an offset less than or equal to the frame is the applicable one.
193+
let left = 0;
194+
let right = sections.length - 1;
195+
let section: Section | null = null;
196+
197+
while (left <= right) {
198+
// fast Math.floor
199+
const middle = ~~((left + right) / 2);
200+
const currentSection = sections[middle];
201+
202+
if (
203+
currentSection.offsetLine0 < line0 ||
204+
(currentSection.offsetLine0 === line0 &&
205+
currentSection.offsetColumn0 <= column0)
206+
) {
207+
section = currentSection;
208+
left = middle + 1;
222209
} else {
223-
if (currentLine > lineNumber) {
224-
if (stopIndex - index > 0) {
225-
stopIndex = index;
226-
} else {
227-
index = stopIndex;
228-
break;
229-
}
230-
} else {
231-
if (index - startIndex > 0) {
232-
startIndex = index;
233-
} else {
234-
index = startIndex;
235-
break;
236-
}
237-
}
210+
right = middle - 1;
238211
}
239212
}
240213

@@ -252,8 +225,9 @@ function IndexedSourceMapConsumer(sourceMapJSON: IndexSourceMap) {
252225
}
253226

254227
return section.sourceMapConsumer.originalPositionFor({
255-
columnNumber,
256-
lineNumber,
228+
// The mappings in a Source Map section are relative to the section offset.
229+
columnNumber: columnNumber - section.offsetColumn0,
230+
lineNumber: lineNumber - section.offsetLine0,
257231
});
258232
}
259233

packages/react-devtools-shared/src/hooks/SourceMapTypes.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export type BasicSourceMap = {
2929
};
3030

3131
export type IndexSourceMapSection = {
32-
map: IndexSourceMap | BasicSourceMap,
32+
map: BasicSourceMap,
3333
offset: {
3434
line: number,
3535
column: number,

0 commit comments

Comments
 (0)