зеркало из https://github.com/mozilla/gecko-dev.git
Backout eb887b962dfa (bug 772119) on suspicion of leaks
This commit is contained in:
Родитель
116a5ab638
Коммит
2c8dec2f1f
|
@ -1060,7 +1060,6 @@ pref("devtools.debugger.remote-host", "localhost");
|
||||||
pref("devtools.debugger.remote-autoconnect", false);
|
pref("devtools.debugger.remote-autoconnect", false);
|
||||||
pref("devtools.debugger.remote-connection-retries", 3);
|
pref("devtools.debugger.remote-connection-retries", 3);
|
||||||
pref("devtools.debugger.remote-timeout", 20000);
|
pref("devtools.debugger.remote-timeout", 20000);
|
||||||
pref("devtools.debugger.source-maps-enabled", false);
|
|
||||||
|
|
||||||
// The default Debugger UI settings
|
// The default Debugger UI settings
|
||||||
pref("devtools.debugger.ui.win-x", 0);
|
pref("devtools.debugger.ui.win-x", 0);
|
||||||
|
|
|
@ -261,8 +261,6 @@ let DebuggerController = {
|
||||||
if (aCallback) {
|
if (aCallback) {
|
||||||
aCallback();
|
aCallback();
|
||||||
}
|
}
|
||||||
}, {
|
|
||||||
useSourceMaps: Services.prefs.getBoolPref("devtools.debugger.source-maps-enabled")
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1114,7 +1112,7 @@ SourceScripts.prototype = {
|
||||||
*/
|
*/
|
||||||
_onSourcesAdded: function SS__onSourcesAdded(aResponse) {
|
_onSourcesAdded: function SS__onSourcesAdded(aResponse) {
|
||||||
if (aResponse.error) {
|
if (aResponse.error) {
|
||||||
Cu.reportError(new Error("Error getting sources: " + aResponse.message));
|
Cu.reportError("Error getting sources: " + aResponse.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,6 @@ MOCHITEST_BROWSER_TESTS = \
|
||||||
browser_dbg_bfcache.js \
|
browser_dbg_bfcache.js \
|
||||||
browser_dbg_progress-listener-bug.js \
|
browser_dbg_progress-listener-bug.js \
|
||||||
browser_dbg_chrome-debugging.js \
|
browser_dbg_chrome-debugging.js \
|
||||||
browser_dbg_source_maps-01.js \
|
|
||||||
head.js \
|
head.js \
|
||||||
helpers.js \
|
helpers.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
@ -128,10 +127,6 @@ MOCHITEST_BROWSER_PAGES = \
|
||||||
test-function-search-01.js \
|
test-function-search-01.js \
|
||||||
test-function-search-02.js \
|
test-function-search-02.js \
|
||||||
test-function-search-03.js \
|
test-function-search-03.js \
|
||||||
binary_search.html \
|
|
||||||
binary_search.coffee \
|
|
||||||
binary_search.js \
|
|
||||||
binary_search.map \
|
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
MOCHITEST_BROWSER_FILES_PARTS = MOCHITEST_BROWSER_TESTS MOCHITEST_BROWSER_PAGES
|
MOCHITEST_BROWSER_FILES_PARTS = MOCHITEST_BROWSER_TESTS MOCHITEST_BROWSER_PAGES
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
# Uses a binary search algorithm to locate a value in the specified array.
|
|
||||||
window.binary_search = (items, value) ->
|
|
||||||
|
|
||||||
start = 0
|
|
||||||
stop = items.length - 1
|
|
||||||
pivot = Math.floor (start + stop) / 2
|
|
||||||
|
|
||||||
while items[pivot] isnt value and start < stop
|
|
||||||
|
|
||||||
# Adjust the search area.
|
|
||||||
stop = pivot - 1 if value < items[pivot]
|
|
||||||
start = pivot + 1 if value > items[pivot]
|
|
||||||
|
|
||||||
# Recalculate the pivot.
|
|
||||||
pivot = Math.floor (stop + start) / 2
|
|
||||||
|
|
||||||
# Make sure we've found the correct value.
|
|
||||||
if items[pivot] is value then pivot else -1
|
|
|
@ -1,12 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset='utf-8'/>
|
|
||||||
<title>Browser Debugger Source Map Test</title>
|
|
||||||
<!-- Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
|
||||||
<script type="text/javascript" src="binary_search.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,30 +0,0 @@
|
||||||
// Generated by CoffeeScript 1.6.1
|
|
||||||
(function() {
|
|
||||||
|
|
||||||
window.binary_search = function(items, value) {
|
|
||||||
var pivot, start, stop;
|
|
||||||
start = 0;
|
|
||||||
stop = items.length - 1;
|
|
||||||
pivot = Math.floor((start + stop) / 2);
|
|
||||||
while (items[pivot] !== value && start < stop) {
|
|
||||||
if (value < items[pivot]) {
|
|
||||||
stop = pivot - 1;
|
|
||||||
}
|
|
||||||
if (value > items[pivot]) {
|
|
||||||
start = pivot + 1;
|
|
||||||
}
|
|
||||||
pivot = Math.floor((stop + start) / 2);
|
|
||||||
}
|
|
||||||
if (items[pivot] === value) {
|
|
||||||
return pivot;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}).call(this);
|
|
||||||
|
|
||||||
// TODO bug 849069: this should just be "binary_search.map", not a full path.
|
|
||||||
/*
|
|
||||||
//@ sourceMappingURL=http://example.com/browser/browser/devtools/debugger/test/binary_search.map
|
|
||||||
*/
|
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"file": "binary_search.js",
|
|
||||||
"sources": [
|
|
||||||
"http://example.com/browser/browser/devtools/debugger/test/binary_search.coffee"
|
|
||||||
],
|
|
||||||
"names": [],
|
|
||||||
"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"
|
|
||||||
}
|
|
|
@ -27,22 +27,19 @@ function test()
|
||||||
gDebugger = gPane.panelWin;
|
gDebugger = gPane.panelWin;
|
||||||
resumed = true;
|
resumed = true;
|
||||||
|
|
||||||
gDebugger.addEventListener("Debugger:SourceShown", onSourceShown);
|
gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
|
||||||
|
|
||||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded",
|
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||||
onFramesAdded);
|
framesAdded = true;
|
||||||
|
executeSoon(startTest);
|
||||||
|
});
|
||||||
|
|
||||||
executeSoon(function() {
|
executeSoon(function() {
|
||||||
gDebuggee.firstCall();
|
gDebuggee.firstCall();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function onFramesAdded(aEvent) {
|
function onScriptShown(aEvent) {
|
||||||
framesAdded = true;
|
|
||||||
executeSoon(startTest);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSourceShown(aEvent) {
|
|
||||||
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
|
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
|
||||||
executeSoon(startTest);
|
executeSoon(startTest);
|
||||||
}
|
}
|
||||||
|
@ -51,8 +48,8 @@ function test()
|
||||||
{
|
{
|
||||||
if (scriptShown && framesAdded && resumed && !testStarted) {
|
if (scriptShown && framesAdded && resumed && !testStarted) {
|
||||||
testStarted = true;
|
testStarted = true;
|
||||||
gDebugger.removeEventListener("Debugger:SourceShown", onSourceShown);
|
gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
|
||||||
executeSoon(performTest);
|
Services.tm.currentThread.dispatch({ run: performTest }, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,158 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that we can set breakpoints and step through source mapped coffee
|
|
||||||
* script.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const TAB_URL = EXAMPLE_URL + "binary_search.html";
|
|
||||||
|
|
||||||
var gPane = null;
|
|
||||||
var gTab = null;
|
|
||||||
var gDebuggee = null;
|
|
||||||
var gDebugger = null;
|
|
||||||
|
|
||||||
function test()
|
|
||||||
{
|
|
||||||
let scriptShown = false;
|
|
||||||
let framesAdded = false;
|
|
||||||
let resumed = false;
|
|
||||||
let testStarted = false;
|
|
||||||
|
|
||||||
Services.prefs.setBoolPref("devtools.debugger.source-maps-enabled", true);
|
|
||||||
|
|
||||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
|
||||||
resumed = true;
|
|
||||||
gTab = aTab;
|
|
||||||
gDebuggee = aDebuggee;
|
|
||||||
gPane = aPane;
|
|
||||||
gDebugger = gPane.panelWin;
|
|
||||||
|
|
||||||
gDebugger.addEventListener("Debugger:SourceShown", function _onSourceShown(aEvent) {
|
|
||||||
gDebugger.removeEventListener("Debugger:SourceShown", _onSourceShown);
|
|
||||||
ok(aEvent.detail.url.indexOf(".coffee") != -1,
|
|
||||||
"The debugger should show the source mapped coffee script file.");
|
|
||||||
ok(gDebugger.editor.getText().search(/isnt/) != -1,
|
|
||||||
"The debugger's editor should have the coffee script source displayed.");
|
|
||||||
|
|
||||||
testSetBreakpoint();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSetBreakpoint() {
|
|
||||||
let { activeThread } = gDebugger.DebuggerController;
|
|
||||||
activeThread.interrupt(function (aResponse) {
|
|
||||||
activeThread.setBreakpoint({
|
|
||||||
url: EXAMPLE_URL + "binary_search.coffee",
|
|
||||||
line: 5
|
|
||||||
}, function (aResponse, bpClient) {
|
|
||||||
ok(!aResponse.error,
|
|
||||||
"Should be able to set a breakpoint in a coffee script file.");
|
|
||||||
testSetBreakpointBlankLine();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSetBreakpointBlankLine() {
|
|
||||||
let { activeThread } = gDebugger.DebuggerController;
|
|
||||||
activeThread.setBreakpoint({
|
|
||||||
url: EXAMPLE_URL + "binary_search.coffee",
|
|
||||||
line: 3
|
|
||||||
}, function (aResponse, bpClient) {
|
|
||||||
ok(aResponse.actualLocation,
|
|
||||||
"Because 3 is empty, we should have an actualLocation");
|
|
||||||
is(aResponse.actualLocation.url, EXAMPLE_URL + "binary_search.coffee",
|
|
||||||
"actualLocation.url should be source mapped to the coffee file");
|
|
||||||
is(aResponse.actualLocation.line, 2,
|
|
||||||
"actualLocation.line should be source mapped back to 2");
|
|
||||||
testHitBreakpoint();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function testHitBreakpoint() {
|
|
||||||
let { activeThread } = gDebugger.DebuggerController;
|
|
||||||
activeThread.resume(function (aResponse) {
|
|
||||||
ok(!aResponse.error, "Shouldn't get an error resuming");
|
|
||||||
is(aResponse.type, "resumed", "Type should be 'resumed'");
|
|
||||||
|
|
||||||
activeThread.addOneTimeListener("paused", function (aEvent, aPacket) {
|
|
||||||
is(aPacket.type, "paused",
|
|
||||||
"We should now be paused again");
|
|
||||||
is(aPacket.why.type, "breakpoint",
|
|
||||||
"and the reason we should be paused is because we hit a breakpoint");
|
|
||||||
|
|
||||||
// Check that we stopped at the right place, by making sure that the
|
|
||||||
// environment is in the state that we expect.
|
|
||||||
is(aPacket.frame.environment.bindings.variables.start.value, 0,
|
|
||||||
"'start' is 0");
|
|
||||||
is(aPacket.frame.environment.bindings.variables.stop.value.type, "undefined",
|
|
||||||
"'stop' hasn't been assigned to yet");
|
|
||||||
is(aPacket.frame.environment.bindings.variables.pivot.value.type, "undefined",
|
|
||||||
"'pivot' hasn't been assigned to yet");
|
|
||||||
|
|
||||||
waitForCaretPos(4, testStepping);
|
|
||||||
});
|
|
||||||
|
|
||||||
// This will cause the breakpoint to be hit, and put us back in the paused
|
|
||||||
// state.
|
|
||||||
executeSoon(function() {
|
|
||||||
gDebuggee.binary_search([0, 2, 3, 5, 7, 10], 5);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function testStepping() {
|
|
||||||
let { activeThread } = gDebugger.DebuggerController;
|
|
||||||
activeThread.resume(function (aResponse) {
|
|
||||||
ok(!aResponse.error, "Shouldn't get an error resuming");
|
|
||||||
is(aResponse.type, "resumed", "Type should be 'resumed'");
|
|
||||||
|
|
||||||
// After stepping, we will pause again, so listen for that.
|
|
||||||
activeThread.addOneTimeListener("paused", function (aEvent, aPacket) {
|
|
||||||
|
|
||||||
// Check that we stopped at the right place, by making sure that the
|
|
||||||
// environment is in the state that we expect.
|
|
||||||
is(aPacket.frame.environment.bindings.variables.start.value, 0,
|
|
||||||
"'start' is 0");
|
|
||||||
is(aPacket.frame.environment.bindings.variables.stop.value, 5,
|
|
||||||
"'stop' hasn't been assigned to yet");
|
|
||||||
is(aPacket.frame.environment.bindings.variables.pivot.value.type, "undefined",
|
|
||||||
"'pivot' hasn't been assigned to yet");
|
|
||||||
|
|
||||||
waitForCaretPos(5, closeDebuggerAndFinish);
|
|
||||||
});
|
|
||||||
}, {
|
|
||||||
type: "step"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function waitForCaretPos(number, callback)
|
|
||||||
{
|
|
||||||
// Poll every few milliseconds until the source editor line is active.
|
|
||||||
let count = 0;
|
|
||||||
let intervalID = window.setInterval(function() {
|
|
||||||
info("count: " + count + " ");
|
|
||||||
if (++count > 50) {
|
|
||||||
ok(false, "Timed out while polling for the line.");
|
|
||||||
window.clearInterval(intervalID);
|
|
||||||
return closeDebuggerAndFinish();
|
|
||||||
}
|
|
||||||
if (gDebugger.DebuggerView.editor.getCaretPosition().line != number) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// We got the source editor at the expected line, it's safe to callback.
|
|
||||||
window.clearInterval(intervalID);
|
|
||||||
callback();
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
registerCleanupFunction(function() {
|
|
||||||
Services.prefs.setBoolPref("devtools.debugger.source-maps-enabled", false);
|
|
||||||
removeTab(gTab);
|
|
||||||
gPane = null;
|
|
||||||
gTab = null;
|
|
||||||
gDebuggee = null;
|
|
||||||
gDebugger = null;
|
|
||||||
});
|
|
|
@ -322,10 +322,7 @@ DebuggerClient.prototype = {
|
||||||
*/
|
*/
|
||||||
attachTab: function DC_attachTab(aTabActor, aOnResponse) {
|
attachTab: function DC_attachTab(aTabActor, aOnResponse) {
|
||||||
let self = this;
|
let self = this;
|
||||||
let packet = {
|
let packet = { to: aTabActor, type: "attach" };
|
||||||
to: aTabActor,
|
|
||||||
type: "attach"
|
|
||||||
};
|
|
||||||
this.request(packet, function(aResponse) {
|
this.request(packet, function(aResponse) {
|
||||||
let tabClient;
|
let tabClient;
|
||||||
if (!aResponse.error) {
|
if (!aResponse.error) {
|
||||||
|
@ -375,17 +372,10 @@ DebuggerClient.prototype = {
|
||||||
* @param function aOnResponse
|
* @param function aOnResponse
|
||||||
* Called with the response packet and a ThreadClient
|
* Called with the response packet and a ThreadClient
|
||||||
* (which will be undefined on error).
|
* (which will be undefined on error).
|
||||||
* @param object aOptions
|
|
||||||
* Configuration options.
|
|
||||||
* - useSourceMaps: whether to use source maps or not.
|
|
||||||
*/
|
*/
|
||||||
attachThread: function DC_attachThread(aThreadActor, aOnResponse, aOptions={}) {
|
attachThread: function DC_attachThread(aThreadActor, aOnResponse) {
|
||||||
let self = this;
|
let self = this;
|
||||||
let packet = {
|
let packet = { to: aThreadActor, type: "attach" };
|
||||||
to: aThreadActor,
|
|
||||||
type: "attach",
|
|
||||||
options: aOptions
|
|
||||||
};
|
|
||||||
this.request(packet, function(aResponse) {
|
this.request(packet, function(aResponse) {
|
||||||
if (!aResponse.error) {
|
if (!aResponse.error) {
|
||||||
var threadClient = new ThreadClient(self, aThreadActor);
|
var threadClient = new ThreadClient(self, aThreadActor);
|
||||||
|
@ -443,7 +433,7 @@ DebuggerClient.prototype = {
|
||||||
*/
|
*/
|
||||||
_sendRequests: function DC_sendRequests() {
|
_sendRequests: function DC_sendRequests() {
|
||||||
let self = this;
|
let self = this;
|
||||||
this._pendingRequests = this._pendingRequests.filter(function (request) {
|
this._pendingRequests = this._pendingRequests.filter(function(request) {
|
||||||
if (request.to in self._activeRequests) {
|
if (request.to in self._activeRequests) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -470,7 +460,7 @@ DebuggerClient.prototype = {
|
||||||
? aPacket
|
? aPacket
|
||||||
: this.compat.onPacket(aPacket);
|
: this.compat.onPacket(aPacket);
|
||||||
|
|
||||||
resolve(packet).then((aPacket) => {
|
resolve(packet).then(function (aPacket) {
|
||||||
if (!this._connected) {
|
if (!this._connected) {
|
||||||
// Hello packet.
|
// Hello packet.
|
||||||
this._connected = true;
|
this._connected = true;
|
||||||
|
@ -480,53 +470,55 @@ DebuggerClient.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aPacket.from) {
|
try {
|
||||||
let msg = "Server did not specify an actor, dropping packet: " +
|
if (!aPacket.from) {
|
||||||
JSON.stringify(aPacket);
|
let msg = "Server did not specify an actor, dropping packet: " +
|
||||||
Cu.reportError(msg);
|
JSON.stringify(aPacket);
|
||||||
dumpn(msg);
|
Cu.reportError(msg);
|
||||||
return;
|
dumpn(msg);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let onResponse;
|
let onResponse;
|
||||||
// Don't count unsolicited notifications or pauses as responses.
|
// Don't count unsolicited notifications or pauses as responses.
|
||||||
if (aPacket.from in this._activeRequests &&
|
if (aPacket.from in this._activeRequests &&
|
||||||
!(aPacket.type in UnsolicitedNotifications) &&
|
!(aPacket.type in UnsolicitedNotifications) &&
|
||||||
!(aPacket.type == ThreadStateTypes.paused &&
|
!(aPacket.type == ThreadStateTypes.paused &&
|
||||||
aPacket.why.type in UnsolicitedPauses)) {
|
aPacket.why.type in UnsolicitedPauses)) {
|
||||||
onResponse = this._activeRequests[aPacket.from].onResponse;
|
onResponse = this._activeRequests[aPacket.from].onResponse;
|
||||||
delete this._activeRequests[aPacket.from];
|
delete this._activeRequests[aPacket.from];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Packets that indicate thread state changes get special treatment.
|
// Packets that indicate thread state changes get special treatment.
|
||||||
if (aPacket.type in ThreadStateTypes &&
|
if (aPacket.type in ThreadStateTypes &&
|
||||||
aPacket.from in this._threadClients) {
|
aPacket.from in this._threadClients) {
|
||||||
this._threadClients[aPacket.from]._onThreadState(aPacket);
|
this._threadClients[aPacket.from]._onThreadState(aPacket);
|
||||||
}
|
}
|
||||||
// On navigation the server resumes, so the client must resume as well.
|
// On navigation the server resumes, so the client must resume as well.
|
||||||
// We achieve that by generating a fake resumption packet that triggers
|
// We achieve that by generating a fake resumption packet that triggers
|
||||||
// the client's thread state change listeners.
|
// the client's thread state change listeners.
|
||||||
if (this.activeThread &&
|
if (this.activeThread &&
|
||||||
aPacket.type == UnsolicitedNotifications.tabNavigated &&
|
aPacket.type == UnsolicitedNotifications.tabNavigated &&
|
||||||
aPacket.from in this._tabClients) {
|
aPacket.from in this._tabClients) {
|
||||||
let resumption = { from: this.activeThread._actor, type: "resumed" };
|
let resumption = { from: this.activeThread._actor, type: "resumed" };
|
||||||
this.activeThread._onThreadState(resumption);
|
this.activeThread._onThreadState(resumption);
|
||||||
}
|
}
|
||||||
// Only try to notify listeners on events, not responses to requests
|
// Only try to notify listeners on events, not responses to requests
|
||||||
// that lack a packet type.
|
// that lack a packet type.
|
||||||
if (aPacket.type) {
|
if (aPacket.type) {
|
||||||
this.notify(aPacket.type, aPacket);
|
this.notify(aPacket.type, aPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onResponse) {
|
if (onResponse) {
|
||||||
onResponse(aPacket);
|
onResponse(aPacket);
|
||||||
|
}
|
||||||
|
} catch(ex) {
|
||||||
|
dumpn("Error handling response: " + ex + " - stack:\n" + ex.stack);
|
||||||
|
Cu.reportError(ex + "\n" + ex.stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._sendRequests();
|
this._sendRequests();
|
||||||
}, function (ex) {
|
}.bind(this));
|
||||||
dumpn("Error handling response: " + ex + " - stack:\n" + ex.stack);
|
|
||||||
Cu.reportError(ex.message + "\n" + ex.stack);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -30,6 +30,7 @@ function ThreadActor(aHooks, aGlobal)
|
||||||
this._frameActors = [];
|
this._frameActors = [];
|
||||||
this._environmentActors = [];
|
this._environmentActors = [];
|
||||||
this._hooks = aHooks;
|
this._hooks = aHooks;
|
||||||
|
this._sources = {};
|
||||||
this.global = aGlobal;
|
this.global = aGlobal;
|
||||||
|
|
||||||
// A cache of prototype chains for objects that have received a
|
// A cache of prototype chains for objects that have received a
|
||||||
|
@ -45,11 +46,6 @@ function ThreadActor(aHooks, aGlobal)
|
||||||
|
|
||||||
this.findGlobals = this.globalManager.findGlobals.bind(this);
|
this.findGlobals = this.globalManager.findGlobals.bind(this);
|
||||||
this.onNewGlobal = this.globalManager.onNewGlobal.bind(this);
|
this.onNewGlobal = this.globalManager.onNewGlobal.bind(this);
|
||||||
this.onNewSource = this.onNewSource.bind(this);
|
|
||||||
|
|
||||||
this._options = {
|
|
||||||
useSourceMaps: false
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,21 +73,13 @@ ThreadActor.prototype = {
|
||||||
return this._threadLifetimePool;
|
return this._threadLifetimePool;
|
||||||
},
|
},
|
||||||
|
|
||||||
get sources() {
|
|
||||||
if (!this._sources) {
|
|
||||||
this._sources = new ThreadSources(this, this._options.useSourceMaps,
|
|
||||||
this._allowSource, this.onNewSource);
|
|
||||||
}
|
|
||||||
return this._sources;
|
|
||||||
},
|
|
||||||
|
|
||||||
clearDebuggees: function TA_clearDebuggees() {
|
clearDebuggees: function TA_clearDebuggees() {
|
||||||
if (this.dbg) {
|
if (this.dbg) {
|
||||||
this.dbg.removeAllDebuggees();
|
this.dbg.removeAllDebuggees();
|
||||||
}
|
}
|
||||||
this.conn.removeActorPool(this._threadLifetimePool || undefined);
|
this.conn.removeActorPool(this._threadLifetimePool || undefined);
|
||||||
this._threadLifetimePool = null;
|
this._threadLifetimePool = null;
|
||||||
this._sources = null;
|
this._sources = {};
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -214,14 +202,11 @@ ThreadActor.prototype = {
|
||||||
|
|
||||||
this._state = "attached";
|
this._state = "attached";
|
||||||
|
|
||||||
update(this._options, aRequest.options || {});
|
|
||||||
|
|
||||||
if (!this.dbg) {
|
if (!this.dbg) {
|
||||||
this._initDebugger();
|
this._initDebugger();
|
||||||
}
|
}
|
||||||
this.findGlobals();
|
this.findGlobals();
|
||||||
this.dbg.enabled = true;
|
this.dbg.enabled = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Put ourselves in the paused state.
|
// Put ourselves in the paused state.
|
||||||
let packet = this._paused();
|
let packet = this._paused();
|
||||||
|
@ -237,20 +222,19 @@ ThreadActor.prototype = {
|
||||||
|
|
||||||
// Start a nested event loop.
|
// Start a nested event loop.
|
||||||
this._nest();
|
this._nest();
|
||||||
|
|
||||||
// We already sent a response to this request, don't send one
|
// We already sent a response to this request, don't send one
|
||||||
// now.
|
// now.
|
||||||
return null;
|
return null;
|
||||||
} catch (e) {
|
} catch(e) {
|
||||||
reportError(e);
|
Cu.reportError(e);
|
||||||
return { error: "notAttached", message: e.toString() };
|
return { error: "notAttached", message: e.toString() };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onDetach: function TA_onDetach(aRequest) {
|
onDetach: function TA_onDetach(aRequest) {
|
||||||
this.disconnect();
|
this.disconnect();
|
||||||
return {
|
return { type: "detached" };
|
||||||
type: "detached"
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -261,19 +245,15 @@ ThreadActor.prototype = {
|
||||||
* The newest debuggee frame in the stack.
|
* The newest debuggee frame in the stack.
|
||||||
* @param object aReason
|
* @param object aReason
|
||||||
* An object with a 'type' property containing the reason for the pause.
|
* An object with a 'type' property containing the reason for the pause.
|
||||||
* @param function onPacket
|
|
||||||
* Hook to modify the packet before it is sent. Feel free to return a
|
|
||||||
* promise.
|
|
||||||
*/
|
*/
|
||||||
_pauseAndRespond: function TA__pauseAndRespond(aFrame, aReason,
|
_pauseAndRespond: function TA__pauseAndRespond(aFrame, aReason) {
|
||||||
onPacket=function (k) k) {
|
|
||||||
try {
|
try {
|
||||||
let packet = this._paused(aFrame);
|
let packet = this._paused(aFrame);
|
||||||
if (!packet) {
|
if (!packet) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
packet.why = aReason;
|
packet.why = aReason;
|
||||||
resolve(onPacket(packet)).then(this.conn.send.bind(this.conn));
|
this.conn.send(packet);
|
||||||
return this._nest();
|
return this._nest();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
let msg = "Got an exception during TA__pauseAndRespond: " + e +
|
let msg = "Got an exception during TA__pauseAndRespond: " + e +
|
||||||
|
@ -288,14 +268,6 @@ ThreadActor.prototype = {
|
||||||
* Handle a protocol request to resume execution of the debuggee.
|
* Handle a protocol request to resume execution of the debuggee.
|
||||||
*/
|
*/
|
||||||
onResume: function TA_onResume(aRequest) {
|
onResume: function TA_onResume(aRequest) {
|
||||||
if (this._state !== "paused") {
|
|
||||||
return {
|
|
||||||
error: "wrongState",
|
|
||||||
message: "Can't resume when debuggee isn't paused. Current state is '"
|
|
||||||
+ this._state + "'"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// In case of multiple nested event loops (due to multiple debuggers open in
|
// In case of multiple nested event loops (due to multiple debuggers open in
|
||||||
// different tabs or multiple debugger clients connected to the same tab)
|
// different tabs or multiple debugger clients connected to the same tab)
|
||||||
// only allow resumption in a LIFO order.
|
// only allow resumption in a LIFO order.
|
||||||
|
@ -467,23 +439,14 @@ ThreadActor.prototype = {
|
||||||
// Return request.count frames, or all remaining
|
// Return request.count frames, or all remaining
|
||||||
// frames if count is not defined.
|
// frames if count is not defined.
|
||||||
let frames = [];
|
let frames = [];
|
||||||
let promises = [];
|
for (; frame && (!count || i < (start + count)); i++) {
|
||||||
for (; frame && (!count || i < (start + count)); i++, frame=frame.older) {
|
|
||||||
let form = this._createFrameActor(frame).form();
|
let form = this._createFrameActor(frame).form();
|
||||||
form.depth = i;
|
form.depth = i;
|
||||||
frames.push(form);
|
frames.push(form);
|
||||||
|
frame = frame.older;
|
||||||
let promise = this.sources.getOriginalLocation(form.where.url,
|
|
||||||
form.where.line)
|
|
||||||
.then(function (aOrigLocation) {
|
|
||||||
form.where = aOrigLocation;
|
|
||||||
});
|
|
||||||
promises.push(promise);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(promises).then(function () {
|
return { frames: frames };
|
||||||
return { frames: frames };
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onReleaseMany: function TA_onReleaseMany(aRequest) {
|
onReleaseMany: function TA_onReleaseMany(aRequest) {
|
||||||
|
@ -516,58 +479,25 @@ ThreadActor.prototype = {
|
||||||
message: "Breakpoints can only be set while the debuggee is paused."};
|
message: "Breakpoints can only be set while the debuggee is paused."};
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: `originalColumn` is never used. See bug 827639.
|
let location = aRequest.location;
|
||||||
let { url: originalSource,
|
let line = location.line;
|
||||||
line: originalLine,
|
if (this.dbg.findScripts({ url: location.url }).length == 0 || line < 0) {
|
||||||
column: originalColumn } = aRequest.location;
|
return { error: "noScript" };
|
||||||
|
}
|
||||||
|
|
||||||
let locationPromise = this.sources.getGeneratedLocation(originalSource,
|
// Add the breakpoint to the store for later reuse, in case it belongs to a
|
||||||
originalLine)
|
// script that hasn't appeared yet.
|
||||||
return locationPromise.then(function (aLocation) {
|
if (!this._breakpointStore[location.url]) {
|
||||||
let line = aLocation.line;
|
this._breakpointStore[location.url] = [];
|
||||||
if (this.dbg.findScripts({ url: aLocation.url }).length == 0 || line < 0) {
|
}
|
||||||
return { error: "noScript" };
|
let scriptBreakpoints = this._breakpointStore[location.url];
|
||||||
}
|
scriptBreakpoints[line] = {
|
||||||
|
url: location.url,
|
||||||
|
line: line,
|
||||||
|
column: location.column
|
||||||
|
};
|
||||||
|
|
||||||
// Add the breakpoint to the store for later reuse, in case it belongs to a
|
return this._setBreakpoint(location);
|
||||||
// script that hasn't appeared yet.
|
|
||||||
if (!this._breakpointStore[aLocation.url]) {
|
|
||||||
this._breakpointStore[aLocation.url] = [];
|
|
||||||
}
|
|
||||||
let scriptBreakpoints = this._breakpointStore[aLocation.url];
|
|
||||||
scriptBreakpoints[line] = {
|
|
||||||
url: aLocation.url,
|
|
||||||
line: line,
|
|
||||||
column: aLocation.column
|
|
||||||
};
|
|
||||||
|
|
||||||
let response = this._setBreakpoint(aLocation);
|
|
||||||
// If the original location of our generated location is different from
|
|
||||||
// the original location we attempted to set the breakpoint on, we will
|
|
||||||
// need to know so that we can set actualLocation on the response.
|
|
||||||
let originalLocation = this.sources.getOriginalLocation(aLocation.url,
|
|
||||||
aLocation.line);
|
|
||||||
|
|
||||||
return Promise.all(response, originalLocation)
|
|
||||||
.then(function ([aResponse, {url, line}]) {
|
|
||||||
if (aResponse.actualLocation) {
|
|
||||||
let actualOrigLocation = this.sources.getOriginalLocation(
|
|
||||||
aResponse.actualLocation.url, aResponse.actualLocation.line);
|
|
||||||
return actualOrigLocation.then(function ({ url, line }) {
|
|
||||||
if (url !== originalSource || line !== originalLine) {
|
|
||||||
aResponse.actualLocation = { url: url, line: line };
|
|
||||||
}
|
|
||||||
return aResponse;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url !== originalSource || line !== originalLine) {
|
|
||||||
aResponse.actualLocation = { url: url, line: line };
|
|
||||||
}
|
|
||||||
|
|
||||||
return aResponse;
|
|
||||||
}.bind(this));
|
|
||||||
}.bind(this));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -678,16 +608,17 @@ ThreadActor.prototype = {
|
||||||
* Get the script and source lists from the debugger.
|
* Get the script and source lists from the debugger.
|
||||||
*/
|
*/
|
||||||
_discoverScriptsAndSources: function TA__discoverScriptsAndSources() {
|
_discoverScriptsAndSources: function TA__discoverScriptsAndSources() {
|
||||||
return Promise.all([this._addScript(s)
|
for (let s of this.dbg.findScripts()) {
|
||||||
for (s of this.dbg.findScripts())]);
|
this._addScript(s);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onSources: function TA_onSources(aRequest) {
|
onSources: function TA_onSources(aRequest) {
|
||||||
return this._discoverScriptsAndSources().then(function () {
|
this._discoverScriptsAndSources();
|
||||||
return {
|
let urls = Object.getOwnPropertyNames(this._sources);
|
||||||
sources: [s.form() for (s of this.sources.iter())]
|
return {
|
||||||
};
|
sources: [this._getSource(url).form() for (url of urls)]
|
||||||
}.bind(this));
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -724,8 +655,8 @@ ThreadActor.prototype = {
|
||||||
// We already sent a response to this request, don't send one
|
// We already sent a response to this request, don't send one
|
||||||
// now.
|
// now.
|
||||||
return null;
|
return null;
|
||||||
} catch (e) {
|
} catch(e) {
|
||||||
reportError(e);
|
Cu.reportError(e);
|
||||||
return { error: "notInterrupted", message: e.toString() };
|
return { error: "notInterrupted", message: e.toString() };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -796,6 +727,7 @@ ThreadActor.prototype = {
|
||||||
if (aFrame) {
|
if (aFrame) {
|
||||||
packet.frame = this._createFrameActor(aFrame).form();
|
packet.frame = this._createFrameActor(aFrame).form();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (poppedFrames) {
|
if (poppedFrames) {
|
||||||
packet.poppedFrames = poppedFrames;
|
packet.poppedFrames = poppedFrames;
|
||||||
}
|
}
|
||||||
|
@ -1101,9 +1033,8 @@ ThreadActor.prototype = {
|
||||||
* Create a source grip for the given script.
|
* Create a source grip for the given script.
|
||||||
*/
|
*/
|
||||||
sourceGrip: function TA_sourceGrip(aScript) {
|
sourceGrip: function TA_sourceGrip(aScript) {
|
||||||
// TODO bug 637572: Once we have Debugger.Source, this should be replaced
|
// TODO: Once we have Debugger.Source, this should be replaced with a
|
||||||
// with a weakmap mapping Debugger.Source instances to SourceActor
|
// weakmap mapping Debugger.Source instances to SourceActor instances.
|
||||||
// instances.
|
|
||||||
if (!this.threadLifetimePool.sourceActors) {
|
if (!this.threadLifetimePool.sourceActors) {
|
||||||
this.threadLifetimePool.sourceActors = {};
|
this.threadLifetimePool.sourceActors = {};
|
||||||
}
|
}
|
||||||
|
@ -1163,7 +1094,7 @@ ThreadActor.prototype = {
|
||||||
exception: this.createValueGrip(aValue) };
|
exception: this.createValueGrip(aValue) };
|
||||||
this.conn.send(packet);
|
this.conn.send(packet);
|
||||||
return this._nest();
|
return this._nest();
|
||||||
} catch (e) {
|
} catch(e) {
|
||||||
Cu.reportError("Got an exception during TA_onExceptionUnwind: " + e +
|
Cu.reportError("Got an exception during TA_onExceptionUnwind: " + e +
|
||||||
": " + e.stack);
|
": " + e.stack);
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -1183,14 +1114,6 @@ ThreadActor.prototype = {
|
||||||
this._addScript(aScript);
|
this._addScript(aScript);
|
||||||
},
|
},
|
||||||
|
|
||||||
onNewSource: function TA_onNewSource(aSource) {
|
|
||||||
this.conn.send({
|
|
||||||
from: this.actorID,
|
|
||||||
type: "newSource",
|
|
||||||
source: aSource.form()
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if scripts from the provided source URL are allowed to be stored in
|
* Check if scripts from the provided source URL are allowed to be stored in
|
||||||
* the cache.
|
* the cache.
|
||||||
|
@ -1199,7 +1122,7 @@ ThreadActor.prototype = {
|
||||||
* The url of the script's source that will be stored.
|
* The url of the script's source that will be stored.
|
||||||
* @returns true, if the script can be added, false otherwise.
|
* @returns true, if the script can be added, false otherwise.
|
||||||
*/
|
*/
|
||||||
_allowSource: function TA__allowSource(aSourceUrl) {
|
_allowSource: function TA__allowScript(aSourceUrl) {
|
||||||
// Ignore anything we don't have a URL for (eval scripts, for example).
|
// Ignore anything we don't have a URL for (eval scripts, for example).
|
||||||
if (!aSourceUrl)
|
if (!aSourceUrl)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1223,30 +1146,28 @@ ThreadActor.prototype = {
|
||||||
*/
|
*/
|
||||||
_addScript: function TA__addScript(aScript) {
|
_addScript: function TA__addScript(aScript) {
|
||||||
if (!this._allowSource(aScript.url)) {
|
if (!this._allowSource(aScript.url)) {
|
||||||
return resolve(false);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO bug 637572: we should be dealing with sources directly, not
|
// TODO bug 637572: we should be dealing with sources directly, not
|
||||||
// inferring them through scripts.
|
// inferring them through scripts.
|
||||||
return this.sources.sourcesForScript(aScript).then(function () {
|
this._addSource(aScript.url);
|
||||||
|
|
||||||
// Set any stored breakpoints.
|
// Set any stored breakpoints.
|
||||||
let existing = this._breakpointStore[aScript.url];
|
let existing = this._breakpointStore[aScript.url];
|
||||||
if (existing) {
|
if (existing) {
|
||||||
let endLine = aScript.startLine + aScript.lineCount - 1;
|
let endLine = aScript.startLine + aScript.lineCount - 1;
|
||||||
// Iterate over the lines backwards, so that sliding breakpoints don't
|
// Iterate over the lines backwards, so that sliding breakpoints don't
|
||||||
// affect the loop.
|
// affect the loop.
|
||||||
for (let line = existing.length - 1; line >= 0; line--) {
|
for (let line = existing.length - 1; line >= 0; line--) {
|
||||||
let bp = existing[line];
|
let bp = existing[line];
|
||||||
// Limit search to the line numbers contained in the new script.
|
// Limit search to the line numbers contained in the new script.
|
||||||
if (bp && line >= aScript.startLine && line <= endLine) {
|
if (bp && line >= aScript.startLine && line <= endLine) {
|
||||||
this._setBreakpoint(bp);
|
this._setBreakpoint(bp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}.bind(this));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1294,6 +1215,48 @@ ThreadActor.prototype = {
|
||||||
return retval;
|
return retval;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a source to the current set of sources.
|
||||||
|
*
|
||||||
|
* Right now this takes an url, but in the future it should
|
||||||
|
* take a Debugger.Source.
|
||||||
|
*
|
||||||
|
* @param string the source URL.
|
||||||
|
* @returns a SourceActor representing the source.
|
||||||
|
*/
|
||||||
|
_addSource: function TA__addSource(aURL) {
|
||||||
|
if (!this._allowSource(aURL)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aURL in this._sources) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let actor = new SourceActor(aURL, this);
|
||||||
|
this.threadLifetimePool.addActor(actor);
|
||||||
|
this._sources[aURL] = actor;
|
||||||
|
|
||||||
|
this.conn.send({
|
||||||
|
from: this.actorID,
|
||||||
|
type: "newSource",
|
||||||
|
source: actor.form()
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the source actor for the given URL.
|
||||||
|
*/
|
||||||
|
_getSource: function TA__getSource(aUrl) {
|
||||||
|
let source = this._sources[aUrl];
|
||||||
|
if (!source) {
|
||||||
|
throw new Error("No source for '" + aUrl + "'");
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ThreadActor.prototype.requestTypes = {
|
ThreadActor.prototype.requestTypes = {
|
||||||
|
@ -1400,7 +1363,6 @@ SourceActor.prototype = {
|
||||||
actorPrefix: "source",
|
actorPrefix: "source",
|
||||||
|
|
||||||
get threadActor() { return this._threadActor; },
|
get threadActor() { return this._threadActor; },
|
||||||
get url() { return this._url; },
|
|
||||||
|
|
||||||
form: function SA_form() {
|
form: function SA_form() {
|
||||||
return {
|
return {
|
||||||
|
@ -1420,9 +1382,10 @@ SourceActor.prototype = {
|
||||||
* Handler for the "source" packet.
|
* Handler for the "source" packet.
|
||||||
*/
|
*/
|
||||||
onSource: function SA_onSource(aRequest) {
|
onSource: function SA_onSource(aRequest) {
|
||||||
return fetch(this._url)
|
return this
|
||||||
|
._loadSource()
|
||||||
.then(function(aSource) {
|
.then(function(aSource) {
|
||||||
return this.threadActor.createValueGrip(
|
return this._threadActor.createValueGrip(
|
||||||
aSource, this.threadActor.threadLifetimePool);
|
aSource, this.threadActor.threadLifetimePool);
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
.then(function (aSourceGrip) {
|
.then(function (aSourceGrip) {
|
||||||
|
@ -1431,17 +1394,121 @@ SourceActor.prototype = {
|
||||||
source: aSourceGrip
|
source: aSourceGrip
|
||||||
};
|
};
|
||||||
}.bind(this), function (aError) {
|
}.bind(this), function (aError) {
|
||||||
let msg = "Got an exception during SA_onSource: " + aError +
|
|
||||||
"\n" + aError.stack;
|
|
||||||
Cu.reportError(msg);
|
|
||||||
dumpn(msg);
|
|
||||||
return {
|
return {
|
||||||
"from": this.actorID,
|
"from": this.actorID,
|
||||||
"error": "loadSourceError",
|
"error": "loadSourceError",
|
||||||
"message": "Could not load the source for " + this._url + "."
|
"message": "Could not load the source for " + this._url + "."
|
||||||
};
|
};
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a given string, encoded in a given character set, to unicode.
|
||||||
|
* @param string aString
|
||||||
|
* A string.
|
||||||
|
* @param string aCharset
|
||||||
|
* A character set.
|
||||||
|
* @return string
|
||||||
|
* A unicode string.
|
||||||
|
*/
|
||||||
|
_convertToUnicode: function SS__convertToUnicode(aString, aCharset) {
|
||||||
|
// Decoding primitives.
|
||||||
|
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||||
|
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||||
|
|
||||||
|
try {
|
||||||
|
converter.charset = aCharset || "UTF-8";
|
||||||
|
return converter.ConvertToUnicode(aString);
|
||||||
|
} catch(e) {
|
||||||
|
return aString;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a request to load the desired URL and returns a promise.
|
||||||
|
*
|
||||||
|
* @param aURL String
|
||||||
|
* The URL we will request.
|
||||||
|
* @returns Promise
|
||||||
|
*
|
||||||
|
* XXX: It may be better to use nsITraceableChannel to get to the sources
|
||||||
|
* without relying on caching when we can (not for eval, etc.):
|
||||||
|
* http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/
|
||||||
|
*/
|
||||||
|
_loadSource: function SA__loadSource() {
|
||||||
|
let deferred = defer();
|
||||||
|
let scheme;
|
||||||
|
let url = this._url.split(" -> ").pop();
|
||||||
|
|
||||||
|
try {
|
||||||
|
scheme = Services.io.extractScheme(url);
|
||||||
|
} catch (e) {
|
||||||
|
// In the xpcshell tests, the script url is the absolute path of the test
|
||||||
|
// file, which will make a malformed URI error be thrown. Add the file
|
||||||
|
// scheme prefix ourselves.
|
||||||
|
url = "file://" + url;
|
||||||
|
scheme = Services.io.extractScheme(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (scheme) {
|
||||||
|
case "file":
|
||||||
|
case "chrome":
|
||||||
|
case "resource":
|
||||||
|
try {
|
||||||
|
NetUtil.asyncFetch(url, function onFetch(aStream, aStatus) {
|
||||||
|
if (!Components.isSuccessCode(aStatus)) {
|
||||||
|
deferred.reject(new Error("Request failed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let source = NetUtil.readInputStreamToString(aStream, aStream.available());
|
||||||
|
deferred.resolve(this._convertToUnicode(source));
|
||||||
|
aStream.close();
|
||||||
|
}.bind(this));
|
||||||
|
} catch (ex) {
|
||||||
|
deferred.reject(new Error("Request failed"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
let channel;
|
||||||
|
try {
|
||||||
|
channel = Services.io.newChannel(url, null, null);
|
||||||
|
} catch (e if e.name == "NS_ERROR_UNKNOWN_PROTOCOL") {
|
||||||
|
// On Windows xpcshell tests, c:/foo/bar can pass as a valid URL, but
|
||||||
|
// newChannel won't be able to handle it.
|
||||||
|
url = "file:///" + url;
|
||||||
|
channel = Services.io.newChannel(url, null, null);
|
||||||
|
}
|
||||||
|
let chunks = [];
|
||||||
|
let streamListener = {
|
||||||
|
onStartRequest: function(aRequest, aContext, aStatusCode) {
|
||||||
|
if (!Components.isSuccessCode(aStatusCode)) {
|
||||||
|
deferred.reject("Request failed");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDataAvailable: function(aRequest, aContext, aStream, aOffset, aCount) {
|
||||||
|
chunks.push(NetUtil.readInputStreamToString(aStream, aCount));
|
||||||
|
},
|
||||||
|
onStopRequest: function(aRequest, aContext, aStatusCode) {
|
||||||
|
if (!Components.isSuccessCode(aStatusCode)) {
|
||||||
|
deferred.reject("Request failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
deferred.resolve(this._convertToUnicode(chunks.join(""),
|
||||||
|
channel.contentCharset));
|
||||||
|
}.bind(this)
|
||||||
|
};
|
||||||
|
|
||||||
|
channel.loadFlags = channel.LOAD_FROM_CACHE;
|
||||||
|
channel.asyncOpen(streamListener, null);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SourceActor.prototype.requestTypes = {
|
SourceActor.prototype.requestTypes = {
|
||||||
|
@ -2028,14 +2095,7 @@ BreakpointActor.prototype = {
|
||||||
hit: function BA_hit(aFrame) {
|
hit: function BA_hit(aFrame) {
|
||||||
// TODO: add the rest of the breakpoints on that line (bug 676602).
|
// TODO: add the rest of the breakpoints on that line (bug 676602).
|
||||||
let reason = { type: "breakpoint", actors: [ this.actorID ] };
|
let reason = { type: "breakpoint", actors: [ this.actorID ] };
|
||||||
return this.threadActor._pauseAndRespond(aFrame, reason, function (aPacket) {
|
return this.threadActor._pauseAndRespond(aFrame, reason);
|
||||||
let { url, line } = aPacket.frame.where;
|
|
||||||
return this.threadActor.sources.getOriginalLocation(url, line)
|
|
||||||
.then(function (aOrigPosition) {
|
|
||||||
aPacket.frame.where = aOrigPosition;
|
|
||||||
return aPacket;
|
|
||||||
});
|
|
||||||
}.bind(this));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2357,183 +2417,6 @@ update(ChromeDebuggerActor.prototype, {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages the sources for a thread. Handles source maps, locations in the
|
|
||||||
* sources, etc for ThreadActors.
|
|
||||||
*/
|
|
||||||
function ThreadSources(aThreadActor, aUseSourceMaps,
|
|
||||||
aAllowPredicate, aOnNewSource) {
|
|
||||||
this._thread = aThreadActor;
|
|
||||||
this._useSourceMaps = aUseSourceMaps;
|
|
||||||
this._allow = aAllowPredicate;
|
|
||||||
this._onNewSource = aOnNewSource;
|
|
||||||
|
|
||||||
// source map URL --> promise of SourceMapConsumer
|
|
||||||
this._sourceMaps = Object.create(null);
|
|
||||||
// generated source url --> promise of SourceMapConsumer
|
|
||||||
this._sourceMapsByGeneratedSource = Object.create(null);
|
|
||||||
// original source url --> promise of SourceMapConsumer
|
|
||||||
this._sourceMapsByOriginalSource = Object.create(null);
|
|
||||||
// source url --> SourceActor
|
|
||||||
this._sourceActors = Object.create(null);
|
|
||||||
// original url --> generated url
|
|
||||||
this._generatedUrlsByOriginalUrl = Object.create(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
ThreadSources.prototype = {
|
|
||||||
/**
|
|
||||||
* Add a source to the current set of sources.
|
|
||||||
*
|
|
||||||
* Right now this takes a URL, but in the future it should
|
|
||||||
* take a Debugger.Source. See bug 637572.
|
|
||||||
*
|
|
||||||
* @param string the source URL.
|
|
||||||
* @returns a SourceActor representing the source or null.
|
|
||||||
*/
|
|
||||||
source: function TS_source(aURL) {
|
|
||||||
if (!this._allow(aURL)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aURL in this._sourceActors) {
|
|
||||||
return this._sourceActors[aURL];
|
|
||||||
}
|
|
||||||
|
|
||||||
let actor = new SourceActor(aURL, this._thread);
|
|
||||||
this._thread.threadLifetimePool.addActor(actor);
|
|
||||||
this._sourceActors[aURL] = actor;
|
|
||||||
try {
|
|
||||||
this._onNewSource(actor);
|
|
||||||
} catch (e) {
|
|
||||||
reportError(e);
|
|
||||||
}
|
|
||||||
return actor;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add all of the sources associated with the given script.
|
|
||||||
*/
|
|
||||||
sourcesForScript: function TS_sourcesForScript(aScript) {
|
|
||||||
if (!this._useSourceMaps || !aScript.sourceMapURL) {
|
|
||||||
return resolve([this.source(aScript.url)].filter(isNotNull));
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.sourceMap(aScript)
|
|
||||||
.then(function (aSourceMap) {
|
|
||||||
return [
|
|
||||||
this.source(s) for (s of aSourceMap.sources)
|
|
||||||
];
|
|
||||||
}.bind(this), function (e) {
|
|
||||||
reportError(e);
|
|
||||||
delete this._sourceMaps[aScript.sourceMapURL];
|
|
||||||
delete this._sourceMapsByGeneratedSource[aScript.url];
|
|
||||||
return [this.source(aScript.url)];
|
|
||||||
}.bind(this))
|
|
||||||
.then(function (aSources) {
|
|
||||||
return aSources.filter(isNotNull);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the source map for the given script.
|
|
||||||
*/
|
|
||||||
sourceMap: function TS_sourceMap(aScript) {
|
|
||||||
if (aScript.url in this._sourceMapsByGeneratedSource) {
|
|
||||||
return this._sourceMapsByGeneratedSource[aScript.url];
|
|
||||||
}
|
|
||||||
dbg_assert(aScript.sourceMapURL);
|
|
||||||
let map = this._fetchSourceMap(aScript.sourceMapURL)
|
|
||||||
.then(function (aSourceMap) {
|
|
||||||
for (let s of aSourceMap.sources) {
|
|
||||||
this._generatedUrlsByOriginalUrl[s] = aScript.url;
|
|
||||||
this._sourceMapsByOriginalSource[s] = resolve(aSourceMap);
|
|
||||||
}
|
|
||||||
return aSourceMap;
|
|
||||||
}.bind(this));
|
|
||||||
this._sourceMapsByGeneratedSource[aScript.url] = map;
|
|
||||||
return map;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the source map located at the given url.
|
|
||||||
*/
|
|
||||||
_fetchSourceMap: function TS__featchSourceMap(aSourceMapURL) {
|
|
||||||
if (aSourceMapURL in this._sourceMaps) {
|
|
||||||
return this._sourceMaps[aSourceMapURL];
|
|
||||||
} else {
|
|
||||||
let promise = fetch(aSourceMapURL).then(function (rawSourceMap) {
|
|
||||||
return new SourceMapConsumer(rawSourceMap);
|
|
||||||
});
|
|
||||||
this._sourceMaps[aSourceMapURL] = promise;
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a promise for the location in the original source if the source is
|
|
||||||
* source mapped, otherwise a promise of the same location.
|
|
||||||
*
|
|
||||||
* TODO bug 637572: take/return a column
|
|
||||||
*/
|
|
||||||
getOriginalLocation: function TS_getOriginalLocation(aSourceUrl, aLine) {
|
|
||||||
if (aSourceUrl in this._sourceMapsByGeneratedSource) {
|
|
||||||
return this._sourceMapsByGeneratedSource[aSourceUrl]
|
|
||||||
.then(function (aSourceMap) {
|
|
||||||
let { source, line } = aSourceMap.originalPositionFor({
|
|
||||||
source: aSourceUrl,
|
|
||||||
line: aLine,
|
|
||||||
column: Infinity
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
url: source,
|
|
||||||
line: line
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// No source map
|
|
||||||
return resolve({
|
|
||||||
url: aSourceUrl,
|
|
||||||
line: aLine
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a promise of the location in the generated source corresponding to
|
|
||||||
* the original source and line given.
|
|
||||||
*
|
|
||||||
* TODO bug 637572: take/return a column
|
|
||||||
*/
|
|
||||||
getGeneratedLocation: function TS_getGeneratedLocation(aSourceUrl, aLine) {
|
|
||||||
if (aSourceUrl in this._sourceMapsByOriginalSource) {
|
|
||||||
return this._sourceMapsByOriginalSource[aSourceUrl]
|
|
||||||
.then(function (aSourceMap) {
|
|
||||||
let { line } = aSourceMap.generatedPositionFor({
|
|
||||||
source: aSourceUrl,
|
|
||||||
line: aLine,
|
|
||||||
column: Infinity
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
url: this._generatedUrlsByOriginalUrl[aSourceUrl],
|
|
||||||
line: line
|
|
||||||
};
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
// No source map
|
|
||||||
return resolve({
|
|
||||||
url: aSourceUrl,
|
|
||||||
line: aLine
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
iter: function TS_iter() {
|
|
||||||
for (let url in this._sourceActors) {
|
|
||||||
yield this._sourceActors[url];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Utility functions.
|
// Utility functions.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2554,126 +2437,3 @@ function update(aTarget, aNewAttrs) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if its argument is not null.
|
|
||||||
*/
|
|
||||||
function isNotNull(aThing) {
|
|
||||||
return aThing !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs a request to load the desired URL and returns a promise.
|
|
||||||
*
|
|
||||||
* @param aURL String
|
|
||||||
* The URL we will request.
|
|
||||||
* @returns Promise
|
|
||||||
*
|
|
||||||
* XXX: It may be better to use nsITraceableChannel to get to the sources
|
|
||||||
* without relying on caching when we can (not for eval, etc.):
|
|
||||||
* http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/
|
|
||||||
*/
|
|
||||||
function fetch(aURL) {
|
|
||||||
let deferred = defer();
|
|
||||||
let scheme;
|
|
||||||
let url = aURL.split(" -> ").pop();
|
|
||||||
let charset;
|
|
||||||
|
|
||||||
try {
|
|
||||||
scheme = Services.io.extractScheme(url);
|
|
||||||
} catch (e) {
|
|
||||||
// In the xpcshell tests, the script url is the absolute path of the test
|
|
||||||
// file, which will make a malformed URI error be thrown. Add the file
|
|
||||||
// scheme prefix ourselves.
|
|
||||||
url = "file://" + url;
|
|
||||||
scheme = Services.io.extractScheme(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (scheme) {
|
|
||||||
case "file":
|
|
||||||
case "chrome":
|
|
||||||
case "resource":
|
|
||||||
try {
|
|
||||||
NetUtil.asyncFetch(url, function onFetch(aStream, aStatus) {
|
|
||||||
if (!Components.isSuccessCode(aStatus)) {
|
|
||||||
deferred.reject(new Error("Request failed"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let source = NetUtil.readInputStreamToString(aStream, aStream.available());
|
|
||||||
deferred.resolve(source);
|
|
||||||
aStream.close();
|
|
||||||
});
|
|
||||||
} catch (ex) {
|
|
||||||
deferred.reject(new Error("Request failed: " + url));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
let channel;
|
|
||||||
try {
|
|
||||||
channel = Services.io.newChannel(url, null, null);
|
|
||||||
} catch (e if e.name == "NS_ERROR_UNKNOWN_PROTOCOL") {
|
|
||||||
// On Windows xpcshell tests, c:/foo/bar can pass as a valid URL, but
|
|
||||||
// newChannel won't be able to handle it.
|
|
||||||
url = "file:///" + url;
|
|
||||||
channel = Services.io.newChannel(url, null, null);
|
|
||||||
}
|
|
||||||
let chunks = [];
|
|
||||||
let streamListener = {
|
|
||||||
onStartRequest: function(aRequest, aContext, aStatusCode) {
|
|
||||||
if (!Components.isSuccessCode(aStatusCode)) {
|
|
||||||
deferred.reject("Request failed");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onDataAvailable: function(aRequest, aContext, aStream, aOffset, aCount) {
|
|
||||||
chunks.push(NetUtil.readInputStreamToString(aStream, aCount));
|
|
||||||
},
|
|
||||||
onStopRequest: function(aRequest, aContext, aStatusCode) {
|
|
||||||
if (!Components.isSuccessCode(aStatusCode)) {
|
|
||||||
deferred.reject("Request failed: " + url);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
charset = channel.contentCharset;
|
|
||||||
deferred.resolve(chunks.join(""));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
channel.loadFlags = channel.LOAD_FROM_CACHE;
|
|
||||||
channel.asyncOpen(streamListener, null);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return deferred.promise.then(function (source) {
|
|
||||||
return convertToUnicode(source, charset);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a given string, encoded in a given character set, to unicode.
|
|
||||||
*
|
|
||||||
* @param string aString
|
|
||||||
* A string.
|
|
||||||
* @param string aCharset
|
|
||||||
* A character set.
|
|
||||||
*/
|
|
||||||
function convertToUnicode(aString, aCharset=null) {
|
|
||||||
// Decoding primitives.
|
|
||||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
|
||||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
|
||||||
try {
|
|
||||||
converter.charset = aCharset || "UTF-8";
|
|
||||||
return converter.ConvertToUnicode(aString);
|
|
||||||
} catch(e) {
|
|
||||||
return aString;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Report the given error in the error console and to stdout.
|
|
||||||
*/
|
|
||||||
function reportError(aError) {
|
|
||||||
Cu.reportError(aError);
|
|
||||||
dumpn(aError.message + ":\n" + aError.stack);
|
|
||||||
}
|
|
||||||
|
|
|
@ -26,9 +26,6 @@ addDebuggerToGlobal(this);
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||||
const { defer, resolve, reject } = Promise;
|
const { defer, resolve, reject } = Promise;
|
||||||
Promise.all = Promise.promised(Array);
|
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/devtools/SourceMap.jsm");
|
|
||||||
|
|
||||||
function dumpn(str) {
|
function dumpn(str) {
|
||||||
if (wantLogging) {
|
if (wantLogging) {
|
||||||
|
@ -603,17 +600,6 @@ DebuggerServerConnection.prototype = {
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
_unknownError: function DSC__unknownError(aPrefix, aError) {
|
|
||||||
let errorString = safeErrorString(aError);
|
|
||||||
errorString += "\n" + aError.stack;
|
|
||||||
Cu.reportError(errorString);
|
|
||||||
dumpn(errorString);
|
|
||||||
return {
|
|
||||||
error: "unknownError",
|
|
||||||
message: (aPrefix + "': " + errorString)
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
// Transport hooks.
|
// Transport hooks.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -636,9 +622,12 @@ DebuggerServerConnection.prototype = {
|
||||||
try {
|
try {
|
||||||
instance = new actor();
|
instance = new actor();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.transport.send(this._unknownError(
|
Cu.reportError(e);
|
||||||
"Error occurred while creating actor '" + actor.name,
|
this.transport.send({
|
||||||
e));
|
error: "unknownError",
|
||||||
|
message: ("error occurred while creating actor '" + actor.name +
|
||||||
|
"': " + safeErrorString(e))
|
||||||
|
});
|
||||||
}
|
}
|
||||||
instance.parentID = actor.parentID;
|
instance.parentID = actor.parentID;
|
||||||
// We want the newly-constructed actor to completely replace the factory
|
// We want the newly-constructed actor to completely replace the factory
|
||||||
|
@ -650,14 +639,16 @@ DebuggerServerConnection.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
var ret = null;
|
var ret = null;
|
||||||
|
|
||||||
// Dispatch the request to the actor.
|
// Dispatch the request to the actor.
|
||||||
if (actor.requestTypes && actor.requestTypes[aPacket.type]) {
|
if (actor.requestTypes && actor.requestTypes[aPacket.type]) {
|
||||||
try {
|
try {
|
||||||
ret = actor.requestTypes[aPacket.type].bind(actor)(aPacket);
|
ret = actor.requestTypes[aPacket.type].bind(actor)(aPacket);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
this.transport.send(this._unknownError(
|
Cu.reportError(e);
|
||||||
"error occurred while processing '" + aPacket.type,
|
ret = { error: "unknownError",
|
||||||
e));
|
message: ("error occurred while processing '" + aPacket.type +
|
||||||
|
"' request: " + safeErrorString(e)) };
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = { error: "unrecognizedPacketType",
|
ret = { error: "unrecognizedPacketType",
|
||||||
|
@ -672,19 +663,12 @@ DebuggerServerConnection.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(ret)
|
resolve(ret).then(function(returnPacket) {
|
||||||
.then(null, function (e) {
|
if (!returnPacket.from) {
|
||||||
return this._unknownError(
|
returnPacket.from = aPacket.to;
|
||||||
"error occurred while processing '" + aPacket.type,
|
}
|
||||||
e);
|
this.transport.send(returnPacket);
|
||||||
}.bind(this))
|
}.bind(this));
|
||||||
.then(function (aResponse) {
|
|
||||||
if (!aResponse.from) {
|
|
||||||
aResponse.from = aPacket.to;
|
|
||||||
}
|
|
||||||
return aResponse;
|
|
||||||
})
|
|
||||||
.then(this.transport.send.bind(this.transport));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -111,7 +111,7 @@ function getTestGlobalContext(aClient, aName, aCallback) {
|
||||||
|
|
||||||
function attachTestGlobalClient(aClient, aName, aCallback) {
|
function attachTestGlobalClient(aClient, aName, aCallback) {
|
||||||
getTestGlobalContext(aClient, aName, function(aContext) {
|
getTestGlobalContext(aClient, aName, function(aContext) {
|
||||||
aClient.attachThread(aContext.actor, aCallback, { useSourceMaps: true });
|
aClient.attachThread(aContext.actor, aCallback);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ function attachTestTabAndResume(aClient, aName, aCallback) {
|
||||||
aThreadClient.resume(function (aResponse) {
|
aThreadClient.resume(function (aResponse) {
|
||||||
aCallback(aResponse, aTabClient, aThreadClient);
|
aCallback(aResponse, aTabClient, aThreadClient);
|
||||||
});
|
});
|
||||||
}, { useSourceMaps: true });
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,8 @@ function test_child_breakpoint()
|
||||||
|
|
||||||
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||||
"function foo() {\n" + // line0 + 1
|
"function foo() {\n" + // line0 + 1
|
||||||
" this.a = 1;\n" + // line0 + 2
|
" this.a = 1;\n" + // line0 + 2
|
||||||
" this.b = 2;\n" + // line0 + 3
|
" this.b = 2;\n" + // line0 + 3
|
||||||
"}\n" + // line0 + 4
|
"}\n" + // line0 + 4
|
||||||
"debugger;\n" + // line0 + 5
|
"debugger;\n" + // line0 + 5
|
||||||
"foo();\n"); // line0 + 6
|
"foo();\n"); // line0 + 6
|
||||||
|
|
|
@ -38,7 +38,6 @@ function run_test()
|
||||||
function test_attach(aContext)
|
function test_attach(aContext)
|
||||||
{
|
{
|
||||||
gClient.request({ to: aContext.actor, type: "attach" }, function(aResponse) {
|
gClient.request({ to: aContext.actor, type: "attach" }, function(aResponse) {
|
||||||
do_check_true(!aResponse.error);
|
|
||||||
do_check_eq(aResponse.type, "paused");
|
do_check_eq(aResponse.type, "paused");
|
||||||
|
|
||||||
// Resume the thread and test the debugger statement.
|
// Resume the thread and test the debugger statement.
|
||||||
|
|
|
@ -16,6 +16,14 @@ function run_test()
|
||||||
initTestDebuggerServer();
|
initTestDebuggerServer();
|
||||||
gDebuggee = addTestGlobal("test-stack");
|
gDebuggee = addTestGlobal("test-stack");
|
||||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
|
gClient.request = (function (request) {
|
||||||
|
return function (aRequest, aOnResponse) {
|
||||||
|
if (aRequest.type === "sources") {
|
||||||
|
++gNumTimesSourcesSent;
|
||||||
|
}
|
||||||
|
return request.call(this, aRequest, aOnResponse);
|
||||||
|
};
|
||||||
|
}(gClient.request));
|
||||||
gClient.connect(function () {
|
gClient.connect(function () {
|
||||||
attachTestGlobalClientAndResume(gClient, "test-stack", function (aResponse, aThreadClient) {
|
attachTestGlobalClientAndResume(gClient, "test-stack", function (aResponse, aThreadClient) {
|
||||||
gThreadClient = aThreadClient;
|
gThreadClient = aThreadClient;
|
||||||
|
|
|
@ -16,7 +16,6 @@ function run_test()
|
||||||
initTestDebuggerServer();
|
initTestDebuggerServer();
|
||||||
gDebuggee = addTestGlobal("test-stack");
|
gDebuggee = addTestGlobal("test-stack");
|
||||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
|
|
||||||
gClient.request = (function (request) {
|
gClient.request = (function (request) {
|
||||||
return function (aRequest, aOnResponse) {
|
return function (aRequest, aOnResponse) {
|
||||||
if (aRequest.type === "sources") {
|
if (aRequest.type === "sources") {
|
||||||
|
@ -34,7 +33,6 @@ function run_test()
|
||||||
test_listing_zero_sources();
|
test_listing_zero_sources();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +47,6 @@ function test_listing_zero_sources()
|
||||||
"Should only send one sources request at most, even though we"
|
"Should only send one sources request at most, even though we"
|
||||||
+ " might have had to send one to determine feature support.");
|
+ " might have had to send one to determine feature support.");
|
||||||
|
|
||||||
finishClient(gClient);
|
finishClient(gClient);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check getSources functionality when there are lots of sources.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var gDebuggee;
|
|
||||||
var gClient;
|
|
||||||
var gThreadClient;
|
|
||||||
|
|
||||||
function run_test()
|
|
||||||
{
|
|
||||||
initTestDebuggerServer();
|
|
||||||
gDebuggee = addTestGlobal("test-sources");
|
|
||||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
|
||||||
gClient.connect(function () {
|
|
||||||
attachTestGlobalClientAndResume(gClient, "test-sources", function (aResponse, aThreadClient) {
|
|
||||||
gThreadClient = aThreadClient;
|
|
||||||
test_simple_listsources();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
do_test_pending();
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_simple_listsources()
|
|
||||||
{
|
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
|
||||||
gThreadClient.getSources(function (aResponse) {
|
|
||||||
do_check_true(
|
|
||||||
!aResponse.error,
|
|
||||||
"There shouldn't be an error fetching large amounts of sources.");
|
|
||||||
|
|
||||||
do_check_true(aResponse.sources.some(function (s) {
|
|
||||||
return s.url.match(/foo-999.js$/);
|
|
||||||
}));
|
|
||||||
|
|
||||||
gThreadClient.resume(function () {
|
|
||||||
finishClient(gClient);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
Cu.evalInSandbox("function foo###() {return ###;}".replace(/###/g, i),
|
|
||||||
gDebuggee,
|
|
||||||
"1.8",
|
|
||||||
"http://example.com/foo-" + i + ".js",
|
|
||||||
1);
|
|
||||||
}
|
|
||||||
gDebuggee.eval("debugger;");
|
|
||||||
}
|
|
|
@ -30,12 +30,10 @@ function test_pause_frame()
|
||||||
gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) {
|
gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) {
|
||||||
do_check_eq(aPacket.why.type, "exception");
|
do_check_eq(aPacket.why.type, "exception");
|
||||||
do_check_eq(aPacket.why.exception, 42);
|
do_check_eq(aPacket.why.exception, 42);
|
||||||
|
|
||||||
gThreadClient.resume(function () {
|
gThreadClient.resume(function () {
|
||||||
finishClient(gClient);
|
finishClient(gClient);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
gThreadClient.pauseOnExceptions(true);
|
gThreadClient.pauseOnExceptions(true);
|
||||||
gThreadClient.resume();
|
gThreadClient.resume();
|
||||||
});
|
});
|
||||||
|
|
|
@ -114,15 +114,21 @@ function test_profile(aClient, aProfiler)
|
||||||
do_check_eq(typeof aResponse.profile.threads[0].samples, "object");
|
do_check_eq(typeof aResponse.profile.threads[0].samples, "object");
|
||||||
do_check_neq(aResponse.profile.threads[0].samples.length, 0);
|
do_check_neq(aResponse.profile.threads[0].samples.length, 0);
|
||||||
|
|
||||||
let location = stack.name + " (" + stack.filename + ":" + funcLine + ")";
|
function some(array, cb) {
|
||||||
|
for (var i = array.length; i; i--) {
|
||||||
|
if (cb(array[i - 1]))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// At least one sample is expected to have been in the busy wait above.
|
// At least one sample is expected to have been in the busy wait above.
|
||||||
do_check_true(aResponse.profile.threads[0].samples.some(function(sample) {
|
do_check_true(some(aResponse.profile.threads[0].samples, function(sample) {
|
||||||
return sample.name == "(root)" &&
|
return sample.name == "(root)" &&
|
||||||
typeof sample.frames == "object" &&
|
typeof sample.frames == "object" &&
|
||||||
sample.frames.length != 0 &&
|
sample.frames.length != 0 &&
|
||||||
sample.frames.some(function(f) {
|
sample.frames.some(function(f) {
|
||||||
return (f.line == stack.lineNumber) &&
|
return (f.line == stack.lineNumber) &&
|
||||||
(f.location == location);
|
(f.location == stack.name + " (" + stack.filename + ":" + funcLine + ")");
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -155,13 +161,9 @@ function test_profiler_status()
|
||||||
|
|
||||||
var profiler = aResponse.profilerActor;
|
var profiler = aResponse.profilerActor;
|
||||||
do_check_false(Profiler.IsActive());
|
do_check_false(Profiler.IsActive());
|
||||||
client.request({
|
client.request({ to: profiler, type: "startProfiler", features: [] }, (aResponse) => {
|
||||||
to: profiler,
|
|
||||||
type: "startProfiler",
|
|
||||||
features: []
|
|
||||||
}, (aResponse) => {
|
|
||||||
do_check_true(Profiler.IsActive());
|
do_check_true(Profiler.IsActive());
|
||||||
client.close();
|
client.close(function () {});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check basic source map integration with the "newSource" packet in the RDP.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var gDebuggee;
|
|
||||||
var gClient;
|
|
||||||
var gThreadClient;
|
|
||||||
|
|
||||||
Components.utils.import('resource:///modules/devtools/SourceMap.jsm');
|
|
||||||
|
|
||||||
function run_test()
|
|
||||||
{
|
|
||||||
initTestDebuggerServer();
|
|
||||||
gDebuggee = addTestGlobal("test-source-map");
|
|
||||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
|
||||||
gClient.connect(function() {
|
|
||||||
attachTestGlobalClientAndResume(gClient, "test-source-map", function(aResponse, aThreadClient) {
|
|
||||||
gThreadClient = aThreadClient;
|
|
||||||
test_simple_source_map();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
do_test_pending();
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_simple_source_map()
|
|
||||||
{
|
|
||||||
// Because we are source mapping, we should be notified of a.js, b.js, and
|
|
||||||
// c.js as sources, and shouldn't receive abc.js or test_sourcemaps-01.js.
|
|
||||||
let expectedSources = new Set(["http://example.com/www/js/a.js",
|
|
||||||
"http://example.com/www/js/b.js",
|
|
||||||
"http://example.com/www/js/c.js"]);
|
|
||||||
|
|
||||||
gClient.addListener("newSource", function _onNewSource(aEvent, aPacket) {
|
|
||||||
do_check_eq(aEvent, "newSource");
|
|
||||||
do_check_eq(aPacket.type, "newSource");
|
|
||||||
do_check_true(!!aPacket.source);
|
|
||||||
|
|
||||||
do_check_true(expectedSources.has(aPacket.source.url),
|
|
||||||
"The source url should be one of our original sources.");
|
|
||||||
expectedSources.delete(aPacket.source.url);
|
|
||||||
|
|
||||||
if (expectedSources.size === 0) {
|
|
||||||
gClient.removeListener("newSource", _onNewSource);
|
|
||||||
finishClient(gClient);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let { code, map } = (new SourceNode(null, null, null, [
|
|
||||||
new SourceNode(1, 0, "a.js", "function a() { return 'a'; }\n"),
|
|
||||||
new SourceNode(1, 0, "b.js", "function b() { return 'b'; }\n"),
|
|
||||||
new SourceNode(1, 0, "c.js", "function c() { return 'c'; }\n"),
|
|
||||||
])).toStringWithSourceMap({
|
|
||||||
file: "abc.js",
|
|
||||||
sourceRoot: "http://example.com/www/js/"
|
|
||||||
});
|
|
||||||
|
|
||||||
code += "//@ sourceMappingURL=data:text/json;base64," + btoa(map.toString());
|
|
||||||
|
|
||||||
Components.utils.evalInSandbox(code, gDebuggee, "1.8",
|
|
||||||
"http://example.com/www/js/abc.js", 1);
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check basic source map integration with the "sources" packet in the RDP.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var gDebuggee;
|
|
||||||
var gClient;
|
|
||||||
var gThreadClient;
|
|
||||||
|
|
||||||
Components.utils.import("resource:///modules/devtools/SourceMap.jsm");
|
|
||||||
|
|
||||||
function run_test()
|
|
||||||
{
|
|
||||||
initTestDebuggerServer();
|
|
||||||
gDebuggee = addTestGlobal("test-source-map");
|
|
||||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
|
||||||
gClient.connect(function() {
|
|
||||||
attachTestGlobalClientAndResume(gClient, "test-source-map", function(aResponse, aThreadClient) {
|
|
||||||
gThreadClient = aThreadClient;
|
|
||||||
test_simple_source_map();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
do_test_pending();
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_simple_source_map()
|
|
||||||
{
|
|
||||||
// Because we are source mapping, we should be notified of a.js, b.js, and
|
|
||||||
// c.js as sources, and shouldn"t receive abc.js or test_sourcemaps-01.js.
|
|
||||||
let expectedSources = new Set(["http://example.com/www/js/a.js",
|
|
||||||
"http://example.com/www/js/b.js",
|
|
||||||
"http://example.com/www/js/c.js"]);
|
|
||||||
|
|
||||||
let numNewSources = 0;
|
|
||||||
|
|
||||||
gClient.addListener("newSource", function _onNewSource(aEvent, aPacket) {
|
|
||||||
if (++numNewSources !== 3) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
gClient.removeListener("newSource", _onNewSource);
|
|
||||||
|
|
||||||
gThreadClient.getSources(function (aResponse) {
|
|
||||||
do_check_true(!aResponse.error, "Should not get an error");
|
|
||||||
|
|
||||||
for (let s of aResponse.sources) {
|
|
||||||
do_check_true(expectedSources.has(s.url),
|
|
||||||
"The source's url should be one of our original sources");
|
|
||||||
expectedSources.delete(s.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
do_check_eq(expectedSources.size, 0,
|
|
||||||
"Shouldn't be expecting any more sources");
|
|
||||||
|
|
||||||
finishClient(gClient);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let { code, map } = (new SourceNode(null, null, null, [
|
|
||||||
new SourceNode(1, 0, "a.js", "function a() { return 'a'; }\n"),
|
|
||||||
new SourceNode(1, 0, "b.js", "function b() { return 'b'; }\n"),
|
|
||||||
new SourceNode(1, 0, "c.js", "function c() { return 'c'; }\n"),
|
|
||||||
])).toStringWithSourceMap({
|
|
||||||
file: "abc.js",
|
|
||||||
sourceRoot: "http://example.com/www/js/"
|
|
||||||
});
|
|
||||||
|
|
||||||
code += "//@ sourceMappingURL=data:text/json;base64," + btoa(map.toString());
|
|
||||||
|
|
||||||
Components.utils.evalInSandbox(code, gDebuggee, "1.8",
|
|
||||||
"http://example.com/www/js/abc.js", 1);
|
|
||||||
}
|
|
|
@ -1,149 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check setting breakpoints in source mapped sources.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var gDebuggee;
|
|
||||||
var gClient;
|
|
||||||
var gThreadClient;
|
|
||||||
|
|
||||||
Components.utils.import('resource:///modules/devtools/SourceMap.jsm');
|
|
||||||
|
|
||||||
function run_test()
|
|
||||||
{
|
|
||||||
initTestDebuggerServer();
|
|
||||||
gDebuggee = addTestGlobal("test-source-map");
|
|
||||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
|
||||||
gClient.connect(function() {
|
|
||||||
attachTestGlobalClientAndResume(gClient, "test-source-map", function(aResponse, aThreadClient) {
|
|
||||||
gThreadClient = aThreadClient;
|
|
||||||
test_simple_source_map();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
do_test_pending();
|
|
||||||
}
|
|
||||||
|
|
||||||
function testBreakpointMapping(aName, aCallback)
|
|
||||||
{
|
|
||||||
// Pause so we can set a breakpoint.
|
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
|
||||||
do_check_true(!aPacket.error);
|
|
||||||
do_check_eq(aPacket.why.type, "debuggerStatement");
|
|
||||||
|
|
||||||
gThreadClient.setBreakpoint({
|
|
||||||
url: "http://example.com/www/js/" + aName + ".js",
|
|
||||||
// Setting the breakpoint on an empty line so that it is pushed down one
|
|
||||||
// line and we can check the source mapped actualLocation later.
|
|
||||||
line: 3,
|
|
||||||
column: 0
|
|
||||||
}, function (aResponse) {
|
|
||||||
do_check_true(!aResponse.error);
|
|
||||||
|
|
||||||
// Actual location should come back source mapped still so that
|
|
||||||
// breakpoints are displayed in the UI correctly, etc.
|
|
||||||
do_check_eq(aResponse.actualLocation.line, 4);
|
|
||||||
do_check_eq(aResponse.actualLocation.url,
|
|
||||||
"http://example.com/www/js/" + aName + ".js");
|
|
||||||
|
|
||||||
// The eval will cause us to resume, then we get an unsolicited pause
|
|
||||||
// because of our breakpoint, we resume again to finish the eval, and
|
|
||||||
// finally receive our last pause which has the result of the client
|
|
||||||
// evaluation.
|
|
||||||
gThreadClient.eval(null, aName + "()", function (aResponse) {
|
|
||||||
do_check_true(!aResponse.error, "Shouldn't be an error resuming to eval");
|
|
||||||
do_check_eq(aResponse.type, "resumed");
|
|
||||||
|
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
|
||||||
do_check_eq(aPacket.why.type, "breakpoint");
|
|
||||||
// Assert that we paused because of the breakpoint at the correct
|
|
||||||
// location in the code by testing that the value of `ret` is still
|
|
||||||
// undefined.
|
|
||||||
do_check_eq(aPacket.frame.environment.bindings.variables.ret.value.type,
|
|
||||||
"undefined");
|
|
||||||
|
|
||||||
gThreadClient.resume(function (aResponse) {
|
|
||||||
do_check_true(!aResponse.error);
|
|
||||||
|
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
|
||||||
do_check_eq(aPacket.why.type, "clientEvaluated");
|
|
||||||
do_check_eq(aPacket.why.frameFinished.return, aName);
|
|
||||||
|
|
||||||
gThreadClient.resume(function (aResponse) {
|
|
||||||
do_check_true(!aResponse.error);
|
|
||||||
aCallback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
gDebuggee.eval("(" + function () {
|
|
||||||
debugger;
|
|
||||||
} + "());");
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_simple_source_map()
|
|
||||||
{
|
|
||||||
let expectedSources = new Set([
|
|
||||||
"http://example.com/www/js/a.js",
|
|
||||||
"http://example.com/www/js/b.js",
|
|
||||||
"http://example.com/www/js/c.js"
|
|
||||||
]);
|
|
||||||
|
|
||||||
gClient.addListener("newSource", function _onNewSource(aEvent, aPacket) {
|
|
||||||
expectedSources.delete(aPacket.source.url);
|
|
||||||
if (expectedSources.size > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
gClient.removeListener("newSource", _onNewSource);
|
|
||||||
|
|
||||||
testBreakpointMapping("a", function () {
|
|
||||||
testBreakpointMapping("b", function () {
|
|
||||||
testBreakpointMapping("c", function () {
|
|
||||||
finishClient(gClient);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let a = new SourceNode(null, null, null, [
|
|
||||||
new SourceNode(1, 0, "a.js", "function a() {\n"),
|
|
||||||
new SourceNode(2, 0, "a.js", " var ret;\n"),
|
|
||||||
new SourceNode(3, 0, "a.js", " // Empty line\n"),
|
|
||||||
new SourceNode(4, 0, "a.js", " ret = 'a';\n"),
|
|
||||||
new SourceNode(5, 0, "a.js", " return ret;\n"),
|
|
||||||
new SourceNode(6, 0, "a.js", "}\n")
|
|
||||||
]);
|
|
||||||
let b = new SourceNode(null, null, null, [
|
|
||||||
new SourceNode(1, 0, "b.js", "function b() {\n"),
|
|
||||||
new SourceNode(2, 0, "b.js", " var ret;\n"),
|
|
||||||
new SourceNode(3, 0, "b.js", " // Empty line\n"),
|
|
||||||
new SourceNode(4, 0, "b.js", " ret = 'b';\n"),
|
|
||||||
new SourceNode(5, 0, "b.js", " return ret;\n"),
|
|
||||||
new SourceNode(6, 0, "b.js", "}\n")
|
|
||||||
]);
|
|
||||||
let c = new SourceNode(null, null, null, [
|
|
||||||
new SourceNode(1, 0, "c.js", "function c() {\n"),
|
|
||||||
new SourceNode(2, 0, "c.js", " var ret;\n"),
|
|
||||||
new SourceNode(3, 0, "c.js", " // Empty line\n"),
|
|
||||||
new SourceNode(4, 0, "c.js", " ret = 'c';\n"),
|
|
||||||
new SourceNode(5, 0, "c.js", " return ret;\n"),
|
|
||||||
new SourceNode(6, 0, "c.js", "}\n")
|
|
||||||
]);
|
|
||||||
|
|
||||||
let { code, map } = (new SourceNode(null, null, null, [
|
|
||||||
a, b, c
|
|
||||||
])).toStringWithSourceMap({
|
|
||||||
file: "http://example.com/www/js/abc.js",
|
|
||||||
sourceRoot: "http://example.com/www/js/"
|
|
||||||
});
|
|
||||||
|
|
||||||
code += "//@ sourceMappingURL=data:text/json;base64," + btoa(map.toString());
|
|
||||||
|
|
||||||
Components.utils.evalInSandbox(code, gDebuggee, "1.8",
|
|
||||||
"http://example.com/www/js/abc.js", 1);
|
|
||||||
}
|
|
|
@ -18,7 +18,6 @@ function run_test()
|
||||||
initSourcesBackwardsCompatDebuggerServer();
|
initSourcesBackwardsCompatDebuggerServer();
|
||||||
gDebuggee = addTestGlobal("test-sources-compat");
|
gDebuggee = addTestGlobal("test-sources-compat");
|
||||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
|
|
||||||
gClient.request = (function (request) {
|
gClient.request = (function (request) {
|
||||||
return function (aRequest, aOnResponse) {
|
return function (aRequest, aOnResponse) {
|
||||||
if (aRequest.type === "sources") {
|
if (aRequest.type === "sources") {
|
||||||
|
@ -27,7 +26,6 @@ function run_test()
|
||||||
return request.call(this, aRequest, aOnResponse);
|
return request.call(this, aRequest, aOnResponse);
|
||||||
};
|
};
|
||||||
}(gClient.request));
|
}(gClient.request));
|
||||||
|
|
||||||
gClient.connect(function() {
|
gClient.connect(function() {
|
||||||
attachTestTabAndResume(gClient, "test-sources-compat", function (aResponse,
|
attachTestTabAndResume(gClient, "test-sources-compat", function (aResponse,
|
||||||
aTabClient,
|
aTabClient,
|
||||||
|
|
|
@ -17,7 +17,6 @@ function run_test()
|
||||||
initSourcesBackwardsCompatDebuggerServer();
|
initSourcesBackwardsCompatDebuggerServer();
|
||||||
gDebuggee = addTestGlobal("test-sources-compat");
|
gDebuggee = addTestGlobal("test-sources-compat");
|
||||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
|
|
||||||
gClient.request = (function (request) {
|
gClient.request = (function (request) {
|
||||||
return function (aRequest, aOnResponse) {
|
return function (aRequest, aOnResponse) {
|
||||||
if (aRequest.type === "sources") {
|
if (aRequest.type === "sources") {
|
||||||
|
|
|
@ -30,26 +30,26 @@ function createRootActor()
|
||||||
};
|
};
|
||||||
|
|
||||||
actor.thread.requestTypes["scripts"] = function (aRequest) {
|
actor.thread.requestTypes["scripts"] = function (aRequest) {
|
||||||
return this._discoverScriptsAndSources().then(function () {
|
this._discoverScriptsAndSources();
|
||||||
let scripts = [];
|
|
||||||
for (let s of this.dbg.findScripts()) {
|
|
||||||
if (!s.url) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let script = {
|
|
||||||
url: s.url,
|
|
||||||
startLine: s.startLine,
|
|
||||||
lineCount: s.lineCount,
|
|
||||||
source: this.sources.source(s.url).form()
|
|
||||||
};
|
|
||||||
scripts.push(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
let scripts = [];
|
||||||
from: this.actorID,
|
for (let s of this.dbg.findScripts()) {
|
||||||
scripts: scripts
|
if (!s.url) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let script = {
|
||||||
|
url: s.url,
|
||||||
|
startLine: s.startLine,
|
||||||
|
lineCount: s.lineCount,
|
||||||
|
source: this._getSource(s.url).form()
|
||||||
};
|
};
|
||||||
}.bind(this));
|
scripts.push(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
from: this.actorID,
|
||||||
|
scripts: scripts
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pretend that we do not know about the "sources" packet to force the
|
// Pretend that we do not know about the "sources" packet to force the
|
||||||
|
@ -70,7 +70,7 @@ function createRootActor()
|
||||||
url: aScript.url,
|
url: aScript.url,
|
||||||
startLine: aScript.startLine,
|
startLine: aScript.startLine,
|
||||||
lineCount: aScript.lineCount,
|
lineCount: aScript.lineCount,
|
||||||
source: actor.thread.sources.source(aScript.url).form()
|
source: actor.thread._getSource(aScript.url).form()
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}(actor.thread.onNewScript));
|
}(actor.thread.onNewScript));
|
||||||
|
|
|
@ -74,13 +74,9 @@ skip-if = toolkit == "gonk"
|
||||||
reason = bug 820380
|
reason = bug 820380
|
||||||
[test_listsources-01.js]
|
[test_listsources-01.js]
|
||||||
[test_listsources-02.js]
|
[test_listsources-02.js]
|
||||||
[test_listsources-03.js]
|
|
||||||
[test_new_source-01.js]
|
[test_new_source-01.js]
|
||||||
[test_sources_backwards_compat-01.js]
|
[test_sources_backwards_compat-01.js]
|
||||||
[test_sources_backwards_compat-02.js]
|
[test_sources_backwards_compat-02.js]
|
||||||
[test_sourcemaps-01.js]
|
|
||||||
[test_sourcemaps-02.js]
|
|
||||||
[test_sourcemaps-03.js]
|
|
||||||
[test_objectgrips-01.js]
|
[test_objectgrips-01.js]
|
||||||
[test_objectgrips-02.js]
|
[test_objectgrips-02.js]
|
||||||
[test_objectgrips-03.js]
|
[test_objectgrips-03.js]
|
||||||
|
|
|
@ -44,7 +44,6 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou
|
||||||
* - sources: An array of URLs to the original source files.
|
* - sources: An array of URLs to the original source files.
|
||||||
* - names: An array of identifiers which can be referrenced by individual mappings.
|
* - names: An array of identifiers which can be referrenced by individual mappings.
|
||||||
* - sourceRoot: Optional. The URL root from which all sources are relative.
|
* - sourceRoot: Optional. The URL root from which all sources are relative.
|
||||||
* - sourcesContent: Optional. An array of contents of the original source files.
|
|
||||||
* - mappings: A string of base64 VLQs which contain the actual mappings.
|
* - mappings: A string of base64 VLQs which contain the actual mappings.
|
||||||
* - file: The generated file this source map is associated with.
|
* - file: The generated file this source map is associated with.
|
||||||
*
|
*
|
||||||
|
@ -71,7 +70,6 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou
|
||||||
var sources = util.getArg(sourceMap, 'sources');
|
var sources = util.getArg(sourceMap, 'sources');
|
||||||
var names = util.getArg(sourceMap, 'names');
|
var names = util.getArg(sourceMap, 'names');
|
||||||
var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
|
var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
|
||||||
var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);
|
|
||||||
var mappings = util.getArg(sourceMap, 'mappings');
|
var mappings = util.getArg(sourceMap, 'mappings');
|
||||||
var file = util.getArg(sourceMap, 'file');
|
var file = util.getArg(sourceMap, 'file');
|
||||||
|
|
||||||
|
@ -81,8 +79,7 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou
|
||||||
|
|
||||||
this._names = ArraySet.fromArray(names);
|
this._names = ArraySet.fromArray(names);
|
||||||
this._sources = ArraySet.fromArray(sources);
|
this._sources = ArraySet.fromArray(sources);
|
||||||
this.sourceRoot = sourceRoot;
|
this._sourceRoot = sourceRoot;
|
||||||
this.sourcesContent = sourcesContent;
|
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
|
||||||
// `this._generatedMappings` and `this._originalMappings` hold the parsed
|
// `this._generatedMappings` and `this._originalMappings` hold the parsed
|
||||||
|
@ -124,7 +121,7 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou
|
||||||
Object.defineProperty(SourceMapConsumer.prototype, 'sources', {
|
Object.defineProperty(SourceMapConsumer.prototype, 'sources', {
|
||||||
get: function () {
|
get: function () {
|
||||||
return this._sources.toArray().map(function (s) {
|
return this._sources.toArray().map(function (s) {
|
||||||
return this.sourceRoot ? util.join(this.sourceRoot, s) : s;
|
return this._sourceRoot ? util.join(this._sourceRoot, s) : s;
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -168,7 +165,12 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou
|
||||||
if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {
|
if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {
|
||||||
// Original source.
|
// Original source.
|
||||||
temp = base64VLQ.decode(str);
|
temp = base64VLQ.decode(str);
|
||||||
mapping.source = this._sources.at(previousSource + temp.value);
|
if (aSourceRoot) {
|
||||||
|
mapping.source = util.join(aSourceRoot, this._sources.at(previousSource + temp.value));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mapping.source = this._sources.at(previousSource + temp.value);
|
||||||
|
}
|
||||||
previousSource += temp.value;
|
previousSource += temp.value;
|
||||||
str = temp.rest;
|
str = temp.rest;
|
||||||
if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {
|
if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {
|
||||||
|
@ -202,9 +204,7 @@ 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,15 +291,11 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou
|
||||||
this._generatedMappings,
|
this._generatedMappings,
|
||||||
"generatedLine",
|
"generatedLine",
|
||||||
"generatedColumn",
|
"generatedColumn",
|
||||||
this._compareGeneratedPositions);
|
this._compareGeneratedPositions)
|
||||||
|
|
||||||
if (mapping) {
|
if (mapping) {
|
||||||
var source = util.getArg(mapping, 'source', null);
|
|
||||||
if (source && this.sourceRoot) {
|
|
||||||
source = util.join(this.sourceRoot, source);
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
source: source,
|
source: util.getArg(mapping, 'source', null),
|
||||||
line: util.getArg(mapping, 'originalLine', null),
|
line: util.getArg(mapping, 'originalLine', null),
|
||||||
column: util.getArg(mapping, 'originalColumn', null),
|
column: util.getArg(mapping, 'originalColumn', null),
|
||||||
name: util.getArg(mapping, 'name', null)
|
name: util.getArg(mapping, 'name', null)
|
||||||
|
@ -314,32 +310,6 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the original source content. The only argument is
|
|
||||||
* the url of the original source file. Returns null if no
|
|
||||||
* original source content is availible.
|
|
||||||
*/
|
|
||||||
SourceMapConsumer.prototype.sourceContentFor =
|
|
||||||
function SourceMapConsumer_sourceContentFor(aSource) {
|
|
||||||
if (!this.sourcesContent) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.sourceRoot) {
|
|
||||||
// Try to remove the sourceRoot
|
|
||||||
var relativeUrl = util.relative(this.sourceRoot, aSource);
|
|
||||||
if (this._sources.has(relativeUrl)) {
|
|
||||||
return this.sourcesContent[this._sources.indexOf(relativeUrl)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._sources.has(aSource)) {
|
|
||||||
return this.sourcesContent[this._sources.indexOf(aSource)];
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error('"' + aSource + '" is not in the SourceMap.');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the generated line and column information for the original source,
|
* Returns the generated line and column information for the original source,
|
||||||
* line, and column positions provided. The only argument is an object with
|
* line, and column positions provided. The only argument is an object with
|
||||||
|
@ -362,15 +332,11 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou
|
||||||
originalColumn: util.getArg(aArgs, 'column')
|
originalColumn: util.getArg(aArgs, 'column')
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.sourceRoot) {
|
|
||||||
needle.source = util.relative(this.sourceRoot, needle.source);
|
|
||||||
}
|
|
||||||
|
|
||||||
var mapping = this._findMapping(needle,
|
var mapping = this._findMapping(needle,
|
||||||
this._originalMappings,
|
this._originalMappings,
|
||||||
"originalLine",
|
"originalLine",
|
||||||
"originalColumn",
|
"originalColumn",
|
||||||
this._compareOriginalPositions);
|
this._compareOriginalPositions)
|
||||||
|
|
||||||
if (mapping) {
|
if (mapping) {
|
||||||
return {
|
return {
|
||||||
|
@ -393,7 +359,8 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou
|
||||||
* generated line/column in this source map.
|
* generated line/column in this source map.
|
||||||
*
|
*
|
||||||
* @param Function aCallback
|
* @param Function aCallback
|
||||||
* The function that is called with each mapping.
|
* The function that is called with each mapping. This function should
|
||||||
|
* not mutate the mapping.
|
||||||
* @param Object aContext
|
* @param Object aContext
|
||||||
* Optional. If specified, this object will be the value of `this` every
|
* Optional. If specified, this object will be the value of `this` every
|
||||||
* time that `aCallback` is called.
|
* time that `aCallback` is called.
|
||||||
|
@ -421,21 +388,7 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou
|
||||||
throw new Error("Unknown order of iteration.");
|
throw new Error("Unknown order of iteration.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var sourceRoot = this.sourceRoot;
|
mappings.forEach(aCallback, context);
|
||||||
mappings.map(function (mapping) {
|
|
||||||
var source = mapping.source;
|
|
||||||
if (source && sourceRoot) {
|
|
||||||
source = util.join(sourceRoot, source);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
source: source,
|
|
||||||
generatedLine: mapping.generatedLine,
|
|
||||||
generatedColumn: mapping.generatedColumn,
|
|
||||||
originalLine: mapping.originalLine,
|
|
||||||
originalColumn: mapping.originalColumn,
|
|
||||||
name: mapping.name
|
|
||||||
};
|
|
||||||
}).forEach(aCallback, context);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.SourceMapConsumer = SourceMapConsumer;
|
exports.SourceMapConsumer = SourceMapConsumer;
|
||||||
|
@ -473,37 +426,10 @@ define('source-map/util', ['require', 'exports', 'module' , ], function(require,
|
||||||
function join(aRoot, aPath) {
|
function join(aRoot, aPath) {
|
||||||
return aPath.charAt(0) === '/'
|
return aPath.charAt(0) === '/'
|
||||||
? aPath
|
? aPath
|
||||||
: aRoot.replace(/\/$/, '') + '/' + aPath;
|
: aRoot.replace(/\/*$/, '') + '/' + aPath;
|
||||||
}
|
}
|
||||||
exports.join = join;
|
exports.join = join;
|
||||||
|
|
||||||
/**
|
|
||||||
* Because behavior goes wacky when you set `__proto__` on objects, we
|
|
||||||
* have to prefix all the strings in our set with an arbitrary character.
|
|
||||||
*
|
|
||||||
* See https://github.com/mozilla/source-map/pull/31 and
|
|
||||||
* https://github.com/mozilla/source-map/issues/30
|
|
||||||
*
|
|
||||||
* @param String aStr
|
|
||||||
*/
|
|
||||||
function toSetString(aStr) {
|
|
||||||
return '$' + aStr;
|
|
||||||
}
|
|
||||||
exports.toSetString = toSetString;
|
|
||||||
|
|
||||||
function fromSetString(aStr) {
|
|
||||||
return aStr.substr(1);
|
|
||||||
}
|
|
||||||
exports.fromSetString = fromSetString;
|
|
||||||
|
|
||||||
function relative(aRoot, aPath) {
|
|
||||||
aRoot = aRoot.replace(/\/$/, '');
|
|
||||||
return aPath.indexOf(aRoot + '/') === 0
|
|
||||||
? aPath.substr(aRoot.length + 1)
|
|
||||||
: aPath;
|
|
||||||
}
|
|
||||||
exports.relative = relative;
|
|
||||||
|
|
||||||
});
|
});
|
||||||
/* -*- Mode: js; js-indent-level: 2; -*- */
|
/* -*- Mode: js; js-indent-level: 2; -*- */
|
||||||
/*
|
/*
|
||||||
|
@ -589,9 +515,7 @@ define('source-map/binary-search', ['require', 'exports', 'module' , ], function
|
||||||
* Licensed under the New BSD license. See LICENSE or:
|
* Licensed under the New BSD license. See LICENSE or:
|
||||||
* http://opensource.org/licenses/BSD-3-Clause
|
* http://opensource.org/licenses/BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
define('source-map/array-set', ['require', 'exports', 'module' , 'source-map/util'], function(require, exports, module) {
|
define('source-map/array-set', ['require', 'exports', 'module' , ], function(require, exports, module) {
|
||||||
|
|
||||||
var util = require('source-map/util');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A data structure which is a combination of an array and a set. Adding a new
|
* A data structure which is a combination of an array and a set. Adding a new
|
||||||
|
@ -615,6 +539,19 @@ define('source-map/array-set', ['require', 'exports', 'module' , 'source-map/ut
|
||||||
return set;
|
return set;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Because behavior goes wacky when you set `__proto__` on `this._set`, we
|
||||||
|
* have to prefix all the strings in our set with an arbitrary character.
|
||||||
|
*
|
||||||
|
* See https://github.com/mozilla/source-map/pull/31 and
|
||||||
|
* https://github.com/mozilla/source-map/issues/30
|
||||||
|
*
|
||||||
|
* @param String aStr
|
||||||
|
*/
|
||||||
|
ArraySet.prototype._toSetString = function ArraySet__toSetString (aStr) {
|
||||||
|
return "$" + aStr;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the given string to this set.
|
* Add the given string to this set.
|
||||||
*
|
*
|
||||||
|
@ -627,7 +564,7 @@ define('source-map/array-set', ['require', 'exports', 'module' , 'source-map/ut
|
||||||
}
|
}
|
||||||
var idx = this._array.length;
|
var idx = this._array.length;
|
||||||
this._array.push(aStr);
|
this._array.push(aStr);
|
||||||
this._set[util.toSetString(aStr)] = idx;
|
this._set[this._toSetString(aStr)] = idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -637,7 +574,7 @@ define('source-map/array-set', ['require', 'exports', 'module' , 'source-map/ut
|
||||||
*/
|
*/
|
||||||
ArraySet.prototype.has = function ArraySet_has(aStr) {
|
ArraySet.prototype.has = function ArraySet_has(aStr) {
|
||||||
return Object.prototype.hasOwnProperty.call(this._set,
|
return Object.prototype.hasOwnProperty.call(this._set,
|
||||||
util.toSetString(aStr));
|
this._toSetString(aStr));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -647,7 +584,7 @@ define('source-map/array-set', ['require', 'exports', 'module' , 'source-map/ut
|
||||||
*/
|
*/
|
||||||
ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
|
ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
|
||||||
if (this.has(aStr)) {
|
if (this.has(aStr)) {
|
||||||
return this._set[util.toSetString(aStr)];
|
return this._set[this._toSetString(aStr)];
|
||||||
}
|
}
|
||||||
throw new Error('"' + aStr + '" is not in the set.');
|
throw new Error('"' + aStr + '" is not in the set.');
|
||||||
};
|
};
|
||||||
|
@ -882,58 +819,10 @@ define('source-map/source-map-generator', ['require', 'exports', 'module' , 'so
|
||||||
this._sources = new ArraySet();
|
this._sources = new ArraySet();
|
||||||
this._names = new ArraySet();
|
this._names = new ArraySet();
|
||||||
this._mappings = [];
|
this._mappings = [];
|
||||||
this._sourcesContents = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceMapGenerator.prototype._version = 3;
|
SourceMapGenerator.prototype._version = 3;
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new SourceMapGenerator based on a SourceMapConsumer
|
|
||||||
*
|
|
||||||
* @param aSourceMapConsumer The SourceMap.
|
|
||||||
*/
|
|
||||||
SourceMapGenerator.fromSourceMap =
|
|
||||||
function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
|
|
||||||
var sourceRoot = aSourceMapConsumer.sourceRoot;
|
|
||||||
var generator = new SourceMapGenerator({
|
|
||||||
file: aSourceMapConsumer.file,
|
|
||||||
sourceRoot: sourceRoot
|
|
||||||
});
|
|
||||||
aSourceMapConsumer.eachMapping(function (mapping) {
|
|
||||||
var newMapping = {
|
|
||||||
generated: {
|
|
||||||
line: mapping.generatedLine,
|
|
||||||
column: mapping.generatedColumn
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (mapping.source) {
|
|
||||||
newMapping.source = mapping.source;
|
|
||||||
if (sourceRoot) {
|
|
||||||
newMapping.source = util.relative(sourceRoot, newMapping.source);
|
|
||||||
}
|
|
||||||
|
|
||||||
newMapping.original = {
|
|
||||||
line: mapping.originalLine,
|
|
||||||
column: mapping.originalColumn
|
|
||||||
};
|
|
||||||
|
|
||||||
if (mapping.name) {
|
|
||||||
newMapping.name = mapping.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generator.addMapping(newMapping);
|
|
||||||
});
|
|
||||||
aSourceMapConsumer.sources.forEach(function (sourceFile) {
|
|
||||||
var content = aSourceMapConsumer.sourceContentFor(sourceFile);
|
|
||||||
if (content) {
|
|
||||||
generator.setSourceContent(sourceFile, content);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return generator;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a single mapping from original source line and column to the generated
|
* Add a single mapping from original source line and column to the generated
|
||||||
* source's line and column for this source map being created. The mapping
|
* source's line and column for this source map being created. The mapping
|
||||||
|
@ -969,110 +858,6 @@ define('source-map/source-map-generator', ['require', 'exports', 'module' , 'so
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the source content for a source file.
|
|
||||||
*/
|
|
||||||
SourceMapGenerator.prototype.setSourceContent =
|
|
||||||
function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
|
|
||||||
var source = aSourceFile;
|
|
||||||
if (this._sourceRoot) {
|
|
||||||
source = util.relative(this._sourceRoot, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aSourceContent !== null) {
|
|
||||||
// Add the source content to the _sourcesContents map.
|
|
||||||
// Create a new _sourcesContents map if the property is null.
|
|
||||||
if (!this._sourcesContents) {
|
|
||||||
this._sourcesContents = {};
|
|
||||||
}
|
|
||||||
this._sourcesContents[util.toSetString(source)] = aSourceContent;
|
|
||||||
} else {
|
|
||||||
// Remove the source file from the _sourcesContents map.
|
|
||||||
// If the _sourcesContents map is empty, set the property to null.
|
|
||||||
delete this._sourcesContents[util.toSetString(source)];
|
|
||||||
if (Object.keys(this._sourcesContents).length === 0) {
|
|
||||||
this._sourcesContents = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies the mappings of a sub-source-map for a specific source file to the
|
|
||||||
* source map being generated. Each mapping to the supplied source file is
|
|
||||||
* rewritten using the supplied source map. Note: The resolution for the
|
|
||||||
* resulting mappings is the minimium of this map and the supplied map.
|
|
||||||
*
|
|
||||||
* @param aSourceMapConsumer The source map to be applied.
|
|
||||||
* @param aSourceFile Optional. The filename of the source file.
|
|
||||||
* If omitted, SourceMapConsumer's file property will be used.
|
|
||||||
*/
|
|
||||||
SourceMapGenerator.prototype.applySourceMap =
|
|
||||||
function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) {
|
|
||||||
// If aSourceFile is omitted, we will use the file property of the SourceMap
|
|
||||||
if (!aSourceFile) {
|
|
||||||
aSourceFile = aSourceMapConsumer.file;
|
|
||||||
}
|
|
||||||
var sourceRoot = this._sourceRoot;
|
|
||||||
// Make "aSourceFile" relative if an absolute Url is passed.
|
|
||||||
if (sourceRoot) {
|
|
||||||
aSourceFile = util.relative(sourceRoot, aSourceFile);
|
|
||||||
}
|
|
||||||
// Applying the SourceMap can add and remove items from the sources and
|
|
||||||
// the names array.
|
|
||||||
var newSources = new ArraySet();
|
|
||||||
var newNames = new ArraySet();
|
|
||||||
|
|
||||||
// Find mappings for the "aSourceFile"
|
|
||||||
this._mappings.forEach(function (mapping) {
|
|
||||||
if (mapping.source === aSourceFile && mapping.original) {
|
|
||||||
// Check if it can be mapped by the source map, then update the mapping.
|
|
||||||
var original = aSourceMapConsumer.originalPositionFor({
|
|
||||||
line: mapping.original.line,
|
|
||||||
column: mapping.original.column
|
|
||||||
});
|
|
||||||
if (original.source !== null) {
|
|
||||||
// Copy mapping
|
|
||||||
if (sourceRoot) {
|
|
||||||
mapping.source = util.relative(sourceRoot, original.source);
|
|
||||||
} else {
|
|
||||||
mapping.source = original.source;
|
|
||||||
}
|
|
||||||
mapping.original.line = original.line;
|
|
||||||
mapping.original.column = original.column;
|
|
||||||
if (original.name !== null && mapping.name !== null) {
|
|
||||||
// Only use the identifier name if it's an identifier
|
|
||||||
// in both SourceMaps
|
|
||||||
mapping.name = original.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var source = mapping.source;
|
|
||||||
if (source && !newSources.has(source)) {
|
|
||||||
newSources.add(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
var name = mapping.name;
|
|
||||||
if (name && !newNames.has(name)) {
|
|
||||||
newNames.add(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
}, this);
|
|
||||||
this._sources = newSources;
|
|
||||||
this._names = newNames;
|
|
||||||
|
|
||||||
// Copy sourcesContents of applied map.
|
|
||||||
aSourceMapConsumer.sources.forEach(function (sourceFile) {
|
|
||||||
var content = aSourceMapConsumer.sourceContentFor(sourceFile);
|
|
||||||
if (content) {
|
|
||||||
if (sourceRoot) {
|
|
||||||
sourceFile = util.relative(sourceRoot, sourceFile);
|
|
||||||
}
|
|
||||||
this.setSourceContent(sourceFile, content);
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mapping can have one of the three levels of data:
|
* A mapping can have one of the three levels of data:
|
||||||
*
|
*
|
||||||
|
@ -1193,17 +978,6 @@ define('source-map/source-map-generator', ['require', 'exports', 'module' , 'so
|
||||||
if (this._sourceRoot) {
|
if (this._sourceRoot) {
|
||||||
map.sourceRoot = this._sourceRoot;
|
map.sourceRoot = this._sourceRoot;
|
||||||
}
|
}
|
||||||
if (this._sourcesContents) {
|
|
||||||
map.sourcesContent = map.sources.map(function (source) {
|
|
||||||
if (map.sourceRoot) {
|
|
||||||
source = util.relative(map.sourceRoot, source);
|
|
||||||
}
|
|
||||||
return Object.prototype.hasOwnProperty.call(
|
|
||||||
this._sourcesContents, util.toSetString(source))
|
|
||||||
? this._sourcesContents[util.toSetString(source)]
|
|
||||||
: null;
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
return map;
|
return map;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1224,10 +998,9 @@ define('source-map/source-map-generator', ['require', 'exports', 'module' , 'so
|
||||||
* Licensed under the New BSD license. See LICENSE or:
|
* Licensed under the New BSD license. See LICENSE or:
|
||||||
* http://opensource.org/licenses/BSD-3-Clause
|
* http://opensource.org/licenses/BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/source-map-generator', 'source-map/util'], function(require, exports, module) {
|
define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/source-map-generator'], function(require, exports, module) {
|
||||||
|
|
||||||
var SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator;
|
var SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator;
|
||||||
var util = require('source-map/util');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SourceNodes provide a way to abstract over interpolating/concatenating
|
* SourceNodes provide a way to abstract over interpolating/concatenating
|
||||||
|
@ -1239,121 +1012,15 @@ define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/
|
||||||
* @param aSource The original source's filename.
|
* @param aSource The original source's filename.
|
||||||
* @param aChunks Optional. An array of strings which are snippets of
|
* @param aChunks Optional. An array of strings which are snippets of
|
||||||
* generated JS, or other SourceNodes.
|
* generated JS, or other SourceNodes.
|
||||||
* @param aName The original identifier.
|
|
||||||
*/
|
*/
|
||||||
function SourceNode(aLine, aColumn, aSource, aChunks, aName) {
|
function SourceNode(aLine, aColumn, aSource, aChunks) {
|
||||||
this.children = [];
|
this.children = [];
|
||||||
this.sourceContents = {};
|
this.line = aLine;
|
||||||
this.line = aLine === undefined ? null : aLine;
|
this.column = aColumn;
|
||||||
this.column = aColumn === undefined ? null : aColumn;
|
this.source = aSource;
|
||||||
this.source = aSource === undefined ? null : aSource;
|
|
||||||
this.name = aName === undefined ? null : aName;
|
|
||||||
if (aChunks != null) this.add(aChunks);
|
if (aChunks != null) this.add(aChunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a SourceNode from generated code and a SourceMapConsumer.
|
|
||||||
*
|
|
||||||
* @param aGeneratedCode The generated code
|
|
||||||
* @param aSourceMapConsumer The SourceMap for the generated code
|
|
||||||
*/
|
|
||||||
SourceNode.fromStringWithSourceMap =
|
|
||||||
function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) {
|
|
||||||
// The SourceNode we want to fill with the generated code
|
|
||||||
// and the SourceMap
|
|
||||||
var node = new SourceNode();
|
|
||||||
|
|
||||||
// The generated code
|
|
||||||
// Processed fragments are removed from this array.
|
|
||||||
var remainingLines = aGeneratedCode.split('\n');
|
|
||||||
|
|
||||||
// We need to remember the position of "remainingLines"
|
|
||||||
var lastGeneratedLine = 1, lastGeneratedColumn = 0;
|
|
||||||
|
|
||||||
// The generate SourceNodes we need a code range.
|
|
||||||
// To extract it current and last mapping is used.
|
|
||||||
// Here we store the last mapping.
|
|
||||||
var lastMapping = null;
|
|
||||||
|
|
||||||
aSourceMapConsumer.eachMapping(function (mapping) {
|
|
||||||
if (lastMapping === null) {
|
|
||||||
// We add the generated code until the first mapping
|
|
||||||
// to the SourceNode without any mapping.
|
|
||||||
// Each line is added as separate string.
|
|
||||||
while (lastGeneratedLine < mapping.generatedLine) {
|
|
||||||
node.add(remainingLines.shift() + "\n");
|
|
||||||
lastGeneratedLine++;
|
|
||||||
}
|
|
||||||
if (lastGeneratedColumn < mapping.generatedColumn) {
|
|
||||||
var nextLine = remainingLines[0];
|
|
||||||
node.add(nextLine.substr(0, mapping.generatedColumn));
|
|
||||||
remainingLines[0] = nextLine.substr(mapping.generatedColumn);
|
|
||||||
lastGeneratedColumn = mapping.generatedColumn;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We add the code from "lastMapping" to "mapping":
|
|
||||||
// First check if there is a new line in between.
|
|
||||||
if (lastGeneratedLine < mapping.generatedLine) {
|
|
||||||
var code = "";
|
|
||||||
// Associate full lines with "lastMapping"
|
|
||||||
do {
|
|
||||||
code += remainingLines.shift() + "\n";
|
|
||||||
lastGeneratedLine++;
|
|
||||||
lastGeneratedColumn = 0;
|
|
||||||
} while (lastGeneratedLine < mapping.generatedLine);
|
|
||||||
// When we reached the correct line, we add code until we
|
|
||||||
// reach the correct column too.
|
|
||||||
if (lastGeneratedColumn < mapping.generatedColumn) {
|
|
||||||
var nextLine = remainingLines[0];
|
|
||||||
code += nextLine.substr(0, mapping.generatedColumn);
|
|
||||||
remainingLines[0] = nextLine.substr(mapping.generatedColumn);
|
|
||||||
lastGeneratedColumn = mapping.generatedColumn;
|
|
||||||
}
|
|
||||||
// Create the SourceNode.
|
|
||||||
addMappingWithCode(lastMapping, code);
|
|
||||||
} else {
|
|
||||||
// There is no new line in between.
|
|
||||||
// Associate the code between "lastGeneratedColumn" and
|
|
||||||
// "mapping.generatedColumn" with "lastMapping"
|
|
||||||
var nextLine = remainingLines[0];
|
|
||||||
var code = nextLine.substr(0, mapping.generatedColumn -
|
|
||||||
lastGeneratedColumn);
|
|
||||||
remainingLines[0] = nextLine.substr(mapping.generatedColumn -
|
|
||||||
lastGeneratedColumn);
|
|
||||||
lastGeneratedColumn = mapping.generatedColumn;
|
|
||||||
addMappingWithCode(lastMapping, code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastMapping = mapping;
|
|
||||||
}, this);
|
|
||||||
// We have processed all mappings.
|
|
||||||
// Associate the remaining code in the current line with "lastMapping"
|
|
||||||
// and add the remaining lines without any mapping
|
|
||||||
addMappingWithCode(lastMapping, remainingLines.join("\n"));
|
|
||||||
|
|
||||||
// Copy sourcesContent into SourceNode
|
|
||||||
aSourceMapConsumer.sources.forEach(function (sourceFile) {
|
|
||||||
var content = aSourceMapConsumer.sourceContentFor(sourceFile);
|
|
||||||
if (content) {
|
|
||||||
node.setSourceContent(sourceFile, content);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return node;
|
|
||||||
|
|
||||||
function addMappingWithCode(mapping, code) {
|
|
||||||
if (mapping.source === undefined) {
|
|
||||||
node.add(code);
|
|
||||||
} else {
|
|
||||||
node.add(new SourceNode(mapping.originalLine,
|
|
||||||
mapping.originalColumn,
|
|
||||||
mapping.source,
|
|
||||||
code,
|
|
||||||
mapping.name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a chunk of generated JS to this source node.
|
* Add a chunk of generated JS to this source node.
|
||||||
*
|
*
|
||||||
|
@ -1416,10 +1083,7 @@ define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (chunk !== '') {
|
if (chunk !== '') {
|
||||||
aFn(chunk, { source: this.source,
|
aFn(chunk, { source: this.source, line: this.line, column: this.column });
|
||||||
line: this.line,
|
|
||||||
column: this.column,
|
|
||||||
name: this.name });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
|
@ -1434,7 +1098,7 @@ define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/
|
||||||
SourceNode.prototype.join = function SourceNode_join(aSep) {
|
SourceNode.prototype.join = function SourceNode_join(aSep) {
|
||||||
var newChildren;
|
var newChildren;
|
||||||
var i;
|
var i;
|
||||||
var len = this.children.length;
|
var len = this.children.length
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
newChildren = [];
|
newChildren = [];
|
||||||
for (i = 0; i < len-1; i++) {
|
for (i = 0; i < len-1; i++) {
|
||||||
|
@ -1468,36 +1132,6 @@ define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the source content for a source file. This will be added to the SourceMapGenerator
|
|
||||||
* in the sourcesContent field.
|
|
||||||
*
|
|
||||||
* @param aSourceFile The filename of the source file
|
|
||||||
* @param aSourceContent The content of the source file
|
|
||||||
*/
|
|
||||||
SourceNode.prototype.setSourceContent =
|
|
||||||
function SourceNode_setSourceContent(aSourceFile, aSourceContent) {
|
|
||||||
this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Walk over the tree of SourceNodes. The walking function is called for each
|
|
||||||
* source file content and is passed the filename and source content.
|
|
||||||
*
|
|
||||||
* @param aFn The traversal function.
|
|
||||||
*/
|
|
||||||
SourceNode.prototype.walkSourceContents =
|
|
||||||
function SourceNode_walkSourceContents(aFn) {
|
|
||||||
this.children.forEach(function (chunk) {
|
|
||||||
if (chunk instanceof SourceNode) {
|
|
||||||
chunk.walkSourceContents(aFn);
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
Object.keys(this.sourceContents).forEach(function (sourceFileKey) {
|
|
||||||
aFn(util.fromSetString(sourceFileKey), this.sourceContents[sourceFileKey]);
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the string representation of this source node. Walks over the tree
|
* Return the string representation of this source node. Walks over the tree
|
||||||
* and concatenates all the various snippets together to one string.
|
* and concatenates all the various snippets together to one string.
|
||||||
|
@ -1521,36 +1155,25 @@ define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/
|
||||||
column: 0
|
column: 0
|
||||||
};
|
};
|
||||||
var map = new SourceMapGenerator(aArgs);
|
var map = new SourceMapGenerator(aArgs);
|
||||||
var sourceMappingActive = false;
|
|
||||||
this.walk(function (chunk, original) {
|
this.walk(function (chunk, original) {
|
||||||
generated.code += chunk;
|
generated.code += chunk;
|
||||||
if (original.source !== null
|
if (original.source != null
|
||||||
&& original.line !== null
|
&& original.line != null
|
||||||
&& original.column !== null) {
|
&& original.column != null) {
|
||||||
map.addMapping({
|
map.addMapping({
|
||||||
source: original.source,
|
source: original.source,
|
||||||
original: {
|
original: {
|
||||||
line: original.line,
|
line: original.line,
|
||||||
column: original.column
|
column: original.column
|
||||||
},
|
},
|
||||||
generated: {
|
|
||||||
line: generated.line,
|
|
||||||
column: generated.column
|
|
||||||
},
|
|
||||||
name: original.name
|
|
||||||
});
|
|
||||||
sourceMappingActive = true;
|
|
||||||
} else if (sourceMappingActive) {
|
|
||||||
map.addMapping({
|
|
||||||
generated: {
|
generated: {
|
||||||
line: generated.line,
|
line: generated.line,
|
||||||
column: generated.column
|
column: generated.column
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
sourceMappingActive = false;
|
|
||||||
}
|
}
|
||||||
chunk.split('').forEach(function (ch) {
|
chunk.split('').forEach(function (char) {
|
||||||
if (ch === '\n') {
|
if (char === '\n') {
|
||||||
generated.line++;
|
generated.line++;
|
||||||
generated.column = 0;
|
generated.column = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1558,9 +1181,6 @@ define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.walkSourceContents(function (sourceFile, sourceContent) {
|
|
||||||
map.setSourceContent(sourceFile, sourceContent);
|
|
||||||
});
|
|
||||||
|
|
||||||
return { code: generated.code, map: map };
|
return { code: generated.code, map: map };
|
||||||
};
|
};
|
||||||
|
@ -1571,6 +1191,6 @@ define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/
|
||||||
/* -*- Mode: js; js-indent-level: 2; -*- */
|
/* -*- Mode: js; js-indent-level: 2; -*- */
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
this.SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer;
|
let SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer;
|
||||||
this.SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator;
|
let SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator;
|
||||||
this.SourceNode = require('source-map/source-node').SourceNode;
|
let SourceNode = require('source-map/source-node').SourceNode;
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
Components.utils.import('resource://gre/modules/devtools/Require.jsm');
|
Components.utils.import('resource://gre/modules/devtools/Require.jsm');
|
||||||
Components.utils.import('resource://gre/modules/devtools/SourceMap.jsm');
|
Components.utils.import('resource://gre/modules/devtools/SourceMap.jsm');
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = [ "define", "runSourceMapTests" ];
|
let EXPORTED_SYMBOLS = [ "define", "runSourceMapTests" ];
|
||||||
/* -*- Mode: js; js-indent-level: 2; -*- */
|
/* -*- Mode: js; js-indent-level: 2; -*- */
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Mozilla Foundation and contributors
|
* Copyright 2011 Mozilla Foundation and contributors
|
||||||
|
@ -78,9 +78,7 @@ define('test/source-map/assert', ['exports'], function (exports) {
|
||||||
* Licensed under the New BSD license. See LICENSE or:
|
* Licensed under the New BSD license. See LICENSE or:
|
||||||
* http://opensource.org/licenses/BSD-3-Clause
|
* http://opensource.org/licenses/BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
define('test/source-map/util', ['require', 'exports', 'module' , 'lib/source-map/util'], function(require, exports, module) {
|
define('test/source-map/util', ['require', 'exports', 'module' , ], function(require, exports, module) {
|
||||||
|
|
||||||
var util = require('source-map/util');
|
|
||||||
|
|
||||||
// This is a test mapping which maps functions from two different files
|
// This is a test mapping which maps functions from two different files
|
||||||
// (one.js and two.js) to a minified generated source.
|
// (one.js and two.js) to a minified generated source.
|
||||||
|
@ -101,8 +99,6 @@ define('test/source-map/util', ['require', 'exports', 'module' , 'lib/source-ma
|
||||||
//
|
//
|
||||||
// ONE.foo=function(a){return baz(a);};
|
// ONE.foo=function(a){return baz(a);};
|
||||||
// TWO.inc=function(a){return a+1;};
|
// TWO.inc=function(a){return a+1;};
|
||||||
exports.testGeneratedCode = " ONE.foo=function(a){return baz(a);};\n"+
|
|
||||||
" TWO.inc=function(a){return a+1;};";
|
|
||||||
exports.testMap = {
|
exports.testMap = {
|
||||||
version: 3,
|
version: 3,
|
||||||
file: 'min.js',
|
file: 'min.js',
|
||||||
|
@ -111,22 +107,6 @@ define('test/source-map/util', ['require', 'exports', 'module' , 'lib/source-ma
|
||||||
sourceRoot: '/the/root',
|
sourceRoot: '/the/root',
|
||||||
mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA'
|
mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA'
|
||||||
};
|
};
|
||||||
exports.testMapWithSourcesContent = {
|
|
||||||
version: 3,
|
|
||||||
file: 'min.js',
|
|
||||||
names: ['bar', 'baz', 'n'],
|
|
||||||
sources: ['one.js', 'two.js'],
|
|
||||||
sourcesContent: [
|
|
||||||
' ONE.foo = function (bar) {\n' +
|
|
||||||
' return baz(bar);\n' +
|
|
||||||
' };',
|
|
||||||
' TWO.inc = function (n) {\n' +
|
|
||||||
' return n + 1;\n' +
|
|
||||||
' };'
|
|
||||||
],
|
|
||||||
sourceRoot: '/the/root',
|
|
||||||
mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA'
|
|
||||||
};
|
|
||||||
|
|
||||||
function assertMapping(generatedLine, generatedColumn, originalSource,
|
function assertMapping(generatedLine, generatedColumn, originalSource,
|
||||||
originalLine, originalColumn, name, map, assert,
|
originalLine, originalColumn, name, map, assert,
|
||||||
|
@ -145,8 +125,7 @@ define('test/source-map/util', ['require', 'exports', 'module' , 'lib/source-ma
|
||||||
assert.equal(origMapping.column, originalColumn,
|
assert.equal(origMapping.column, originalColumn,
|
||||||
'Incorrect column, expected ' + JSON.stringify(originalColumn)
|
'Incorrect column, expected ' + JSON.stringify(originalColumn)
|
||||||
+ ', got ' + JSON.stringify(origMapping.column));
|
+ ', got ' + JSON.stringify(origMapping.column));
|
||||||
assert.equal(origMapping.source,
|
assert.equal(origMapping.source, originalSource,
|
||||||
originalSource ? util.join(map._sourceRoot, originalSource) : null,
|
|
||||||
'Incorrect source, expected ' + JSON.stringify(originalSource)
|
'Incorrect source, expected ' + JSON.stringify(originalSource)
|
||||||
+ ', got ' + JSON.stringify(origMapping.source));
|
+ ', got ' + JSON.stringify(origMapping.source));
|
||||||
}
|
}
|
||||||
|
@ -167,111 +146,6 @@ define('test/source-map/util', ['require', 'exports', 'module' , 'lib/source-ma
|
||||||
}
|
}
|
||||||
exports.assertMapping = assertMapping;
|
exports.assertMapping = assertMapping;
|
||||||
|
|
||||||
function assertEqualMaps(assert, actualMap, expectedMap) {
|
|
||||||
assert.equal(actualMap.version, expectedMap.version, "version mismatch");
|
|
||||||
assert.equal(actualMap.file, expectedMap.file, "file mismatch");
|
|
||||||
assert.equal(actualMap.names.length,
|
|
||||||
expectedMap.names.length,
|
|
||||||
"names length mismatch: " +
|
|
||||||
actualMap.names.join(", ") + " != " + expectedMap.names.join(", "));
|
|
||||||
for (var i = 0; i < actualMap.names.length; i++) {
|
|
||||||
assert.equal(actualMap.names[i],
|
|
||||||
expectedMap.names[i],
|
|
||||||
"names[" + i + "] mismatch: " +
|
|
||||||
actualMap.names.join(", ") + " != " + expectedMap.names.join(", "));
|
|
||||||
}
|
|
||||||
assert.equal(actualMap.sources.length,
|
|
||||||
expectedMap.sources.length,
|
|
||||||
"sources length mismatch: " +
|
|
||||||
actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", "));
|
|
||||||
for (var i = 0; i < actualMap.sources.length; i++) {
|
|
||||||
assert.equal(actualMap.sources[i],
|
|
||||||
expectedMap.sources[i],
|
|
||||||
"sources[" + i + "] length mismatch: " +
|
|
||||||
actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", "));
|
|
||||||
}
|
|
||||||
assert.equal(actualMap.sourceRoot,
|
|
||||||
expectedMap.sourceRoot,
|
|
||||||
"sourceRoot mismatch: " +
|
|
||||||
actualMap.sourceRoot + " != " + expectedMap.sourceRoot);
|
|
||||||
assert.equal(actualMap.mappings, expectedMap.mappings, "mappings mismatch");
|
|
||||||
if (actualMap.sourcesContent) {
|
|
||||||
assert.equal(actualMap.sourcesContent.length,
|
|
||||||
expectedMap.sourcesContent.length,
|
|
||||||
"sourcesContent length mismatch");
|
|
||||||
for (var i = 0; i < actualMap.sourcesContent.length; i++) {
|
|
||||||
assert.equal(actualMap.sourcesContent[i],
|
|
||||||
expectedMap.sourcesContent[i],
|
|
||||||
"sourcesContent[" + i + "] mismatch");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.assertEqualMaps = assertEqualMaps;
|
|
||||||
|
|
||||||
});
|
|
||||||
/* -*- Mode: js; js-indent-level: 2; -*- */
|
|
||||||
/*
|
|
||||||
* Copyright 2011 Mozilla Foundation and contributors
|
|
||||||
* Licensed under the New BSD license. See LICENSE or:
|
|
||||||
* http://opensource.org/licenses/BSD-3-Clause
|
|
||||||
*/
|
|
||||||
define('lib/source-map/util', ['require', 'exports', 'module' , ], function(require, exports, module) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a helper function for getting values from parameter/options
|
|
||||||
* objects.
|
|
||||||
*
|
|
||||||
* @param args The object we are extracting values from
|
|
||||||
* @param name The name of the property we are getting.
|
|
||||||
* @param defaultValue An optional value to return if the property is missing
|
|
||||||
* from the object. If this is not specified and the property is missing, an
|
|
||||||
* error will be thrown.
|
|
||||||
*/
|
|
||||||
function getArg(aArgs, aName, aDefaultValue) {
|
|
||||||
if (aName in aArgs) {
|
|
||||||
return aArgs[aName];
|
|
||||||
} else if (arguments.length === 3) {
|
|
||||||
return aDefaultValue;
|
|
||||||
} else {
|
|
||||||
throw new Error('"' + aName + '" is a required argument.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.getArg = getArg;
|
|
||||||
|
|
||||||
function join(aRoot, aPath) {
|
|
||||||
return aPath.charAt(0) === '/'
|
|
||||||
? aPath
|
|
||||||
: aRoot.replace(/\/$/, '') + '/' + aPath;
|
|
||||||
}
|
|
||||||
exports.join = join;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Because behavior goes wacky when you set `__proto__` on objects, we
|
|
||||||
* have to prefix all the strings in our set with an arbitrary character.
|
|
||||||
*
|
|
||||||
* See https://github.com/mozilla/source-map/pull/31 and
|
|
||||||
* https://github.com/mozilla/source-map/issues/30
|
|
||||||
*
|
|
||||||
* @param String aStr
|
|
||||||
*/
|
|
||||||
function toSetString(aStr) {
|
|
||||||
return '$' + aStr;
|
|
||||||
}
|
|
||||||
exports.toSetString = toSetString;
|
|
||||||
|
|
||||||
function fromSetString(aStr) {
|
|
||||||
return aStr.substr(1);
|
|
||||||
}
|
|
||||||
exports.fromSetString = fromSetString;
|
|
||||||
|
|
||||||
function relative(aRoot, aPath) {
|
|
||||||
aRoot = aRoot.replace(/\/$/, '');
|
|
||||||
return aPath.indexOf(aRoot + '/') === 0
|
|
||||||
? aPath.substr(aRoot.length + 1)
|
|
||||||
: aPath;
|
|
||||||
}
|
|
||||||
exports.relative = relative;
|
|
||||||
|
|
||||||
});
|
});
|
||||||
/* -*- Mode: js; js-indent-level: 2; -*- */
|
/* -*- Mode: js; js-indent-level: 2; -*- */
|
||||||
/*
|
/*
|
||||||
|
@ -293,4 +167,3 @@ function runSourceMapTests(modName, do_throw) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
this.runSourceMapTests = runSourceMapTests;
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ Components.utils.import('resource://test/Utils.jsm');
|
||||||
define("test/source-map/test-source-map-consumer", ["require", "exports", "module"], function (require, exports, module) {
|
define("test/source-map/test-source-map-consumer", ["require", "exports", "module"], function (require, exports, module) {
|
||||||
|
|
||||||
var SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer;
|
var SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer;
|
||||||
var SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator;
|
|
||||||
|
|
||||||
exports['test that we can instantiate with a string or an objects'] = function (assert, util) {
|
exports['test that we can instantiate with a string or an objects'] = function (assert, util) {
|
||||||
assert.doesNotThrow(function () {
|
assert.doesNotThrow(function () {
|
||||||
|
@ -98,10 +97,6 @@ define("test/source-map/test-source-map-consumer", ["require", "exports", "modul
|
||||||
map.eachMapping(function (mapping) {
|
map.eachMapping(function (mapping) {
|
||||||
assert.ok(mapping.generatedLine >= previousLine);
|
assert.ok(mapping.generatedLine >= previousLine);
|
||||||
|
|
||||||
if (mapping.source) {
|
|
||||||
assert.equal(mapping.source.indexOf(util.testMap.sourceRoot), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mapping.generatedLine === previousLine) {
|
if (mapping.generatedLine === previousLine) {
|
||||||
assert.ok(mapping.generatedColumn >= previousColumn);
|
assert.ok(mapping.generatedColumn >= previousColumn);
|
||||||
previousColumn = mapping.generatedColumn;
|
previousColumn = mapping.generatedColumn;
|
||||||
|
@ -149,112 +144,6 @@ define("test/source-map/test-source-map-consumer", ["require", "exports", "modul
|
||||||
}, context);
|
}, context);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports['test that the `sourcesContent` field has the original sources'] = function (assert, util) {
|
|
||||||
var map = new SourceMapConsumer(util.testMapWithSourcesContent);
|
|
||||||
var sourcesContent = map.sourcesContent;
|
|
||||||
|
|
||||||
assert.equal(sourcesContent[0], ' ONE.foo = function (bar) {\n return baz(bar);\n };');
|
|
||||||
assert.equal(sourcesContent[1], ' TWO.inc = function (n) {\n return n + 1;\n };');
|
|
||||||
assert.equal(sourcesContent.length, 2);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports['test that we can get the original sources for the sources'] = function (assert, util) {
|
|
||||||
var map = new SourceMapConsumer(util.testMapWithSourcesContent);
|
|
||||||
var sources = map.sources;
|
|
||||||
|
|
||||||
assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };');
|
|
||||||
assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };');
|
|
||||||
assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };');
|
|
||||||
assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };');
|
|
||||||
assert.throws(function () {
|
|
||||||
map.sourceContentFor("");
|
|
||||||
}, Error);
|
|
||||||
assert.throws(function () {
|
|
||||||
map.sourceContentFor("/the/root/three.js");
|
|
||||||
}, Error);
|
|
||||||
assert.throws(function () {
|
|
||||||
map.sourceContentFor("three.js");
|
|
||||||
}, Error);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports['test sourceRoot + generatedPositionFor'] = function (assert, util) {
|
|
||||||
var map = new SourceMapGenerator({
|
|
||||||
sourceRoot: 'foo/bar',
|
|
||||||
file: 'baz.js'
|
|
||||||
});
|
|
||||||
map.addMapping({
|
|
||||||
original: { line: 1, column: 1 },
|
|
||||||
generated: { line: 2, column: 2 },
|
|
||||||
source: 'bang.coffee'
|
|
||||||
});
|
|
||||||
map.addMapping({
|
|
||||||
original: { line: 5, column: 5 },
|
|
||||||
generated: { line: 6, column: 6 },
|
|
||||||
source: 'bang.coffee'
|
|
||||||
});
|
|
||||||
map = new SourceMapConsumer(map.toString());
|
|
||||||
|
|
||||||
// Should handle without sourceRoot.
|
|
||||||
var pos = map.generatedPositionFor({
|
|
||||||
line: 1,
|
|
||||||
column: 1,
|
|
||||||
source: 'bang.coffee'
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.equal(pos.line, 2);
|
|
||||||
assert.equal(pos.column, 2);
|
|
||||||
|
|
||||||
// Should handle with sourceRoot.
|
|
||||||
var pos = map.generatedPositionFor({
|
|
||||||
line: 1,
|
|
||||||
column: 1,
|
|
||||||
source: 'foo/bar/bang.coffee'
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.equal(pos.line, 2);
|
|
||||||
assert.equal(pos.column, 2);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports['test sourceRoot + originalPositionFor'] = function (assert, util) {
|
|
||||||
var map = new SourceMapGenerator({
|
|
||||||
sourceRoot: 'foo/bar',
|
|
||||||
file: 'baz.js'
|
|
||||||
});
|
|
||||||
map.addMapping({
|
|
||||||
original: { line: 1, column: 1 },
|
|
||||||
generated: { line: 2, column: 2 },
|
|
||||||
source: 'bang.coffee'
|
|
||||||
});
|
|
||||||
map = new SourceMapConsumer(map.toString());
|
|
||||||
|
|
||||||
var pos = map.originalPositionFor({
|
|
||||||
line: 2,
|
|
||||||
column: 2,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Should always have the prepended source root
|
|
||||||
assert.equal(pos.source, 'foo/bar/bang.coffee');
|
|
||||||
assert.equal(pos.line, 1);
|
|
||||||
assert.equal(pos.column, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports['test github issue #56'] = function (assert, util) {
|
|
||||||
var map = new SourceMapGenerator({
|
|
||||||
sourceRoot: 'http://',
|
|
||||||
file: 'www.example.com/foo.js'
|
|
||||||
});
|
|
||||||
map.addMapping({
|
|
||||||
original: { line: 1, column: 1 },
|
|
||||||
generated: { line: 2, column: 2 },
|
|
||||||
source: 'www.example.com/original.js'
|
|
||||||
});
|
|
||||||
map = new SourceMapConsumer(map.toString());
|
|
||||||
|
|
||||||
var sources = map.sources;
|
|
||||||
assert.equal(map.sources.length, 1);
|
|
||||||
assert.equal(map.sources[0], 'http://www.example.com/original.js');
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
});
|
||||||
function run_test() {
|
function run_test() {
|
||||||
runSourceMapTests('test/source-map/test-source-map-consumer', do_throw);
|
runSourceMapTests('test/source-map/test-source-map-consumer', do_throw);
|
||||||
|
|
|
@ -15,9 +15,6 @@ Components.utils.import('resource://test/Utils.jsm');
|
||||||
define("test/source-map/test-source-map-generator", ["require", "exports", "module"], function (require, exports, module) {
|
define("test/source-map/test-source-map-generator", ["require", "exports", "module"], function (require, exports, module) {
|
||||||
|
|
||||||
var SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator;
|
var SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator;
|
||||||
var SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer;
|
|
||||||
var SourceNode = require('source-map/source-node').SourceNode;
|
|
||||||
var util = require('source-map/util');
|
|
||||||
|
|
||||||
exports['test some simple stuff'] = function (assert, util) {
|
exports['test some simple stuff'] = function (assert, util) {
|
||||||
var map = new SourceMapGenerator({
|
var map = new SourceMapGenerator({
|
||||||
|
@ -179,100 +176,19 @@ define("test/source-map/test-source-map-generator", ["require", "exports", "modu
|
||||||
|
|
||||||
map = JSON.parse(map.toString());
|
map = JSON.parse(map.toString());
|
||||||
|
|
||||||
util.assertEqualMaps(assert, map, util.testMap);
|
assert.equal(map.version, 3);
|
||||||
};
|
assert.equal(map.file, 'min.js');
|
||||||
|
assert.equal(map.names.length, 3);
|
||||||
exports['test that source content can be set'] = function (assert, util) {
|
assert.equal(map.names[0], 'bar');
|
||||||
var map = new SourceMapGenerator({
|
assert.equal(map.names[1], 'baz');
|
||||||
file: 'min.js',
|
assert.equal(map.names[2], 'n');
|
||||||
sourceRoot: '/the/root'
|
assert.equal(map.sources.length, 2);
|
||||||
});
|
|
||||||
map.addMapping({
|
|
||||||
generated: { line: 1, column: 1 },
|
|
||||||
original: { line: 1, column: 1 },
|
|
||||||
source: 'one.js'
|
|
||||||
});
|
|
||||||
map.addMapping({
|
|
||||||
generated: { line: 2, column: 1 },
|
|
||||||
original: { line: 1, column: 1 },
|
|
||||||
source: 'two.js'
|
|
||||||
});
|
|
||||||
map.setSourceContent('one.js', 'one file content');
|
|
||||||
|
|
||||||
map = JSON.parse(map.toString());
|
|
||||||
assert.equal(map.sources[0], 'one.js');
|
assert.equal(map.sources[0], 'one.js');
|
||||||
assert.equal(map.sources[1], 'two.js');
|
assert.equal(map.sources[1], 'two.js');
|
||||||
assert.equal(map.sourcesContent[0], 'one file content');
|
assert.equal(map.sourceRoot, '/the/root');
|
||||||
assert.equal(map.sourcesContent[1], null);
|
assert.equal(map.mappings, 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports['test .fromSourceMap'] = function (assert, util) {
|
|
||||||
var map = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(util.testMap));
|
|
||||||
util.assertEqualMaps(assert, map.toJSON(), util.testMap);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports['test .fromSourceMap with sourcesContent'] = function (assert, util) {
|
|
||||||
var map = SourceMapGenerator.fromSourceMap(
|
|
||||||
new SourceMapConsumer(util.testMapWithSourcesContent));
|
|
||||||
util.assertEqualMaps(assert, map.toJSON(), util.testMapWithSourcesContent);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports['test applySourceMap'] = function (assert, util) {
|
|
||||||
var node = new SourceNode(null, null, null, [
|
|
||||||
new SourceNode(2, 0, 'fileX', 'lineX2\n'),
|
|
||||||
'genA1\n',
|
|
||||||
new SourceNode(2, 0, 'fileY', 'lineY2\n'),
|
|
||||||
'genA2\n',
|
|
||||||
new SourceNode(1, 0, 'fileX', 'lineX1\n'),
|
|
||||||
'genA3\n',
|
|
||||||
new SourceNode(1, 0, 'fileY', 'lineY1\n')
|
|
||||||
]);
|
|
||||||
var mapStep1 = node.toStringWithSourceMap({
|
|
||||||
file: 'fileA'
|
|
||||||
}).map;
|
|
||||||
mapStep1.setSourceContent('fileX', 'lineX1\nlineX2\n');
|
|
||||||
mapStep1 = mapStep1.toJSON();
|
|
||||||
|
|
||||||
node = new SourceNode(null, null, null, [
|
|
||||||
'gen1\n',
|
|
||||||
new SourceNode(1, 0, 'fileA', 'lineA1\n'),
|
|
||||||
new SourceNode(2, 0, 'fileA', 'lineA2\n'),
|
|
||||||
new SourceNode(3, 0, 'fileA', 'lineA3\n'),
|
|
||||||
new SourceNode(4, 0, 'fileA', 'lineA4\n'),
|
|
||||||
new SourceNode(1, 0, 'fileB', 'lineB1\n'),
|
|
||||||
new SourceNode(2, 0, 'fileB', 'lineB2\n'),
|
|
||||||
'gen2\n'
|
|
||||||
]);
|
|
||||||
var mapStep2 = node.toStringWithSourceMap({
|
|
||||||
file: 'fileGen'
|
|
||||||
}).map;
|
|
||||||
mapStep2.setSourceContent('fileB', 'lineB1\nlineB2\n');
|
|
||||||
mapStep2 = mapStep2.toJSON();
|
|
||||||
|
|
||||||
node = new SourceNode(null, null, null, [
|
|
||||||
'gen1\n',
|
|
||||||
new SourceNode(2, 0, 'fileX', 'lineA1\n'),
|
|
||||||
new SourceNode(2, 0, 'fileA', 'lineA2\n'),
|
|
||||||
new SourceNode(2, 0, 'fileY', 'lineA3\n'),
|
|
||||||
new SourceNode(4, 0, 'fileA', 'lineA4\n'),
|
|
||||||
new SourceNode(1, 0, 'fileB', 'lineB1\n'),
|
|
||||||
new SourceNode(2, 0, 'fileB', 'lineB2\n'),
|
|
||||||
'gen2\n'
|
|
||||||
]);
|
|
||||||
var expectedMap = node.toStringWithSourceMap({
|
|
||||||
file: 'fileGen'
|
|
||||||
}).map;
|
|
||||||
expectedMap.setSourceContent('fileX', 'lineX1\nlineX2\n');
|
|
||||||
expectedMap.setSourceContent('fileB', 'lineB1\nlineB2\n');
|
|
||||||
expectedMap = expectedMap.toJSON();
|
|
||||||
|
|
||||||
// apply source map "mapStep1" to "mapStep2"
|
|
||||||
var generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapStep2));
|
|
||||||
generator.applySourceMap(new SourceMapConsumer(mapStep1));
|
|
||||||
var actualMap = generator.toJSON();
|
|
||||||
|
|
||||||
util.assertEqualMaps(assert, actualMap, expectedMap);
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
function run_test() {
|
function run_test() {
|
||||||
runSourceMapTests('test/source-map/test-source-map-generator', do_throw);
|
runSourceMapTests('test/source-map/test-source-map-generator', do_throw);
|
||||||
|
|
|
@ -136,10 +136,7 @@ define("test/source-map/test-source-node", ["require", "exports", "module"], fun
|
||||||
exports['test .toStringWithSourceMap()'] = function (assert, util) {
|
exports['test .toStringWithSourceMap()'] = function (assert, util) {
|
||||||
var node = new SourceNode(null, null, null,
|
var node = new SourceNode(null, null, null,
|
||||||
['(function () {\n',
|
['(function () {\n',
|
||||||
' ',
|
' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n',
|
||||||
new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'),
|
|
||||||
new SourceNode(1, 8, 'a.js', '()'),
|
|
||||||
';\n',
|
|
||||||
' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n',
|
' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n',
|
||||||
'}());']);
|
'}());']);
|
||||||
var map = node.toStringWithSourceMap({
|
var map = node.toStringWithSourceMap({
|
||||||
|
@ -151,14 +148,6 @@ define("test/source-map/test-source-node", ["require", "exports", "module"], fun
|
||||||
|
|
||||||
var actual;
|
var actual;
|
||||||
|
|
||||||
actual = map.originalPositionFor({
|
|
||||||
line: 1,
|
|
||||||
column: 4
|
|
||||||
});
|
|
||||||
assert.equal(actual.source, null);
|
|
||||||
assert.equal(actual.line, null);
|
|
||||||
assert.equal(actual.column, null);
|
|
||||||
|
|
||||||
actual = map.originalPositionFor({
|
actual = map.originalPositionFor({
|
||||||
line: 2,
|
line: 2,
|
||||||
column: 2
|
column: 2
|
||||||
|
@ -166,7 +155,6 @@ define("test/source-map/test-source-node", ["require", "exports", "module"], fun
|
||||||
assert.equal(actual.source, 'a.js');
|
assert.equal(actual.source, 'a.js');
|
||||||
assert.equal(actual.line, 1);
|
assert.equal(actual.line, 1);
|
||||||
assert.equal(actual.column, 0);
|
assert.equal(actual.column, 0);
|
||||||
assert.equal(actual.name, 'originalCall');
|
|
||||||
|
|
||||||
actual = map.originalPositionFor({
|
actual = map.originalPositionFor({
|
||||||
line: 3,
|
line: 3,
|
||||||
|
@ -175,115 +163,8 @@ define("test/source-map/test-source-node", ["require", "exports", "module"], fun
|
||||||
assert.equal(actual.source, 'b.js');
|
assert.equal(actual.source, 'b.js');
|
||||||
assert.equal(actual.line, 2);
|
assert.equal(actual.line, 2);
|
||||||
assert.equal(actual.column, 0);
|
assert.equal(actual.column, 0);
|
||||||
|
|
||||||
actual = map.originalPositionFor({
|
|
||||||
line: 3,
|
|
||||||
column: 16
|
|
||||||
});
|
|
||||||
assert.equal(actual.source, null);
|
|
||||||
assert.equal(actual.line, null);
|
|
||||||
assert.equal(actual.column, null);
|
|
||||||
|
|
||||||
actual = map.originalPositionFor({
|
|
||||||
line: 4,
|
|
||||||
column: 2
|
|
||||||
});
|
|
||||||
assert.equal(actual.source, null);
|
|
||||||
assert.equal(actual.line, null);
|
|
||||||
assert.equal(actual.column, null);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports['test .fromStringWithSourceMap()'] = function (assert, util) {
|
|
||||||
var node = SourceNode.fromStringWithSourceMap(
|
|
||||||
util.testGeneratedCode,
|
|
||||||
new SourceMapConsumer(util.testMap));
|
|
||||||
|
|
||||||
var result = node.toStringWithSourceMap({
|
|
||||||
file: 'min.js'
|
|
||||||
});
|
|
||||||
var map = result.map;
|
|
||||||
var code = result.code;
|
|
||||||
|
|
||||||
assert.equal(code, util.testGeneratedCode);
|
|
||||||
assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator');
|
|
||||||
map = map.toJSON();
|
|
||||||
assert.equal(map.version, util.testMap.version);
|
|
||||||
assert.equal(map.file, util.testMap.file);
|
|
||||||
assert.equal(map.mappings, util.testMap.mappings);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports['test .fromStringWithSourceMap() complex version'] = function (assert, util) {
|
|
||||||
var input = new SourceNode(null, null, null, [
|
|
||||||
"(function() {\n",
|
|
||||||
" var Test = {};\n",
|
|
||||||
" ", new SourceNode(1, 0, "a.js", "Test.A = { value: 1234 };\n"),
|
|
||||||
" ", new SourceNode(2, 0, "a.js", "Test.A.x = 'xyz';"), "\n",
|
|
||||||
"}());\n",
|
|
||||||
"/* Generated Source */"]);
|
|
||||||
input = input.toStringWithSourceMap({
|
|
||||||
file: 'foo.js'
|
|
||||||
});
|
|
||||||
|
|
||||||
var node = SourceNode.fromStringWithSourceMap(
|
|
||||||
input.code,
|
|
||||||
new SourceMapConsumer(input.map.toString()));
|
|
||||||
|
|
||||||
var result = node.toStringWithSourceMap({
|
|
||||||
file: 'foo.js'
|
|
||||||
});
|
|
||||||
var map = result.map;
|
|
||||||
var code = result.code;
|
|
||||||
|
|
||||||
assert.equal(code, input.code);
|
|
||||||
assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator');
|
|
||||||
map = map.toJSON();
|
|
||||||
var inputMap = input.map.toJSON();
|
|
||||||
util.assertEqualMaps(assert, map, inputMap);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports['test setSourceContent with toStringWithSourceMap'] = function (assert, util) {
|
|
||||||
var aNode = new SourceNode(1, 1, 'a.js', 'a');
|
|
||||||
aNode.setSourceContent('a.js', 'someContent');
|
|
||||||
var node = new SourceNode(null, null, null,
|
|
||||||
['(function () {\n',
|
|
||||||
' ', aNode,
|
|
||||||
' ', new SourceNode(1, 1, 'b.js', 'b'),
|
|
||||||
'}());']);
|
|
||||||
node.setSourceContent('b.js', 'otherContent');
|
|
||||||
var map = node.toStringWithSourceMap({
|
|
||||||
file: 'foo.js'
|
|
||||||
}).map;
|
|
||||||
|
|
||||||
assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator');
|
|
||||||
map = new SourceMapConsumer(map.toString());
|
|
||||||
|
|
||||||
assert.equal(map.sources.length, 2);
|
|
||||||
assert.equal(map.sources[0], 'a.js');
|
|
||||||
assert.equal(map.sources[1], 'b.js');
|
|
||||||
assert.equal(map.sourcesContent.length, 2);
|
|
||||||
assert.equal(map.sourcesContent[0], 'someContent');
|
|
||||||
assert.equal(map.sourcesContent[1], 'otherContent');
|
|
||||||
};
|
|
||||||
|
|
||||||
exports['test walkSourceContents'] = function (assert, util) {
|
|
||||||
var aNode = new SourceNode(1, 1, 'a.js', 'a');
|
|
||||||
aNode.setSourceContent('a.js', 'someContent');
|
|
||||||
var node = new SourceNode(null, null, null,
|
|
||||||
['(function () {\n',
|
|
||||||
' ', aNode,
|
|
||||||
' ', new SourceNode(1, 1, 'b.js', 'b'),
|
|
||||||
'}());']);
|
|
||||||
node.setSourceContent('b.js', 'otherContent');
|
|
||||||
var results = [];
|
|
||||||
node.walkSourceContents(function (sourceFile, sourceContent) {
|
|
||||||
results.push([sourceFile, sourceContent]);
|
|
||||||
});
|
|
||||||
assert.equal(results.length, 2);
|
|
||||||
assert.equal(results[0][0], 'a.js');
|
|
||||||
assert.equal(results[0][1], 'someContent');
|
|
||||||
assert.equal(results[1][0], 'b.js');
|
|
||||||
assert.equal(results[1][1], 'otherContent');
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
function run_test() {
|
function run_test() {
|
||||||
runSourceMapTests('test/source-map/test-source-node', do_throw);
|
runSourceMapTests('test/source-map/test-source-node', do_throw);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче