Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 02353a9

Browse files
committed
Bug 849069 - relative source map URLs should be resolved according to the spec's rules; r=past
1 parent 0c7a23a commit 02353a9

14 files changed

Lines changed: 305 additions & 32 deletions

File tree

browser/devtools/debugger/test/binary_search.js

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

browser/devtools/debugger/test/binary_search.map

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
{
22
"version": 3,
33
"file": "binary_search.js",
4+
"sourceRoot": "",
45
"sources": [
5-
"http://example.com/browser/browser/devtools/debugger/test/binary_search.coffee"
6+
"binary_search.coffee"
67
],
78
"names": [],
89
"mappings": ";AACA;CAAA;CAAA,CAAA,CAAuB,EAAA,CAAjB,GAAkB,IAAxB;CAEE,OAAA,UAAA;CAAA,EAAQ,CAAR,CAAA;CAAA,EACQ,CAAR,CAAa,CAAL;CADR,EAEQ,CAAR,CAAA;CAEA,EAA0C,CAAR,CAAtB,MAAN;CAGJ,EAA6B,CAAR,CAAA,CAArB;CAAA,EAAQ,CAAR,CAAQ,GAAR;QAAA;CACA,EAA6B,CAAR,CAAA,CAArB;CAAA,EAAQ,EAAR,GAAA;QADA;CAAA,EAIQ,CAAI,CAAZ,CAAA;CAXF,IAIA;CAUA,GAAA,CAAS;CAAT,YAA8B;MAA9B;AAA0C,CAAD,YAAA;MAhBpB;CAAvB,EAAuB;CAAvB"

toolkit/devtools/debugger/server/dbg-script-actors.js

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,9 @@ ThreadActor.prototype = {
525525
originalLine)
526526
return locationPromise.then((aLocation) => {
527527
let line = aLocation.line;
528-
if (this.dbg.findScripts({ url: aLocation.url }).length == 0 || line < 0) {
528+
if (this.dbg.findScripts({ url: aLocation.url }).length == 0 ||
529+
line < 0 ||
530+
line == null) {
529531
return { error: "noScript" };
530532
}
531533

@@ -2405,7 +2407,7 @@ ThreadSources.prototype = {
24052407
];
24062408
}, (e) => {
24072409
reportError(e);
2408-
delete this._sourceMaps[aScript.sourceMapURL];
2410+
delete this._sourceMaps[this._normalize(aScript.sourceMapURL, aScript.url)];
24092411
delete this._sourceMapsByGeneratedSource[aScript.url];
24102412
return [this.source(aScript.url)];
24112413
})
@@ -2422,7 +2424,9 @@ ThreadSources.prototype = {
24222424
return this._sourceMapsByGeneratedSource[aScript.url];
24232425
}
24242426
dbg_assert(aScript.sourceMapURL);
2425-
let map = this._fetchSourceMap(aScript.sourceMapURL)
2427+
let sourceMapURL = this._normalize(aScript.sourceMapURL,
2428+
aScript.url);
2429+
let map = this._fetchSourceMap(sourceMapURL)
24262430
.then((aSourceMap) => {
24272431
for (let s of aSourceMap.sources) {
24282432
this._generatedUrlsByOriginalUrl[s] = aScript.url;
@@ -2437,14 +2441,21 @@ ThreadSources.prototype = {
24372441
/**
24382442
* Fetch the source map located at the given url.
24392443
*/
2440-
_fetchSourceMap: function TS__featchSourceMap(aSourceMapURL) {
2441-
if (aSourceMapURL in this._sourceMaps) {
2442-
return this._sourceMaps[aSourceMapURL];
2444+
_fetchSourceMap: function TS__fetchSourceMap(aAbsSourceMapURL) {
2445+
if (aAbsSourceMapURL in this._sourceMaps) {
2446+
return this._sourceMaps[aAbsSourceMapURL];
24432447
} else {
2444-
let promise = fetch(aSourceMapURL).then(function (rawSourceMap) {
2445-
return new SourceMapConsumer(rawSourceMap);
2448+
let promise = fetch(aAbsSourceMapURL).then((rawSourceMap) => {
2449+
let map = new SourceMapConsumer(rawSourceMap);
2450+
let base = aAbsSourceMapURL.replace(/\/[^\/]+$/, '/');
2451+
if (base.indexOf("data:") !== 0) {
2452+
map.sourceRoot = map.sourceRoot
2453+
? this._normalize(map.sourceRoot, base)
2454+
: base;
2455+
}
2456+
return map;
24462457
});
2447-
this._sourceMaps[aSourceMapURL] = promise;
2458+
this._sourceMaps[aAbsSourceMapURL] = promise;
24482459
return promise;
24492460
}
24502461
},
@@ -2507,6 +2518,19 @@ ThreadSources.prototype = {
25072518
});
25082519
},
25092520

2521+
/**
2522+
* Normalize multiple relative paths towards the base paths on the right.
2523+
*/
2524+
_normalize: function TS__normalize(...aURLs) {
2525+
dbg_assert(aURLs.length > 1);
2526+
let base = Services.io.newURI(aURLs.pop(), null, null);
2527+
let url;
2528+
while ((url = aURLs.pop())) {
2529+
base = Services.io.newURI(url, null, base);
2530+
}
2531+
return base.spec;
2532+
},
2533+
25102534
iter: function TS_iter() {
25112535
for (let url in this._sourceActors) {
25122536
yield this._sourceActors[url];

toolkit/devtools/debugger/tests/unit/head_dbg.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,14 @@ function finishClient(aClient)
175175
});
176176
}
177177

178+
/**
179+
* Takes a relative file path and returns the absolute file url for it.
180+
*/
181+
function getFileUrl(aName) {
182+
let file = do_get_file(aName);
183+
return Services.io.newFileURI(file).spec;
184+
}
185+
178186
/**
179187
* Returns the full path of the file with the specified name in a
180188
* platform-independent and URL-like form.
@@ -190,3 +198,20 @@ function getFilePath(aName)
190198
}
191199
return path.slice(filePrePath.length);
192200
}
201+
202+
Cu.import("resource://gre/modules/NetUtil.jsm");
203+
204+
/**
205+
* Returns the full text contents of the given file.
206+
*/
207+
function readFile(aFileName) {
208+
let f = do_get_file(aFileName);
209+
let s = Cc["@mozilla.org/network/file-input-stream;1"]
210+
.createInstance(Ci.nsIFileInputStream);
211+
s.init(f, -1, -1, false);
212+
try {
213+
return NetUtil.readInputStreamToString(s, s.available());
214+
} finally {
215+
s.close();
216+
}
217+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
foo = (n) ->
2+
return "foo" + i for i in [0...n]
3+
4+
[first, second, third] = foo(3)
5+
6+
debugger
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"version": 3,
3+
"file": "sourcemapped.js",
4+
"sourceRoot": "",
5+
"sources": [
6+
"sourcemapped.coffee"
7+
],
8+
"names": [],
9+
"mappings": ";AAAA;CAAA,KAAA,yBAAA;CAAA;CAAA,CAAA,CAAA,MAAO;CACL,IAAA,GAAA;AAAA,CAAA,EAAA,MAA0B,qDAA1B;CAAA,EAAe,EAAR,QAAA;CAAP,IADI;CAAN,EAAM;;CAAN,CAGA,CAAyB,IAAA;;CAEzB,UALA;CAAA"
10+
}

toolkit/devtools/debugger/tests/unit/sourcemapped.js

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

toolkit/devtools/debugger/tests/unit/test_source-01.js

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ var gThreadClient;
1010
// and that they can communicate over the protocol to fetch the source text for
1111
// a given script.
1212

13-
Cu.import("resource://gre/modules/NetUtil.jsm");
14-
1513
function run_test()
1614
{
1715
initTestDebuggerServer();
@@ -60,15 +58,9 @@ function test_source()
6058
do_check_true(!aResponse.error);
6159
do_check_true(!!aResponse.source);
6260

63-
let f = do_get_file("test_source-01.js", false);
64-
let s = Cc["@mozilla.org/network/file-input-stream;1"]
65-
.createInstance(Ci.nsIFileInputStream);
66-
s.init(f, -1, -1, false);
67-
68-
do_check_eq(NetUtil.readInputStreamToString(s, s.available()),
61+
do_check_eq(readFile("test_source-01.js"),
6962
aResponse.source);
7063

71-
s.close();
7264
gThreadClient.resume(function () {
7365
finishClient(gClient);
7466
});
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* Any copyright is dedicated to the Public Domain.
2+
http://creativecommons.org/publicdomain/zero/1.0/ */
3+
4+
/**
5+
* Check that absolute source map urls work.
6+
*/
7+
8+
var gDebuggee;
9+
var gClient;
10+
var gThreadClient;
11+
12+
Components.utils.import('resource:///modules/devtools/SourceMap.jsm');
13+
14+
function run_test()
15+
{
16+
initTestDebuggerServer();
17+
gDebuggee = addTestGlobal("test-source-map");
18+
gClient = new DebuggerClient(DebuggerServer.connectPipe());
19+
gClient.connect(function() {
20+
attachTestGlobalClientAndResume(gClient, "test-source-map", function(aResponse, aThreadClient) {
21+
gThreadClient = aThreadClient;
22+
test_absolute_source_map();
23+
});
24+
});
25+
do_test_pending();
26+
}
27+
28+
function test_absolute_source_map()
29+
{
30+
gClient.addOneTimeListener("newSource", function _onNewSource(aEvent, aPacket) {
31+
do_check_eq(aEvent, "newSource");
32+
do_check_eq(aPacket.type, "newSource");
33+
do_check_true(!!aPacket.source);
34+
35+
do_check_true(aPacket.source.url.indexOf("sourcemapped.coffee") !== -1,
36+
"The new source should be a coffee file.");
37+
do_check_eq(aPacket.source.url.indexOf("sourcemapped.js"), -1,
38+
"The new source should not be a js file.");
39+
40+
finishClient(gClient);
41+
});
42+
43+
code = readFile("sourcemapped.js")
44+
+ "\n//@ sourceMappingURL=" + getFileUrl("source-map-data/sourcemapped.map");
45+
46+
Components.utils.evalInSandbox(code, gDebuggee, "1.8",
47+
getFileUrl("sourcemapped.js"), 1);
48+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* Any copyright is dedicated to the Public Domain.
2+
http://creativecommons.org/publicdomain/zero/1.0/ */
3+
4+
/**
5+
* Check that relative source map urls work.
6+
*/
7+
8+
var gDebuggee;
9+
var gClient;
10+
var gThreadClient;
11+
12+
Components.utils.import('resource:///modules/devtools/SourceMap.jsm');
13+
14+
function run_test()
15+
{
16+
initTestDebuggerServer();
17+
gDebuggee = addTestGlobal("test-source-map");
18+
gClient = new DebuggerClient(DebuggerServer.connectPipe());
19+
gClient.connect(function() {
20+
attachTestGlobalClientAndResume(gClient, "test-source-map", function(aResponse, aThreadClient) {
21+
gThreadClient = aThreadClient;
22+
test_relative_source_map();
23+
});
24+
});
25+
do_test_pending();
26+
}
27+
28+
function test_relative_source_map()
29+
{
30+
gClient.addOneTimeListener("newSource", function _onNewSource(aEvent, aPacket) {
31+
do_check_eq(aEvent, "newSource");
32+
do_check_eq(aPacket.type, "newSource");
33+
do_check_true(!!aPacket.source);
34+
35+
do_check_true(aPacket.source.url.indexOf("sourcemapped.coffee") !== -1,
36+
"The new source should be a coffee file.");
37+
do_check_eq(aPacket.source.url.indexOf("sourcemapped.js"), -1,
38+
"The new source should not be a js file.");
39+
40+
finishClient(gClient);
41+
});
42+
43+
code = readFile("sourcemapped.js")
44+
+ "\n//@ sourceMappingURL=source-map-data/sourcemapped.map";
45+
46+
Components.utils.evalInSandbox(code, gDebuggee, "1.8",
47+
getFileUrl("sourcemapped.js"), 1);
48+
}

0 commit comments

Comments
 (0)