From 65e06ae25f51607622dae121f7032f7c2b613bd4 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Sun, 6 Oct 2013 11:45:07 -0700 Subject: [PATCH] Bug 916454 - Delay parsing source maps until queried for a location; r=past --- toolkit/devtools/sourcemap/SourceMap.jsm | 98 ++++++++++++++++-------- 1 file changed, 65 insertions(+), 33 deletions(-) diff --git a/toolkit/devtools/sourcemap/SourceMap.jsm b/toolkit/devtools/sourcemap/SourceMap.jsm index eefdd4dc24b9..c28d2585cf2d 100644 --- a/toolkit/devtools/sourcemap/SourceMap.jsm +++ b/toolkit/devtools/sourcemap/SourceMap.jsm @@ -85,36 +85,11 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou // #72 and bugzil.la/889492. this._names = ArraySet.fromArray(names, true); this._sources = ArraySet.fromArray(sources, true); + this.sourceRoot = sourceRoot; this.sourcesContent = sourcesContent; + this._mappings = mappings; this.file = file; - - // `this._generatedMappings` and `this._originalMappings` hold the parsed - // mapping coordinates from the source map's "mappings" attribute. Each - // object in the array is of the form - // - // { - // generatedLine: The line number in the generated code, - // generatedColumn: The column number in the generated code, - // source: The path to the original source file that generated this - // chunk of code, - // originalLine: The line number in the original source that - // corresponds to this chunk of generated code, - // originalColumn: The column number in the original source that - // corresponds to this chunk of generated code, - // name: The name of the original symbol which generated this chunk of - // code. - // } - // - // All properties except for `generatedLine` and `generatedColumn` can be - // `null`. - // - // `this._generatedMappings` is ordered by the generated positions. - // - // `this._originalMappings` is ordered by the original positions. - this._generatedMappings = []; - this._originalMappings = []; - this._parseMappings(mappings, sourceRoot); } /** @@ -135,9 +110,9 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou smc.sourceRoot); smc.file = aSourceMap._file; - smc._generatedMappings = aSourceMap._mappings.slice() + smc.__generatedMappings = aSourceMap._mappings.slice() .sort(util.compareByGeneratedPositions); - smc._originalMappings = aSourceMap._mappings.slice() + smc.__originalMappings = aSourceMap._mappings.slice() .sort(util.compareByOriginalPositions); return smc; @@ -159,9 +134,66 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou } }); + // `__generatedMappings` and `__originalMappings` are arrays that hold the + // parsed mapping coordinates from the source map's "mappings" attribute. They + // are lazily instantiated, accessed via the `_generatedMappings` and + // `_originalMappings` getters respectively, and we only parse the mappings + // and create these arrays once queried for a source location. We jump through + // these hoops because there can be many thousands of mappings, and parsing + // them is expensive, so we only want to do it if we must. + // + // Each object in the arrays is of the form: + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `_generatedMappings` is ordered by the generated positions. + // + // `_originalMappings` is ordered by the original positions. + + SourceMapConsumer.prototype.__generatedMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } + }); + + SourceMapConsumer.prototype.__originalMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } + }); + /** * Parse the mappings in a string in to a data structure which we can easily - * query (an ordered list in this._generatedMappings). + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). */ SourceMapConsumer.prototype._parseMappings = function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { @@ -231,14 +263,14 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou } } - this._generatedMappings.push(mapping); + this.__generatedMappings.push(mapping); if (typeof mapping.originalLine === 'number') { - this._originalMappings.push(mapping); + this.__originalMappings.push(mapping); } } } - this._originalMappings.sort(util.compareByOriginalPositions); + this.__originalMappings.sort(util.compareByOriginalPositions); }; /**