Skip to content

Commit 75131c7

Browse files
authored
Merge pull request mozilla#286 from tromey/fix-source-root-prepending
Change sourceRoot resolution to match the spec
2 parents 20ab726 + 54825b8 commit 75131c7

16 files changed

+1118
-266
lines changed

dist/source-map.debug.js

Lines changed: 97 additions & 27 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/source-map.js

Lines changed: 96 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,59 @@ return /******/ (function(modules) { // webpackBootstrap
11541154
}
11551155
exports.parseSourceMapInput = parseSourceMapInput;
11561156

1157+
/**
1158+
* Compute the URL of a source given the the source root, the source's
1159+
* URL, and the source map's URL.
1160+
*/
1161+
function computeSourceURL(sourceRoot, sourceURL, sourceMapURL) {
1162+
sourceURL = sourceURL || '';
1163+
1164+
if (sourceRoot) {
1165+
// This follows what Chrome does.
1166+
if (sourceRoot[sourceRoot.length - 1] !== '/' && sourceURL[0] !== '/') {
1167+
sourceRoot += '/';
1168+
}
1169+
// The spec says:
1170+
// Line 4: An optional source root, useful for relocating source
1171+
// files on a server or removing repeated values in the
1172+
// “sources” entry. This value is prepended to the individual
1173+
// entries in the “source” field.
1174+
sourceURL = sourceRoot + sourceURL;
1175+
}
1176+
1177+
// Historically, SourceMapConsumer did not take the sourceMapURL as
1178+
// a parameter. This mode is still somewhat supported, which is why
1179+
// this code block is conditional. However, it's preferable to pass
1180+
// the source map URL to SourceMapConsumer, so that this function
1181+
// can implement the source URL resolution algorithm as outlined in
1182+
// the spec. This block is basically the equivalent of:
1183+
// new URL(sourceURL, sourceMapURL).toString()
1184+
// ... except it avoids using URL, which wasn't available in the
1185+
// older releases of node still supported by this library.
1186+
//
1187+
// The spec says:
1188+
// If the sources are not absolute URLs after prepending of the
1189+
// “sourceRoot”, the sources are resolved relative to the
1190+
// SourceMap (like resolving script src in a html document).
1191+
if (sourceMapURL) {
1192+
var parsed = urlParse(sourceMapURL);
1193+
if (!parsed) {
1194+
throw new Error("sourceMapURL could not be parsed");
1195+
}
1196+
if (parsed.path) {
1197+
// Strip the last path component, but keep the "/".
1198+
var index = parsed.path.lastIndexOf('/');
1199+
if (index >= 0) {
1200+
parsed.path = parsed.path.substring(0, index + 1);
1201+
}
1202+
}
1203+
sourceURL = join(urlGenerate(parsed), sourceURL);
1204+
}
1205+
1206+
return normalize(sourceURL);
1207+
}
1208+
exports.computeSourceURL = computeSourceURL;
1209+
11571210

11581211
/***/ }),
11591212
/* 5 */
@@ -1384,15 +1437,15 @@ return /******/ (function(modules) { // webpackBootstrap
13841437
var base64VLQ = __webpack_require__(2);
13851438
var quickSort = __webpack_require__(9).quickSort;
13861439

1387-
function SourceMapConsumer(aSourceMap) {
1440+
function SourceMapConsumer(aSourceMap, aSourceMapURL) {
13881441
var sourceMap = aSourceMap;
13891442
if (typeof aSourceMap === 'string') {
13901443
sourceMap = util.parseSourceMapInput(aSourceMap);
13911444
}
13921445

13931446
return sourceMap.sections != null
1394-
? new IndexedSourceMapConsumer(sourceMap)
1395-
: new BasicSourceMapConsumer(sourceMap);
1447+
? new IndexedSourceMapConsumer(sourceMap, aSourceMapURL)
1448+
: new BasicSourceMapConsumer(sourceMap, aSourceMapURL);
13961449
}
13971450

13981451
SourceMapConsumer.fromSourceMap = function(aSourceMap) {
@@ -1518,9 +1571,7 @@ return /******/ (function(modules) { // webpackBootstrap
15181571
var sourceRoot = this.sourceRoot;
15191572
mappings.map(function (mapping) {
15201573
var source = mapping.source === null ? null : this._sources.at(mapping.source);
1521-
if (source != null && sourceRoot != null) {
1522-
source = util.join(sourceRoot, source);
1523-
}
1574+
source = util.computeSourceURL(sourceRoot, source, this._sourceMapURL);
15241575
return {
15251576
source: source,
15261577
generatedLine: mapping.generatedLine,
@@ -1634,7 +1685,7 @@ return /******/ (function(modules) { // webpackBootstrap
16341685
* query for information about the original file positions by giving it a file
16351686
* position in the generated source.
16361687
*
1637-
* The only parameter is the raw source map (either as a JSON string, or
1688+
* The first parameter is the raw source map (either as a JSON string, or
16381689
* already parsed to an object). According to the spec, source maps have the
16391690
* following attributes:
16401691
*
@@ -1657,9 +1708,13 @@ return /******/ (function(modules) { // webpackBootstrap
16571708
* mappings: "AA,AB;;ABCDE;"
16581709
* }
16591710
*
1711+
* The second parameter, if given, is a string whose value is the URL
1712+
* at which the source map was found. This URL is used to compute the
1713+
* sources array.
1714+
*
16601715
* [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#
16611716
*/
1662-
function BasicSourceMapConsumer(aSourceMap) {
1717+
function BasicSourceMapConsumer(aSourceMap, aSourceMapURL) {
16631718
var sourceMap = aSourceMap;
16641719
if (typeof aSourceMap === 'string') {
16651720
sourceMap = util.parseSourceMapInput(aSourceMap);
@@ -1711,6 +1766,7 @@ return /******/ (function(modules) { // webpackBootstrap
17111766
this.sourceRoot = sourceRoot;
17121767
this.sourcesContent = sourcesContent;
17131768
this._mappings = mappings;
1769+
this._sourceMapURL = aSourceMapURL;
17141770
this.file = file;
17151771
}
17161772

@@ -1722,10 +1778,12 @@ return /******/ (function(modules) { // webpackBootstrap
17221778
*
17231779
* @param SourceMapGenerator aSourceMap
17241780
* The source map that will be consumed.
1781+
* @param String aSourceMapURL
1782+
* The URL at which the source map can be found (optional)
17251783
* @returns BasicSourceMapConsumer
17261784
*/
17271785
BasicSourceMapConsumer.fromSourceMap =
1728-
function SourceMapConsumer_fromSourceMap(aSourceMap) {
1786+
function SourceMapConsumer_fromSourceMap(aSourceMap, aSourceMapURL) {
17291787
var smc = Object.create(BasicSourceMapConsumer.prototype);
17301788

17311789
var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);
@@ -1734,6 +1792,7 @@ return /******/ (function(modules) { // webpackBootstrap
17341792
smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(),
17351793
smc.sourceRoot);
17361794
smc.file = aSourceMap._file;
1795+
smc._sourceMapURL = aSourceMapURL;
17371796

17381797
// Because we are modifying the entries (by converting string sources and
17391798
// names to indices into the sources and names ArraySets), we have to make
@@ -1781,7 +1840,7 @@ return /******/ (function(modules) { // webpackBootstrap
17811840
Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', {
17821841
get: function () {
17831842
return this._sources.toArray().map(function (s) {
1784-
return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s;
1843+
return util.computeSourceURL(this.sourceRoot, s, this._sourceMapURL);
17851844
}, this);
17861845
}
17871846
});
@@ -2005,9 +2064,7 @@ return /******/ (function(modules) { // webpackBootstrap
20052064
var source = util.getArg(mapping, 'source', null);
20062065
if (source !== null) {
20072066
source = this._sources.at(source);
2008-
if (this.sourceRoot != null) {
2009-
source = util.join(this.sourceRoot, source);
2010-
}
2067+
source = util.computeSourceURL(this.sourceRoot, source, this._sourceMapURL);
20112068
}
20122069
var name = util.getArg(mapping, 'name', null);
20132070
if (name !== null) {
@@ -2054,12 +2111,23 @@ return /******/ (function(modules) { // webpackBootstrap
20542111
return null;
20552112
}
20562113

2114+
var relativeSource = aSource;
20572115
if (this.sourceRoot != null) {
2058-
aSource = util.relative(this.sourceRoot, aSource);
2116+
relativeSource = util.relative(this.sourceRoot, relativeSource);
2117+
}
2118+
2119+
if (this._sources.has(relativeSource)) {
2120+
return this.sourcesContent[this._sources.indexOf(relativeSource)];
20592121
}
20602122

2061-
if (this._sources.has(aSource)) {
2062-
return this.sourcesContent[this._sources.indexOf(aSource)];
2123+
// Maybe aSource is an absolute URL as returned by |sources|. In
2124+
// this case we can't simply undo the transform.
2125+
var sourceArray = this.sources;
2126+
var i;
2127+
for (i = 0; i < sourceArray.length; ++i) {
2128+
if (sourceArray[i] == aSource) {
2129+
return this.sourcesContent[i];
2130+
}
20632131
}
20642132

20652133
var url;
@@ -2069,15 +2137,15 @@ return /******/ (function(modules) { // webpackBootstrap
20692137
// many users. We can help them out when they expect file:// URIs to
20702138
// behave like it would if they were running a local HTTP server. See
20712139
// https://bugzilla.mozilla.org/show_bug.cgi?id=885597.
2072-
var fileUriAbsPath = aSource.replace(/^file:\/\//, "");
2140+
var fileUriAbsPath = relativeSource.replace(/^file:\/\//, "");
20732141
if (url.scheme == "file"
20742142
&& this._sources.has(fileUriAbsPath)) {
20752143
return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]
20762144
}
20772145

20782146
if ((!url.path || url.path == "/")
2079-
&& this._sources.has("/" + aSource)) {
2080-
return this.sourcesContent[this._sources.indexOf("/" + aSource)];
2147+
&& this._sources.has("/" + relativeSource)) {
2148+
return this.sourcesContent[this._sources.indexOf("/" + relativeSource)];
20812149
}
20822150
}
20832151

@@ -2089,7 +2157,7 @@ return /******/ (function(modules) { // webpackBootstrap
20892157
return null;
20902158
}
20912159
else {
2092-
throw new Error('"' + aSource + '" is not in the SourceMap.');
2160+
throw new Error('"' + relativeSource + '" is not in the SourceMap.');
20932161
}
20942162
};
20952163

@@ -2173,7 +2241,7 @@ return /******/ (function(modules) { // webpackBootstrap
21732241
* that it takes "indexed" source maps (i.e. ones with a "sections" field) as
21742242
* input.
21752243
*
2176-
* The only parameter is a raw source map (either as a JSON string, or already
2244+
* The first parameter is a raw source map (either as a JSON string, or already
21772245
* parsed to an object). According to the spec for indexed source maps, they
21782246
* have the following attributes:
21792247
*
@@ -2210,9 +2278,13 @@ return /******/ (function(modules) { // webpackBootstrap
22102278
* }],
22112279
* }
22122280
*
2281+
* The second parameter, if given, is a string whose value is the URL
2282+
* at which the source map was found. This URL is used to compute the
2283+
* sources array.
2284+
*
22132285
* [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt
22142286
*/
2215-
function IndexedSourceMapConsumer(aSourceMap) {
2287+
function IndexedSourceMapConsumer(aSourceMap, aSourceMapURL) {
22162288
var sourceMap = aSourceMap;
22172289
if (typeof aSourceMap === 'string') {
22182290
sourceMap = util.parseSourceMapInput(aSourceMap);
@@ -2255,7 +2327,7 @@ return /******/ (function(modules) { // webpackBootstrap
22552327
generatedLine: offsetLine + 1,
22562328
generatedColumn: offsetColumn + 1
22572329
},
2258-
consumer: new SourceMapConsumer(util.getArg(s, 'map'))
2330+
consumer: new SourceMapConsumer(util.getArg(s, 'map'), aSourceMapURL)
22592331
}
22602332
});
22612333
}
@@ -2441,9 +2513,7 @@ return /******/ (function(modules) { // webpackBootstrap
24412513
var mapping = sectionMappings[j];
24422514

24432515
var source = section.consumer._sources.at(mapping.source);
2444-
if (section.consumer.sourceRoot !== null) {
2445-
source = util.join(section.consumer.sourceRoot, source);
2446-
}
2516+
source = util.computeSourceURL(section.consumer.sourceRoot, source, this._sourceMapURL);
24472517
this._sources.add(source);
24482518
source = this._sources.indexOf(source);
24492519

dist/source-map.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/source-map.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)