@samitouri / QOS-React-2 / commits / b1a1cb1168

DevTools: Lazily parse indexed map sections (#22415)

Indexed maps divide nested source maps into sections, annotated with a line and column offset. Since these sections are JSON and can be quickly parsed, we can easily separate them without doing the heavier base64 and VLQ decoding process. This PR updates our sourcemap parsing code to defer parsing of an indexed map section until we actually need to retrieve mappings from it.

Brian Vaughn committed Sep 24, 2021 at 11:09 UTC b1a1cb11680cf4a03932e8955f64d5a7ba9c89f1
1 file changed +19 -3
packages/react-devtools-shared/src/hooks/SourceMapConsumer.js
+19 -3
@@ -11,6 +11,7 @@ import {decode} from 'sourcemap-codec';
11
12 import type {
13 IndexSourceMap,
14 + IndexSourceMapSection,
15 BasicSourceMap,
16 MixedSourceMap,
17 } from './SourceMapTypes';
@@ -34,7 +35,7 @@ export type SourceMapConsumerType = {|
35 type Mappings = Array<Array<Array<number>>>;
36
37 export default function SourceMapConsumer(
37 - sourceMapJSON: MixedSourceMap,
38 + sourceMapJSON: MixedSourceMap | IndexSourceMapSection,
39 ): SourceMapConsumerType {
40 if (sourceMapJSON.sections != null) {
41 return IndexedSourceMapConsumer(((sourceMapJSON: any): IndexSourceMap));
@@ -137,13 +138,22 @@ function BasicSourceMapConsumer(sourceMapJSON: BasicSourceMap) {
138 }: any): SourceMapConsumerType);
139 }
140
141 +type Section = {|
142 + +generatedColumn: number,
143 + +generatedLine: number,
144 + +map: MixedSourceMap,
145 +
146 + // Lazily parsed only when/as the section is needed.
147 + sourceMapConsumer: SourceMapConsumerType | null,
148 +|};
149 +
150 function IndexedSourceMapConsumer(sourceMapJSON: IndexSourceMap) {
151 let lastOffset = {
152 line: -1,
153 column: 0,
154 };
155
146 - const sections = sourceMapJSON.sections.map(section => {
156 + const sections: Array<Section> = sourceMapJSON.sections.map(section => {
157 const offset = section.offset;
158 const offsetLine = offset.line;
159 const offsetColumn = offset.column;
@@ -161,7 +171,8 @@ function IndexedSourceMapConsumer(sourceMapJSON: IndexSourceMap) {
171 // The offset fields are 0-based, but we use 1-based indices when encoding/decoding from VLQ.
172 generatedLine: offsetLine + 1,
173 generatedColumn: offsetColumn + 1,
164 - sourceMapConsumer: new SourceMapConsumer(section.map),
174 + map: section.map,
175 + sourceMapConsumer: null,
176 };
177 });
178
@@ -229,6 +240,11 @@ function IndexedSourceMapConsumer(sourceMapJSON: IndexSourceMap) {
240 );
241 }
242
243 + if (section.sourceMapConsumer === null) {
244 + // Lazily parse the section only when it's needed.
245 + section.sourceMapConsumer = new SourceMapConsumer(section.map);
246 + }
247 +
248 return section.sourceMapConsumer.originalPositionFor({
249 columnNumber,
250 lineNumber,