blob: f7dd03b92a0eb2a51051090c4ed9e1b0315b8b47 [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371/*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
Tim van der Lippe9293af72020-01-17 10:50:3731import {CompilerSourceMappingContentProvider} from './CompilerSourceMappingContentProvider.js';
32
Blink Reformat4c46d092018-04-07 15:32:3733/**
Tim van der Lippe9b7d21d2019-10-07 18:48:0734 * @interface
35 */
Tim van der Lippe9293af72020-01-17 10:50:3736export class SourceMap {
Tim van der Lippe9b7d21d2019-10-07 18:48:0737 /**
38 * @return {string}
39 */
40 compiledURL() {
41 }
42
43 /**
44 * @return {string}
45 */
46 url() {
47 }
48
49 /**
50 * @return {!Array<string>}
51 */
52 sourceURLs() {
53 }
54
55 /**
56 * @param {string} sourceURL
57 * @param {!Common.ResourceType} contentType
58 * @return {!Common.ContentProvider}
59 */
60 sourceContentProvider(sourceURL, contentType) {
61 }
62
63 /**
64 * @param {string} sourceURL
65 * @return {?string}
66 */
67 embeddedContentByURL(sourceURL) {
68 }
69
70 /**
71 * @param {number} lineNumber in compiled resource
72 * @param {number} columnNumber in compiled resource
73 * @return {?SourceMapEntry}
74 */
75 findEntry(lineNumber, columnNumber) {
76 }
Ingvar Stepanyan1a8762b2019-10-29 18:24:3977
78 /**
79 * @param {string} sourceURL
80 * @param {number} lineNumber
81 * @param {number} columnNumber
82 * @return {?SourceMapEntry}
83 */
84 sourceLineMapping(sourceURL, lineNumber, columnNumber) {
85 }
86
87 /**
88 * @return {!Array<!SourceMapEntry>}
89 */
90 mappings() {
91 }
92
93 dispose() {
94 }
Tim van der Lippe9b7d21d2019-10-07 18:48:0795}
96
97/**
Blink Reformat4c46d092018-04-07 15:32:3798 * @unrestricted
99 */
Tim van der Lippec96ccd92019-11-29 16:23:54100class SourceMapV3 {
Blink Reformat4c46d092018-04-07 15:32:37101 constructor() {
102 /** @type {number} */ this.version;
103 /** @type {string|undefined} */ this.file;
104 /** @type {!Array.<string>} */ this.sources;
Tim van der Lippe9b7d21d2019-10-07 18:48:07105 /** @type {!Array.<!SourceMapV3.Section>|undefined} */ this.sections;
Blink Reformat4c46d092018-04-07 15:32:37106 /** @type {string} */ this.mappings;
107 /** @type {string|undefined} */ this.sourceRoot;
108 /** @type {!Array.<string>|undefined} */ this.names;
109 }
Tim van der Lippe9b7d21d2019-10-07 18:48:07110}
Blink Reformat4c46d092018-04-07 15:32:37111
112/**
113 * @unrestricted
114 */
Tim van der Lippe9b7d21d2019-10-07 18:48:07115SourceMapV3.Section = class {
Blink Reformat4c46d092018-04-07 15:32:37116 constructor() {
Tim van der Lippe9b7d21d2019-10-07 18:48:07117 /** @type {!SourceMapV3} */ this.map;
118 /** @type {!SourceMapV3.Offset} */ this.offset;
Blink Reformat4c46d092018-04-07 15:32:37119 }
120};
121
122/**
123 * @unrestricted
124 */
Tim van der Lippe9b7d21d2019-10-07 18:48:07125SourceMapV3.Offset = class {
Blink Reformat4c46d092018-04-07 15:32:37126 constructor() {
127 /** @type {number} */ this.line;
128 /** @type {number} */ this.column;
129 }
130};
131
132/**
133 * @unrestricted
134 */
Tim van der Lippe9b7d21d2019-10-07 18:48:07135export class SourceMapEntry {
Blink Reformat4c46d092018-04-07 15:32:37136 /**
137 * @param {number} lineNumber
138 * @param {number} columnNumber
139 * @param {string=} sourceURL
140 * @param {number=} sourceLineNumber
141 * @param {number=} sourceColumnNumber
142 * @param {string=} name
143 */
144 constructor(lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber, name) {
145 this.lineNumber = lineNumber;
146 this.columnNumber = columnNumber;
147 this.sourceURL = sourceURL;
148 this.sourceLineNumber = sourceLineNumber;
149 this.sourceColumnNumber = sourceColumnNumber;
150 this.name = name;
151 }
152
153 /**
Tim van der Lippe9b7d21d2019-10-07 18:48:07154 * @param {!SourceMapEntry} entry1
155 * @param {!SourceMapEntry} entry2
Blink Reformat4c46d092018-04-07 15:32:37156 * @return {number}
157 */
158 static compare(entry1, entry2) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34159 if (entry1.lineNumber !== entry2.lineNumber) {
Blink Reformat4c46d092018-04-07 15:32:37160 return entry1.lineNumber - entry2.lineNumber;
Tim van der Lippe1d6e57a2019-09-30 11:55:34161 }
Blink Reformat4c46d092018-04-07 15:32:37162 return entry1.columnNumber - entry2.columnNumber;
163 }
Tim van der Lippe9b7d21d2019-10-07 18:48:07164}
Blink Reformat4c46d092018-04-07 15:32:37165
166/**
167 * @unrestricted
168 */
Tim van der Lippe9b7d21d2019-10-07 18:48:07169export class EditResult {
Blink Reformat4c46d092018-04-07 15:32:37170 /**
Tim van der Lippe9b7d21d2019-10-07 18:48:07171 * @param {!SourceMap} map
Blink Reformat4c46d092018-04-07 15:32:37172 * @param {!Array<!TextUtils.SourceEdit>} compiledEdits
173 * @param {!Map<string, string>} newSources
174 */
175 constructor(map, compiledEdits, newSources) {
176 this.map = map;
177 this.compiledEdits = compiledEdits;
178 this.newSources = newSources;
179 }
Tim van der Lippe9b7d21d2019-10-07 18:48:07180}
Blink Reformat4c46d092018-04-07 15:32:37181
182/**
Tim van der Lippe9b7d21d2019-10-07 18:48:07183 * @implements {SourceMap}
Blink Reformat4c46d092018-04-07 15:32:37184 * @unrestricted
185 */
Tim van der Lippe9b7d21d2019-10-07 18:48:07186export class TextSourceMap {
Blink Reformat4c46d092018-04-07 15:32:37187 /**
188 * Implements Source Map V3 model. See https://github.com/google/closure-compiler/wiki/Source-Maps
189 * for format description.
190 * @param {string} compiledURL
191 * @param {string} sourceMappingURL
Tim van der Lippe9b7d21d2019-10-07 18:48:07192 * @param {!SourceMapV3} payload
Blink Reformat4c46d092018-04-07 15:32:37193 */
194 constructor(compiledURL, sourceMappingURL, payload) {
Tim van der Lippe9b7d21d2019-10-07 18:48:07195 if (!TextSourceMap._base64Map) {
Blink Reformat4c46d092018-04-07 15:32:37196 const base64Digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
Tim van der Lippe9b7d21d2019-10-07 18:48:07197 TextSourceMap._base64Map = {};
Tim van der Lippe1d6e57a2019-09-30 11:55:34198 for (let i = 0; i < base64Digits.length; ++i) {
Tim van der Lippe9b7d21d2019-10-07 18:48:07199 TextSourceMap._base64Map[base64Digits.charAt(i)] = i;
Tim van der Lippe1d6e57a2019-09-30 11:55:34200 }
Blink Reformat4c46d092018-04-07 15:32:37201 }
202
203 this._json = payload;
204 this._compiledURL = compiledURL;
205 this._sourceMappingURL = sourceMappingURL;
206 this._baseURL = sourceMappingURL.startsWith('data:') ? compiledURL : sourceMappingURL;
207
Tim van der Lippe9b7d21d2019-10-07 18:48:07208 /** @type {?Array<!SourceMapEntry>} */
Blink Reformat4c46d092018-04-07 15:32:37209 this._mappings = null;
Tim van der Lippe9b7d21d2019-10-07 18:48:07210 /** @type {!Map<string, !TextSourceMap.SourceInfo>} */
Blink Reformat4c46d092018-04-07 15:32:37211 this._sourceInfos = new Map();
Andrey Lushnikov5df9c3f2019-01-11 02:08:16212 if (this._json.sections) {
213 const sectionWithURL = !!this._json.sections.find(section => !!section.url);
Tim van der Lippe1d6e57a2019-09-30 11:55:34214 if (sectionWithURL) {
Andrey Lushnikov5df9c3f2019-01-11 02:08:16215 Common.console.warn(`SourceMap "${sourceMappingURL}" contains unsupported "URL" field in one of its sections.`);
Tim van der Lippe1d6e57a2019-09-30 11:55:34216 }
Andrey Lushnikov5df9c3f2019-01-11 02:08:16217 }
Blink Reformat4c46d092018-04-07 15:32:37218 this._eachSection(this._parseSources.bind(this));
219 }
220
221 /**
222 * @param {string} sourceMapURL
223 * @param {string} compiledURL
Tim van der Lippe9b7d21d2019-10-07 18:48:07224 * @return {!Promise<?TextSourceMap>}
225 * @this {TextSourceMap}
Blink Reformat4c46d092018-04-07 15:32:37226 */
Ingvar Stepanyan1a8762b2019-10-29 18:24:39227 static async load(sourceMapURL, compiledURL) {
228 let content = await new Promise((resolve, reject) => {
Sigurd Schneidera327cde2020-01-21 15:48:12229 SDK.multitargetNetworkManager.loadResource(sourceMapURL, (success, _headers, content, errorDescription) => {
230 if (!content || !success) {
231 const error = new Error(ls`Could not load content for ${sourceMapURL}: ${errorDescription.message}`);
Ingvar Stepanyan1a8762b2019-10-29 18:24:39232 reject(error);
233 } else {
234 resolve(content);
235 }
236 });
237 });
Blink Reformat4c46d092018-04-07 15:32:37238
Ingvar Stepanyan1a8762b2019-10-29 18:24:39239 if (content.slice(0, 3) === ')]}') {
240 content = content.substring(content.indexOf('\n'));
Blink Reformat4c46d092018-04-07 15:32:37241 }
Ingvar Stepanyan1a8762b2019-10-29 18:24:39242
Sigurd Schneider4c5f0c62019-12-11 12:24:09243 try {
244 const payload = /** @type {!SourceMapV3} */ (JSON.parse(content));
245 return new TextSourceMap(compiledURL, sourceMapURL, payload);
246 } catch (error) {
247 throw new Error(ls`Could not parse content for ${sourceMapURL}: ${error.message}`);
248 }
Blink Reformat4c46d092018-04-07 15:32:37249 }
250
251 /**
252 * @override
253 * @return {string}
254 */
255 compiledURL() {
256 return this._compiledURL;
257 }
258
259 /**
260 * @override
261 * @return {string}
262 */
263 url() {
264 return this._sourceMappingURL;
265 }
266
267 /**
268 * @override
269 * @return {!Array.<string>}
270 */
271 sourceURLs() {
272 return this._sourceInfos.keysArray();
273 }
274
275 /**
276 * @override
277 * @param {string} sourceURL
278 * @param {!Common.ResourceType} contentType
279 * @return {!Common.ContentProvider}
280 */
281 sourceContentProvider(sourceURL, contentType) {
282 const info = this._sourceInfos.get(sourceURL);
Tim van der Lippe1d6e57a2019-09-30 11:55:34283 if (info.content) {
Blink Reformat4c46d092018-04-07 15:32:37284 return Common.StaticContentProvider.fromString(sourceURL, contentType, info.content);
Tim van der Lippe1d6e57a2019-09-30 11:55:34285 }
Tim van der Lippe9293af72020-01-17 10:50:37286 return new CompilerSourceMappingContentProvider(sourceURL, contentType);
Blink Reformat4c46d092018-04-07 15:32:37287 }
288
289 /**
290 * @override
291 * @param {string} sourceURL
292 * @return {?string}
293 */
294 embeddedContentByURL(sourceURL) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34295 if (!this._sourceInfos.has(sourceURL)) {
Blink Reformat4c46d092018-04-07 15:32:37296 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34297 }
Blink Reformat4c46d092018-04-07 15:32:37298 return this._sourceInfos.get(sourceURL).content;
299 }
300
301 /**
302 * @override
Blink Reformat4c46d092018-04-07 15:32:37303 * @param {number} lineNumber in compiled resource
304 * @param {number} columnNumber in compiled resource
Tim van der Lippe9b7d21d2019-10-07 18:48:07305 * @return {?SourceMapEntry}
Blink Reformat4c46d092018-04-07 15:32:37306 */
307 findEntry(lineNumber, columnNumber) {
308 const mappings = this.mappings();
309 const index = mappings.upperBound(
310 undefined, (unused, entry) => lineNumber - entry.lineNumber || columnNumber - entry.columnNumber);
311 return index ? mappings[index - 1] : null;
312 }
313
314 /**
Ingvar Stepanyan1a8762b2019-10-29 18:24:39315 * @override
Blink Reformat4c46d092018-04-07 15:32:37316 * @param {string} sourceURL
317 * @param {number} lineNumber
318 * @param {number} columnNumber
Tim van der Lippe9b7d21d2019-10-07 18:48:07319 * @return {?SourceMapEntry}
Blink Reformat4c46d092018-04-07 15:32:37320 */
321 sourceLineMapping(sourceURL, lineNumber, columnNumber) {
322 const mappings = this._reversedMappings(sourceURL);
323 const first = mappings.lowerBound(lineNumber, lineComparator);
324 const last = mappings.upperBound(lineNumber, lineComparator);
Tim van der Lippe1d6e57a2019-09-30 11:55:34325 if (first >= mappings.length || mappings[first].sourceLineNumber !== lineNumber) {
Blink Reformat4c46d092018-04-07 15:32:37326 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34327 }
Blink Reformat4c46d092018-04-07 15:32:37328 const columnMappings = mappings.slice(first, last);
Tim van der Lippe1d6e57a2019-09-30 11:55:34329 if (!columnMappings.length) {
Alexey Kozyatinskiy1b61b762018-05-03 00:25:13330 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34331 }
Blink Reformat4c46d092018-04-07 15:32:37332 const index =
333 columnMappings.lowerBound(columnNumber, (columnNumber, mapping) => columnNumber - mapping.sourceColumnNumber);
Alexey Kozyatinskiy1b61b762018-05-03 00:25:13334 return index >= columnMappings.length ? columnMappings[columnMappings.length - 1] : columnMappings[index];
Blink Reformat4c46d092018-04-07 15:32:37335
336 /**
337 * @param {number} lineNumber
Tim van der Lippe9b7d21d2019-10-07 18:48:07338 * @param {!SourceMapEntry} mapping
Blink Reformat4c46d092018-04-07 15:32:37339 * @return {number}
340 */
341 function lineComparator(lineNumber, mapping) {
342 return lineNumber - mapping.sourceLineNumber;
343 }
344 }
345
346 /**
347 * @param {string} sourceURL
348 * @param {number} lineNumber
349 * @param {number} columnNumber
Tim van der Lippe9b7d21d2019-10-07 18:48:07350 * @return {!Array<!SourceMapEntry>}
Blink Reformat4c46d092018-04-07 15:32:37351 */
352 findReverseEntries(sourceURL, lineNumber, columnNumber) {
353 const mappings = this._reversedMappings(sourceURL);
354 const endIndex = mappings.upperBound(
355 undefined, (unused, entry) => lineNumber - entry.sourceLineNumber || columnNumber - entry.sourceColumnNumber);
356 let startIndex = endIndex;
357 while (startIndex > 0 && mappings[startIndex - 1].sourceLineNumber === mappings[endIndex - 1].sourceLineNumber &&
Tim van der Lippe1d6e57a2019-09-30 11:55:34358 mappings[startIndex - 1].sourceColumnNumber === mappings[endIndex - 1].sourceColumnNumber) {
Blink Reformat4c46d092018-04-07 15:32:37359 --startIndex;
Tim van der Lippe1d6e57a2019-09-30 11:55:34360 }
Blink Reformat4c46d092018-04-07 15:32:37361
362 return mappings.slice(startIndex, endIndex);
363 }
364
365 /**
Ingvar Stepanyan1a8762b2019-10-29 18:24:39366 * @override
Tim van der Lippe9b7d21d2019-10-07 18:48:07367 * @return {!Array<!SourceMapEntry>}
Blink Reformat4c46d092018-04-07 15:32:37368 */
369 mappings() {
370 if (this._mappings === null) {
371 this._mappings = [];
372 this._eachSection(this._parseMap.bind(this));
373 this._json = null;
374 }
Tim van der Lippe9b7d21d2019-10-07 18:48:07375 return /** @type {!Array<!SourceMapEntry>} */ (this._mappings);
Blink Reformat4c46d092018-04-07 15:32:37376 }
377
378 /**
379 * @param {string} sourceURL
Tim van der Lippe9b7d21d2019-10-07 18:48:07380 * @return {!Array.<!SourceMapEntry>}
Blink Reformat4c46d092018-04-07 15:32:37381 */
382 _reversedMappings(sourceURL) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34383 if (!this._sourceInfos.has(sourceURL)) {
Blink Reformat4c46d092018-04-07 15:32:37384 return [];
Tim van der Lippe1d6e57a2019-09-30 11:55:34385 }
Blink Reformat4c46d092018-04-07 15:32:37386 const mappings = this.mappings();
387 const info = this._sourceInfos.get(sourceURL);
Tim van der Lippe1d6e57a2019-09-30 11:55:34388 if (info.reverseMappings === null) {
Blink Reformat4c46d092018-04-07 15:32:37389 info.reverseMappings = mappings.filter(mapping => mapping.sourceURL === sourceURL).sort(sourceMappingComparator);
Tim van der Lippe1d6e57a2019-09-30 11:55:34390 }
Blink Reformat4c46d092018-04-07 15:32:37391
392 return info.reverseMappings;
393
394 /**
Tim van der Lippe9b7d21d2019-10-07 18:48:07395 * @param {!SourceMapEntry} a
396 * @param {!SourceMapEntry} b
Blink Reformat4c46d092018-04-07 15:32:37397 * @return {number}
398 */
399 function sourceMappingComparator(a, b) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34400 if (a.sourceLineNumber !== b.sourceLineNumber) {
Blink Reformat4c46d092018-04-07 15:32:37401 return a.sourceLineNumber - b.sourceLineNumber;
Tim van der Lippe1d6e57a2019-09-30 11:55:34402 }
403 if (a.sourceColumnNumber !== b.sourceColumnNumber) {
Blink Reformat4c46d092018-04-07 15:32:37404 return a.sourceColumnNumber - b.sourceColumnNumber;
Tim van der Lippe1d6e57a2019-09-30 11:55:34405 }
Blink Reformat4c46d092018-04-07 15:32:37406
Tim van der Lippe1d6e57a2019-09-30 11:55:34407 if (a.lineNumber !== b.lineNumber) {
Blink Reformat4c46d092018-04-07 15:32:37408 return a.lineNumber - b.lineNumber;
Tim van der Lippe1d6e57a2019-09-30 11:55:34409 }
Blink Reformat4c46d092018-04-07 15:32:37410
411 return a.columnNumber - b.columnNumber;
412 }
413 }
414
415 /**
Tim van der Lippe9b7d21d2019-10-07 18:48:07416 * @param {function(!SourceMapV3, number, number)} callback
Blink Reformat4c46d092018-04-07 15:32:37417 */
418 _eachSection(callback) {
419 if (!this._json.sections) {
420 callback(this._json, 0, 0);
421 return;
422 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34423 for (const section of this._json.sections) {
Blink Reformat4c46d092018-04-07 15:32:37424 callback(section.map, section.offset.line, section.offset.column);
Tim van der Lippe1d6e57a2019-09-30 11:55:34425 }
Blink Reformat4c46d092018-04-07 15:32:37426 }
427
428 /**
Tim van der Lippe9b7d21d2019-10-07 18:48:07429 * @param {!SourceMapV3} sourceMap
Blink Reformat4c46d092018-04-07 15:32:37430 */
431 _parseSources(sourceMap) {
432 const sourcesList = [];
433 let sourceRoot = sourceMap.sourceRoot || '';
Tim van der Lippe1d6e57a2019-09-30 11:55:34434 if (sourceRoot && !sourceRoot.endsWith('/')) {
Blink Reformat4c46d092018-04-07 15:32:37435 sourceRoot += '/';
Tim van der Lippe1d6e57a2019-09-30 11:55:34436 }
Blink Reformat4c46d092018-04-07 15:32:37437 for (let i = 0; i < sourceMap.sources.length; ++i) {
438 const href = sourceRoot + sourceMap.sources[i];
439 let url = Common.ParsedURL.completeURL(this._baseURL, href) || href;
440 const source = sourceMap.sourcesContent && sourceMap.sourcesContent[i];
Tim van der Lippe1d6e57a2019-09-30 11:55:34441 if (url === this._compiledURL && source) {
Blink Reformat4c46d092018-04-07 15:32:37442 url += Common.UIString('? [sm]');
Tim van der Lippe1d6e57a2019-09-30 11:55:34443 }
Tim van der Lippe9b7d21d2019-10-07 18:48:07444 this._sourceInfos.set(url, new TextSourceMap.SourceInfo(source, null));
Blink Reformat4c46d092018-04-07 15:32:37445 sourcesList.push(url);
446 }
Tim van der Lippe9b7d21d2019-10-07 18:48:07447 sourceMap[TextSourceMap._sourcesListSymbol] = sourcesList;
Blink Reformat4c46d092018-04-07 15:32:37448 }
449
450 /**
Tim van der Lippe9b7d21d2019-10-07 18:48:07451 * @param {!SourceMapV3} map
Blink Reformat4c46d092018-04-07 15:32:37452 * @param {number} lineNumber
453 * @param {number} columnNumber
454 */
455 _parseMap(map, lineNumber, columnNumber) {
456 let sourceIndex = 0;
457 let sourceLineNumber = 0;
458 let sourceColumnNumber = 0;
459 let nameIndex = 0;
Tim van der Lippe9b7d21d2019-10-07 18:48:07460 const sources = map[TextSourceMap._sourcesListSymbol];
Blink Reformat4c46d092018-04-07 15:32:37461 const names = map.names || [];
Tim van der Lippe9b7d21d2019-10-07 18:48:07462 const stringCharIterator = new TextSourceMap.StringCharIterator(map.mappings);
Blink Reformat4c46d092018-04-07 15:32:37463 let sourceURL = sources[sourceIndex];
464
465 while (true) {
466 if (stringCharIterator.peek() === ',') {
467 stringCharIterator.next();
468 } else {
469 while (stringCharIterator.peek() === ';') {
470 lineNumber += 1;
471 columnNumber = 0;
472 stringCharIterator.next();
473 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34474 if (!stringCharIterator.hasNext()) {
Blink Reformat4c46d092018-04-07 15:32:37475 break;
Tim van der Lippe1d6e57a2019-09-30 11:55:34476 }
Blink Reformat4c46d092018-04-07 15:32:37477 }
478
479 columnNumber += this._decodeVLQ(stringCharIterator);
480 if (!stringCharIterator.hasNext() || this._isSeparator(stringCharIterator.peek())) {
Tim van der Lippe9b7d21d2019-10-07 18:48:07481 this._mappings.push(new SourceMapEntry(lineNumber, columnNumber));
Blink Reformat4c46d092018-04-07 15:32:37482 continue;
483 }
484
485 const sourceIndexDelta = this._decodeVLQ(stringCharIterator);
486 if (sourceIndexDelta) {
487 sourceIndex += sourceIndexDelta;
488 sourceURL = sources[sourceIndex];
489 }
490 sourceLineNumber += this._decodeVLQ(stringCharIterator);
491 sourceColumnNumber += this._decodeVLQ(stringCharIterator);
492
493 if (!stringCharIterator.hasNext() || this._isSeparator(stringCharIterator.peek())) {
494 this._mappings.push(
Tim van der Lippe9b7d21d2019-10-07 18:48:07495 new SourceMapEntry(lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber));
Blink Reformat4c46d092018-04-07 15:32:37496 continue;
497 }
498
499 nameIndex += this._decodeVLQ(stringCharIterator);
Tim van der Lippe9b7d21d2019-10-07 18:48:07500 this._mappings.push(new SourceMapEntry(
Blink Reformat4c46d092018-04-07 15:32:37501 lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber, names[nameIndex]));
502 }
503
504 // As per spec, mappings are not necessarily sorted.
Tim van der Lippe9b7d21d2019-10-07 18:48:07505 this._mappings.sort(SourceMapEntry.compare);
Blink Reformat4c46d092018-04-07 15:32:37506 }
507
508 /**
509 * @param {string} char
510 * @return {boolean}
511 */
512 _isSeparator(char) {
513 return char === ',' || char === ';';
514 }
515
516 /**
Tim van der Lippe9b7d21d2019-10-07 18:48:07517 * @param {!TextSourceMap.StringCharIterator} stringCharIterator
Blink Reformat4c46d092018-04-07 15:32:37518 * @return {number}
519 */
520 _decodeVLQ(stringCharIterator) {
521 // Read unsigned value.
522 let result = 0;
523 let shift = 0;
524 let digit;
525 do {
Tim van der Lippe9b7d21d2019-10-07 18:48:07526 digit = TextSourceMap._base64Map[stringCharIterator.next()];
527 result += (digit & TextSourceMap._VLQ_BASE_MASK) << shift;
528 shift += TextSourceMap._VLQ_BASE_SHIFT;
529 } while (digit & TextSourceMap._VLQ_CONTINUATION_MASK);
Blink Reformat4c46d092018-04-07 15:32:37530
531 // Fix the sign.
532 const negative = result & 1;
533 result >>= 1;
534 return negative ? -result : result;
535 }
536
537 /**
538 * @param {string} url
539 * @param {!TextUtils.TextRange} textRange
540 * @return {!TextUtils.TextRange}
541 */
542 reverseMapTextRange(url, textRange) {
543 /**
544 * @param {!{lineNumber: number, columnNumber: number}} position
Tim van der Lippe9b7d21d2019-10-07 18:48:07545 * @param {!SourceMapEntry} mapping
Blink Reformat4c46d092018-04-07 15:32:37546 * @return {number}
547 */
548 function comparator(position, mapping) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34549 if (position.lineNumber !== mapping.sourceLineNumber) {
Blink Reformat4c46d092018-04-07 15:32:37550 return position.lineNumber - mapping.sourceLineNumber;
Tim van der Lippe1d6e57a2019-09-30 11:55:34551 }
Blink Reformat4c46d092018-04-07 15:32:37552
553 return position.columnNumber - mapping.sourceColumnNumber;
554 }
555
556 const mappings = this._reversedMappings(url);
557 const startIndex =
558 mappings.lowerBound({lineNumber: textRange.startLine, columnNumber: textRange.startColumn}, comparator);
559 const endIndex =
560 mappings.upperBound({lineNumber: textRange.endLine, columnNumber: textRange.endColumn}, comparator);
561
562 const startMapping = mappings[startIndex];
563 const endMapping = mappings[endIndex];
564 return new TextUtils.TextRange(
565 startMapping.lineNumber, startMapping.columnNumber, endMapping.lineNumber, endMapping.columnNumber);
566 }
Ingvar Stepanyan1a8762b2019-10-29 18:24:39567
568 /**
569 * @override
570 */
571 dispose() {
572 }
Tim van der Lippe9b7d21d2019-10-07 18:48:07573}
Blink Reformat4c46d092018-04-07 15:32:37574
Tim van der Lippe9b7d21d2019-10-07 18:48:07575TextSourceMap._VLQ_BASE_SHIFT = 5;
576TextSourceMap._VLQ_BASE_MASK = (1 << 5) - 1;
577TextSourceMap._VLQ_CONTINUATION_MASK = 1 << 5;
Blink Reformat4c46d092018-04-07 15:32:37578
579/**
580 * @unrestricted
581 */
Tim van der Lippe9b7d21d2019-10-07 18:48:07582TextSourceMap.StringCharIterator = class {
Blink Reformat4c46d092018-04-07 15:32:37583 /**
584 * @param {string} string
585 */
586 constructor(string) {
587 this._string = string;
588 this._position = 0;
589 }
590
591 /**
592 * @return {string}
593 */
594 next() {
595 return this._string.charAt(this._position++);
596 }
597
598 /**
599 * @return {string}
600 */
601 peek() {
602 return this._string.charAt(this._position);
603 }
604
605 /**
606 * @return {boolean}
607 */
608 hasNext() {
609 return this._position < this._string.length;
610 }
611};
612
613/**
614 * @unrestricted
615 */
Tim van der Lippe9b7d21d2019-10-07 18:48:07616TextSourceMap.SourceInfo = class {
Blink Reformat4c46d092018-04-07 15:32:37617 /**
618 * @param {?string} content
Tim van der Lippe9b7d21d2019-10-07 18:48:07619 * @param {?Array<!SourceMapEntry>} reverseMappings
Blink Reformat4c46d092018-04-07 15:32:37620 */
621 constructor(content, reverseMappings) {
622 this.content = content;
623 this.reverseMappings = reverseMappings;
624 }
625};
626
Tim van der Lippe9b7d21d2019-10-07 18:48:07627TextSourceMap._sourcesListSymbol = Symbol('sourcesList');
628
Ingvar Stepanyan1a8762b2019-10-29 18:24:39629/**
Tim van der Lippe9293af72020-01-17 10:50:37630 * @implements {SourceMap}
Ingvar Stepanyan1a8762b2019-10-29 18:24:39631 * @unrestricted
632 */
633export class WasmSourceMap {
634 /**
635 * Implements SourceMap interface for DWARF information in Wasm.
636 * @param {string} wasmUrl
637 * @param {*} resolver
638 */
639 constructor(wasmUrl, resolver) {
640 this._wasmUrl = wasmUrl;
641 this._resolver = resolver;
642 }
643
644 /**
645 * @private
646 */
647 static async _loadBindings() {
648 const arrayBuffer =
649 await Root.Runtime.loadBinaryResourcePromise('./sdk/wasm_source_map/pkg/wasm_source_map_bg.wasm');
650 await self.wasm_bindgen(arrayBuffer);
651 return self.wasm_bindgen.Resolver;
652 }
653
654 /**
655 * @private
656 */
657 static _loadBindingsOnce() {
658 return WasmSourceMap._asyncResolver = WasmSourceMap._asyncResolver || WasmSourceMap._loadBindings();
659 }
660
661 static async load(script, wasmUrl) {
662 const [Resolver, wasm] = await Promise.all([WasmSourceMap._loadBindingsOnce(), script.getWasmBytecode()]);
663
Tim van der Lippe9293af72020-01-17 10:50:37664 return new WasmSourceMap(wasmUrl, new Resolver(new Uint8Array(wasm)));
Ingvar Stepanyan1a8762b2019-10-29 18:24:39665 }
666
667 /**
668 * @override
669 * @return {string}
670 */
671 compiledURL() {
672 return this._wasmUrl;
673 }
674
675 /**
676 * @override
677 * @return {string}
678 */
679 url() {
680 return WasmSourceMap.FAKE_URL;
681 }
682
683 /**
684 * @override
685 * @return {!Array.<string>}
686 */
687 sourceURLs() {
688 return this._resolver.listFiles();
689 }
690
691 /**
692 * @override
693 * @param {string} sourceURL
694 * @param {!Common.ResourceType} contentType
695 * @return {!Common.ContentProvider}
696 */
697 sourceContentProvider(sourceURL, contentType) {
Tim van der Lippe9293af72020-01-17 10:50:37698 return new CompilerSourceMappingContentProvider(sourceURL, contentType);
Ingvar Stepanyan1a8762b2019-10-29 18:24:39699 }
700
701 /**
702 * @override
703 * @param {string} sourceURL
704 * @return {?string}
705 */
706 embeddedContentByURL(sourceURL) {
707 return null;
708 }
709
710 /**
711 * @override
712 * @param {number} lineNumber in compiled resource
713 * @param {number} columnNumber in compiled resource
Tim van der Lippe9293af72020-01-17 10:50:37714 * @return {?SourceMapEntry}
Ingvar Stepanyan1a8762b2019-10-29 18:24:39715 */
716 findEntry(lineNumber, columnNumber) {
717 if (lineNumber !== 0) {
718 console.warn(new Error(`Invalid non-zero line number.`));
719 }
720 return this._resolver.resolve(columnNumber);
721 }
722
723 /**
724 * @override
725 * @param {string} sourceURL
726 * @param {number} lineNumber
727 * @param {number} columnNumber
728 * @return {?SourceMapEntry}
729 */
730 sourceLineMapping(sourceURL, lineNumber, columnNumber) {
731 return this._resolver.resolveReverse(sourceURL, lineNumber, columnNumber);
732 }
733
734 /**
735 * @override
736 * @return {!Array<!SourceMapEntry>}
737 */
738 mappings() {
739 return this._resolver.listMappings();
740 }
741
742 /**
743 * @override
744 */
745 dispose() {
746 this._resolver.free();
747 }
748}
749
750/* Special URL that should be kept in sync with one in V8 */
751WasmSourceMap.FAKE_URL = 'wasm://dwarf';