Reviewers: lushnikov
CL:
https://codereview.chromium.org/2371133003/Message:
Please take a look
Description:
[Devtools] Lazily build reverse mappings
Reverse mappings are large enough to cause crashes in at least on case.
This code will lazily compute them to save some memory. On my system,
building reverse mapping for a single source URL takes 25 ms for source
map with 500000 entries. Currently this delay is most noticeable when
the file is being opened in an editor.
Note that these lazily constructed reverse mappings are currently never
cleaned up. I'd like to see if any user will be able to hit the problem
before adding more complexity.
BUG=631389
R=lush...@chromium.orgAffected files (+18, -33 lines):
M third_party/WebKit/LayoutTests/http/tests/inspector/compiler-script-mapping.html
M third_party/WebKit/Source/devtools/front_end/bindings/CompilerScriptMapping.js
M third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js
M third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js
Index: third_party/WebKit/LayoutTests/http/tests/inspector/compiler-script-mapping.html
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/compiler-script-mapping.html b/third_party/WebKit/LayoutTests/http/tests/inspector/compiler-script-mapping.html
index 528c6afab6237c784a507e471d1dfd01e07c66a8..c7c3122ad6107928f9177b9b1b4b9e15349e73f3 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/compiler-script-mapping.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/compiler-script-mapping.html
@@ -150,7 +150,7 @@ function test()
}
]};
var mapping = new WebInspector.TextSourceMap("compiled.js", "source-map.json", mappingPayload);
- InspectorTest.assertEquals(2, mapping.sourceURLs().length);
+ InspectorTest.assertEquals(2, Array.from(mapping.sourceURLs()).length);
checkMapping(0, 0, "source1.js", 0, 0, mapping);
checkMapping(0, 1, "source1.js", 2, 1, mapping);
checkMapping(2, 10, "source2.js", 0, 0, mapping);
Index: third_party/WebKit/Source/devtools/front_end/bindings/CompilerScriptMapping.js
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/CompilerScriptMapping.js b/third_party/WebKit/Source/devtools/front_end/bindings/CompilerScriptMapping.js
index ca159e812afcdc40a2598a1637181ff33b461836..63a91bdb4a7b42df492cd6dd80f55b6ebc471f13 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/CompilerScriptMapping.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/CompilerScriptMapping.js
@@ -232,10 +232,8 @@ WebInspector.CompilerScriptMapping.prototype = {
this._scriptForSourceMap.set(sourceMap, script);
// Report sources.
- var sourceURLs = sourceMap.sourceURLs();
var missingSources = [];
- for (var i = 0; i < sourceURLs.length; ++i) {
- var sourceURL = sourceURLs[i];
+ for (const sourceURL of sourceMap.sourceURLs()) {
if (this._sourceMapForURL.get(sourceURL))
continue;
this._sourceMapForURL.set(sourceURL, sourceMap);
@@ -370,9 +368,8 @@ WebInspector.CompilerScriptMapping.prototype = {
var script = this._scriptForSourceMap.get(sourceMap);
if (!script)
return;
- var sourceURLs = sourceMap.sourceURLs();
- for (var i = 0; i < sourceURLs.length; ++i) {
- var uiSourceCode = this._networkMapping.uiSourceCodeForScriptURL(sourceURLs[i], script);
+ for (const sourceURL of sourceMap.sourceURLs()) {
+ var uiSourceCode = this._networkMapping.uiSourceCodeForScriptURL(sourceURL, script);
if (uiSourceCode)
this._unbindUISourceCode(uiSourceCode);
}
Index: third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js
index 0a10c72cb5445a7852105235bdf23cceb0f928ca..40e7bb6e5f29264b80150dac7a6aedd7c1ff9194 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js
@@ -212,7 +212,9 @@ WebInspector.CSSModel.prototype = {
*/
_factoryForSourceMap: function(sourceMap)
{
- var sourceExtensions = new Set(sourceMap.sourceURLs().map(url => WebInspector.ParsedURL.extractExtension(url)));
+ var sourceExtensions = new Set();
+ for (const url of sourceMap.sourceURLs())
+ sourceExtensions.add(WebInspector.ParsedURL.extractExtension(url));
for (var runtimeExtension of self.runtime.extensions(WebInspector.SourceMapFactory)) {
var supportedExtensions = new Set(runtimeExtension.descriptor()["extensions"]);
if (supportedExtensions.containsAll(sourceExtensions))
Index: third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js b/third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js
index 58c6def49e424619adb62bfab9bcaacf1a62423e..5d7209a579b19af44542e42e4e7c5eed547e1377 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js
@@ -96,7 +96,7 @@ WebInspector.SourceMap.prototype = {
url: function() { },
/**
- * @return {!Array<string>}
+ * @return {!Iterable<string>|!Array<string>}
*/
sourceURLs: function() { },
@@ -174,9 +174,8 @@ WebInspector.TextSourceMap = function(compiledURL, sourceMappingURL, payload)
this._compiledURL = compiledURL;
this._sourceMappingURL = sourceMappingURL;
- this._reverseMappingsBySourceURL = new Map();
this._mappings = [];
- this._sources = {};
+ this._sources = new Map();
this._sourceContentByURL = {};
this._parseMappingPayload(payload);
}
@@ -242,11 +241,11 @@ WebInspector.TextSourceMap.prototype = {
/**
* @override
- * @return {!Array.<string>}
+ * @return {!Iterable.<string>}
*/
sourceURLs: function()
{
- return Object.keys(this._sources);
+ return this._sources.keys();
},
/**
@@ -299,10 +298,8 @@ WebInspector.TextSourceMap.prototype = {
*/
_parseSections: function(sections)
{
- for (var i = 0; i < sections.length; ++i) {
- var section = sections[i];
+ for (const section of sections)
this._parseMap(section.map, section.offset.line, section.offset.column);
- }
},
/**
@@ -370,12 +367,12 @@ WebInspector.TextSourceMap.prototype = {
*/
_reversedMappings: function(sourceURL)
{
- var mappings = this._reverseMappingsBySourceURL.get(sourceURL);
- if (!mappings)
+ if (!this._sources.has(sourceURL))
return [];
- if (!mappings._sorted) {
- mappings.sort(sourceMappingComparator);
- mappings._sorted = true;
+ let mappings = this._sources.get(sourceURL);
+ if (mappings === null) {
+ mappings = this._mappings.filter((mapping) => mapping.sourceURL === sourceURL).sort(sourceMappingComparator);
+ this._sources.set(sourceURL, mappings)
}
return mappings;
@@ -422,7 +419,7 @@ WebInspector.TextSourceMap.prototype = {
if (url === this._compiledURL && hasSource)
url += WebInspector.UIString(" [sm]");
sources.push(url);
- this._sources[url] = true;
+ this._sources.set(url, null);
if (hasSource)
this._sourceContentByURL[url] = map.sourcesContent[i];
@@ -466,17 +463,6 @@ WebInspector.TextSourceMap.prototype = {
nameIndex += this._decodeVLQ(stringCharIterator);
this._mappings.push(new WebInspector.SourceMapEntry(lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber, names[nameIndex]));
}
-
- for (var i = 0; i < this._mappings.length; ++i) {
- var mapping = this._mappings[i];
- var url = mapping.sourceURL;
- if (!url)
- continue;
- if (!this._reverseMappingsBySourceURL.has(url))
- this._reverseMappingsBySourceURL.set(url, []);
- var reverseMappings = this._reverseMappingsBySourceURL.get(url);
- reverseMappings.push(mapping);
- }
},
/**