Skip to content

Commit 85d2fc6

Browse files
committed
Normalize consumer URLs to be as absolute as possible to avoid usage of 'util.relative'.
1 parent 76be1e6 commit 85d2fc6

File tree

2 files changed

+20
-71
lines changed

2 files changed

+20
-71
lines changed

lib/source-map-consumer.js

Lines changed: 16 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,11 @@ class BasicSourceMapConsumer extends SourceMapConsumer {
179179
}
180180

181181
const version = util.getArg(sourceMap, "version");
182-
let sources = util.getArg(sourceMap, "sources");
182+
const sources = util.getArg(sourceMap, "sources").map(String);
183183
// Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which
184184
// requires the array) to play nice here.
185185
const names = util.getArg(sourceMap, "names", []);
186-
let sourceRoot = util.getArg(sourceMap, "sourceRoot", null);
186+
const sourceRoot = util.getArg(sourceMap, "sourceRoot", null);
187187
const sourcesContent = util.getArg(sourceMap, "sourcesContent", null);
188188
const mappings = util.getArg(sourceMap, "mappings");
189189
const file = util.getArg(sourceMap, "file", null);
@@ -194,36 +194,16 @@ class BasicSourceMapConsumer extends SourceMapConsumer {
194194
throw new Error("Unsupported version: " + version);
195195
}
196196

197-
if (sourceRoot) {
198-
sourceRoot = util.normalize(sourceRoot);
199-
}
200-
201-
sources = sources
202-
.map(String)
203-
// Some source maps produce relative source paths like "./foo.js" instead of
204-
// "foo.js". Normalize these first so that future comparisons will succeed.
205-
// See bugzil.la/1090768.
206-
.map(util.normalize)
207-
// Always ensure that absolute sources are internally stored relative to
208-
// the source root, if the source root is absolute. Not doing this would
209-
// be particularly problematic when the source root is a prefix of the
210-
// source (valid, but why??). See github issue #199 and bugzil.la/1188982.
211-
.map(function(source) {
212-
return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source)
213-
? util.relative(sourceRoot, source)
214-
: source;
215-
});
216-
217197
// Pass `true` below to allow duplicate names and sources. While source maps
218198
// are intended to be compressed and deduplicated, the TypeScript compiler
219199
// sometimes generates source maps with duplicates in them. See Github issue
220200
// #72 and bugzil.la/889492.
221201
that._names = ArraySet.fromArray(names.map(String), true);
222202
that._sources = ArraySet.fromArray(sources, true);
223203

224-
that._absoluteSources = that._sources.toArray().map(function(s) {
204+
that._absoluteSources = ArraySet.fromArray(that._sources.toArray().map(function(s) {
225205
return util.computeSourceURL(sourceRoot, s, aSourceMapURL);
226-
});
206+
}), true);
227207

228208
that.sourceRoot = sourceRoot;
229209
that.sourcesContent = sourcesContent;
@@ -247,21 +227,16 @@ class BasicSourceMapConsumer extends SourceMapConsumer {
247227
* found.
248228
*/
249229
_findSourceIndex(aSource) {
250-
let relativeSource = aSource;
251-
if (this.sourceRoot != null) {
252-
relativeSource = util.relative(this.sourceRoot, relativeSource);
230+
// Treat the source as map-relative overall by default.
231+
const sourceAsMapRelative = util.computeSourceURL(null, aSource, this._sourceMapURL);
232+
if (this._absoluteSources.has(sourceAsMapRelative)) {
233+
return this._absoluteSources.indexOf(sourceAsMapRelative);
253234
}
254235

255-
if (this._sources.has(relativeSource)) {
256-
return this._sources.indexOf(relativeSource);
257-
}
258-
259-
// Maybe aSource is an absolute URL as returned by |sources|. In
260-
// this case we can't simply undo the transform.
261-
for (let i = 0; i < this._absoluteSources.length; ++i) {
262-
if (this._absoluteSources[i] == aSource) {
263-
return i;
264-
}
236+
// Fall back to treating the source as sourceRoot-relative.
237+
const sourceAsSourceRootRelative = util.computeSourceURL(this.sourceRoot, aSource, this._sourceMapURL);
238+
if (this._absoluteSources.has(sourceAsSourceRootRelative)) {
239+
return this._absoluteSources.indexOf(sourceAsSourceRootRelative);
265240
}
266241

267242
return -1;
@@ -281,7 +256,7 @@ class BasicSourceMapConsumer extends SourceMapConsumer {
281256
}
282257

283258
get sources() {
284-
return this._absoluteSources.slice();
259+
return this._absoluteSources.toArray();
285260
}
286261

287262
_getMappingsPtr() {
@@ -341,13 +316,11 @@ class BasicSourceMapConsumer extends SourceMapConsumer {
341316
eachMapping(aCallback, aContext, aOrder) {
342317
const context = aContext || null;
343318
const order = aOrder || SourceMapConsumer.GENERATED_ORDER;
344-
const sourceRoot = this.sourceRoot;
345319

346320
this._wasm.withMappingCallback(
347321
mapping => {
348322
if (mapping.source !== null) {
349-
mapping.source = this._sources.at(mapping.source);
350-
mapping.source = util.computeSourceURL(sourceRoot, mapping.source, this._sourceMapURL);
323+
mapping.source = this._absoluteSources.at(mapping.source);
351324

352325
if (mapping.name !== null) {
353326
mapping.name = this._names.at(mapping.name);
@@ -496,8 +469,7 @@ class BasicSourceMapConsumer extends SourceMapConsumer {
496469
if (mapping.generatedLine === needle.generatedLine) {
497470
let source = util.getArg(mapping, "source", null);
498471
if (source !== null) {
499-
source = this._sources.at(source);
500-
source = util.computeSourceURL(this.sourceRoot, source, this._sourceMapURL);
472+
source = this._absoluteSources.at(source);
501473
}
502474

503475
let name = util.getArg(mapping, "name", null);
@@ -549,30 +521,6 @@ class BasicSourceMapConsumer extends SourceMapConsumer {
549521
return this.sourcesContent[index];
550522
}
551523

552-
let relativeSource = aSource;
553-
if (this.sourceRoot != null) {
554-
relativeSource = util.relative(this.sourceRoot, relativeSource);
555-
}
556-
557-
let url;
558-
if (this.sourceRoot != null
559-
&& (url = util.urlParse(this.sourceRoot))) {
560-
// XXX: file:// URIs and absolute paths lead to unexpected behavior for
561-
// many users. We can help them out when they expect file:// URIs to
562-
// behave like it would if they were running a local HTTP server. See
563-
// https://bugzilla.mozilla.org/show_bug.cgi?id=885597.
564-
const fileUriAbsPath = relativeSource.replace(/^file:\/\//, "");
565-
if (url.scheme == "file"
566-
&& this._sources.has(fileUriAbsPath)) {
567-
return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)];
568-
}
569-
570-
if ((!url.path || url.path == "/")
571-
&& this._sources.has("/" + relativeSource)) {
572-
return this.sourcesContent[this._sources.indexOf("/" + relativeSource)];
573-
}
574-
}
575-
576524
// This function is used recursively from
577525
// IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we
578526
// don't want to throw if we can't find the source - we just want to
@@ -581,7 +529,7 @@ class BasicSourceMapConsumer extends SourceMapConsumer {
581529
return null;
582530
}
583531

584-
throw new Error('"' + relativeSource + '" is not in the SourceMap.');
532+
throw new Error('"' + aSource + '" is not in the SourceMap.');
585533
}
586534

587535
/**

test/test-source-map-consumer.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,9 +1424,10 @@ exports["test non-normalized sourceRoot (from issue #227)"] = async function(ass
14241424
sourceRoot: "./src/",
14251425
sourcesContent: [ 'var name = "Mark"\n' ]
14261426
});
1427-
assert.equal(consumer.sourceRoot, "src/", "sourceRoot was normalized");
1428-
// Before the fix, this threw an exception.
1429-
consumer.sourceContentFor(consumer.sources[0]);
1427+
assert.doesNotThrow(() => {
1428+
// Before the fix, this threw an exception.
1429+
consumer.sourceContentFor(consumer.sources[0]);
1430+
});
14301431

14311432
consumer.destroy();
14321433
};

0 commit comments

Comments
 (0)