diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 44df7b5b1ad1..bcae0167be35 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1060,7 +1060,6 @@ pref("devtools.debugger.remote-host", "localhost"); pref("devtools.debugger.remote-autoconnect", false); pref("devtools.debugger.remote-connection-retries", 3); pref("devtools.debugger.remote-timeout", 20000); -pref("devtools.debugger.source-maps-enabled", false); // The default Debugger UI settings pref("devtools.debugger.ui.win-x", 0); diff --git a/browser/devtools/debugger/debugger-controller.js b/browser/devtools/debugger/debugger-controller.js index c37b0afc99b3..5523f7133d94 100644 --- a/browser/devtools/debugger/debugger-controller.js +++ b/browser/devtools/debugger/debugger-controller.js @@ -261,8 +261,6 @@ let DebuggerController = { if (aCallback) { aCallback(); } - }, { - useSourceMaps: Services.prefs.getBoolPref("devtools.debugger.source-maps-enabled") }); }); }, @@ -1114,7 +1112,7 @@ SourceScripts.prototype = { */ _onSourcesAdded: function SS__onSourcesAdded(aResponse) { if (aResponse.error) { - Cu.reportError(new Error("Error getting sources: " + aResponse.message)); + Cu.reportError("Error getting sources: " + aResponse.message); return; } diff --git a/browser/devtools/debugger/test/Makefile.in b/browser/devtools/debugger/test/Makefile.in index 07eeed6da264..7f01762ad840 100644 --- a/browser/devtools/debugger/test/Makefile.in +++ b/browser/devtools/debugger/test/Makefile.in @@ -96,7 +96,6 @@ MOCHITEST_BROWSER_TESTS = \ browser_dbg_bfcache.js \ browser_dbg_progress-listener-bug.js \ browser_dbg_chrome-debugging.js \ - browser_dbg_source_maps-01.js \ head.js \ helpers.js \ $(NULL) @@ -128,10 +127,6 @@ MOCHITEST_BROWSER_PAGES = \ test-function-search-01.js \ test-function-search-02.js \ test-function-search-03.js \ - binary_search.html \ - binary_search.coffee \ - binary_search.js \ - binary_search.map \ $(NULL) MOCHITEST_BROWSER_FILES_PARTS = MOCHITEST_BROWSER_TESTS MOCHITEST_BROWSER_PAGES diff --git a/browser/devtools/debugger/test/binary_search.coffee b/browser/devtools/debugger/test/binary_search.coffee deleted file mode 100644 index e3dacdaaab50..000000000000 --- a/browser/devtools/debugger/test/binary_search.coffee +++ /dev/null @@ -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 \ No newline at end of file diff --git a/browser/devtools/debugger/test/binary_search.html b/browser/devtools/debugger/test/binary_search.html deleted file mode 100644 index f9615da7c40d..000000000000 --- a/browser/devtools/debugger/test/binary_search.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - Browser Debugger Source Map Test - - - - - - diff --git a/browser/devtools/debugger/test/binary_search.js b/browser/devtools/debugger/test/binary_search.js deleted file mode 100644 index ce77903e1b07..000000000000 --- a/browser/devtools/debugger/test/binary_search.js +++ /dev/null @@ -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 -*/ diff --git a/browser/devtools/debugger/test/binary_search.map b/browser/devtools/debugger/test/binary_search.map deleted file mode 100644 index a86e74783f11..000000000000 --- a/browser/devtools/debugger/test/binary_search.map +++ /dev/null @@ -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" -} \ No newline at end of file diff --git a/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js b/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js index fc3b2efb54b4..93ae5ff0e492 100644 --- a/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js +++ b/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js @@ -27,22 +27,19 @@ function test() gDebugger = gPane.panelWin; resumed = true; - gDebugger.addEventListener("Debugger:SourceShown", onSourceShown); + gDebugger.addEventListener("Debugger:SourceShown", onScriptShown); - gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", - onFramesAdded); + gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() { + framesAdded = true; + executeSoon(startTest); + }); executeSoon(function() { gDebuggee.firstCall(); }); }); - function onFramesAdded(aEvent) { - framesAdded = true; - executeSoon(startTest); - } - - function onSourceShown(aEvent) { + function onScriptShown(aEvent) { scriptShown = aEvent.detail.url.indexOf("-02.js") != -1; executeSoon(startTest); } @@ -51,8 +48,8 @@ function test() { if (scriptShown && framesAdded && resumed && !testStarted) { testStarted = true; - gDebugger.removeEventListener("Debugger:SourceShown", onSourceShown); - executeSoon(performTest); + gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown); + Services.tm.currentThread.dispatch({ run: performTest }, 0); } } diff --git a/browser/devtools/debugger/test/browser_dbg_source_maps-01.js b/browser/devtools/debugger/test/browser_dbg_source_maps-01.js deleted file mode 100644 index dea3fc862ca1..000000000000 --- a/browser/devtools/debugger/test/browser_dbg_source_maps-01.js +++ /dev/null @@ -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; -}); diff --git a/toolkit/devtools/debugger/dbg-client.jsm b/toolkit/devtools/debugger/dbg-client.jsm index cf1def29695c..81ce4c965fef 100644 --- a/toolkit/devtools/debugger/dbg-client.jsm +++ b/toolkit/devtools/debugger/dbg-client.jsm @@ -322,10 +322,7 @@ DebuggerClient.prototype = { */ attachTab: function DC_attachTab(aTabActor, aOnResponse) { let self = this; - let packet = { - to: aTabActor, - type: "attach" - }; + let packet = { to: aTabActor, type: "attach" }; this.request(packet, function(aResponse) { let tabClient; if (!aResponse.error) { @@ -375,17 +372,10 @@ DebuggerClient.prototype = { * @param function aOnResponse * Called with the response packet and a ThreadClient * (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 packet = { - to: aThreadActor, - type: "attach", - options: aOptions - }; + let packet = { to: aThreadActor, type: "attach" }; this.request(packet, function(aResponse) { if (!aResponse.error) { var threadClient = new ThreadClient(self, aThreadActor); @@ -443,7 +433,7 @@ DebuggerClient.prototype = { */ _sendRequests: function DC_sendRequests() { let self = this; - this._pendingRequests = this._pendingRequests.filter(function (request) { + this._pendingRequests = this._pendingRequests.filter(function(request) { if (request.to in self._activeRequests) { return true; } @@ -470,7 +460,7 @@ DebuggerClient.prototype = { ? aPacket : this.compat.onPacket(aPacket); - resolve(packet).then((aPacket) => { + resolve(packet).then(function (aPacket) { if (!this._connected) { // Hello packet. this._connected = true; @@ -480,53 +470,55 @@ DebuggerClient.prototype = { return; } - if (!aPacket.from) { - let msg = "Server did not specify an actor, dropping packet: " + - JSON.stringify(aPacket); - Cu.reportError(msg); - dumpn(msg); - return; - } + try { + if (!aPacket.from) { + let msg = "Server did not specify an actor, dropping packet: " + + JSON.stringify(aPacket); + Cu.reportError(msg); + dumpn(msg); + return; + } - let onResponse; - // Don't count unsolicited notifications or pauses as responses. - if (aPacket.from in this._activeRequests && - !(aPacket.type in UnsolicitedNotifications) && - !(aPacket.type == ThreadStateTypes.paused && - aPacket.why.type in UnsolicitedPauses)) { - onResponse = this._activeRequests[aPacket.from].onResponse; - delete this._activeRequests[aPacket.from]; - } + let onResponse; + // Don't count unsolicited notifications or pauses as responses. + if (aPacket.from in this._activeRequests && + !(aPacket.type in UnsolicitedNotifications) && + !(aPacket.type == ThreadStateTypes.paused && + aPacket.why.type in UnsolicitedPauses)) { + onResponse = this._activeRequests[aPacket.from].onResponse; + delete this._activeRequests[aPacket.from]; + } - // Packets that indicate thread state changes get special treatment. - if (aPacket.type in ThreadStateTypes && - aPacket.from in this._threadClients) { - this._threadClients[aPacket.from]._onThreadState(aPacket); - } - // On navigation the server resumes, so the client must resume as well. - // We achieve that by generating a fake resumption packet that triggers - // the client's thread state change listeners. - if (this.activeThread && - aPacket.type == UnsolicitedNotifications.tabNavigated && - aPacket.from in this._tabClients) { - let resumption = { from: this.activeThread._actor, type: "resumed" }; - this.activeThread._onThreadState(resumption); - } - // Only try to notify listeners on events, not responses to requests - // that lack a packet type. - if (aPacket.type) { - this.notify(aPacket.type, aPacket); - } + // Packets that indicate thread state changes get special treatment. + if (aPacket.type in ThreadStateTypes && + aPacket.from in this._threadClients) { + this._threadClients[aPacket.from]._onThreadState(aPacket); + } + // On navigation the server resumes, so the client must resume as well. + // We achieve that by generating a fake resumption packet that triggers + // the client's thread state change listeners. + if (this.activeThread && + aPacket.type == UnsolicitedNotifications.tabNavigated && + aPacket.from in this._tabClients) { + let resumption = { from: this.activeThread._actor, type: "resumed" }; + this.activeThread._onThreadState(resumption); + } + // Only try to notify listeners on events, not responses to requests + // that lack a packet type. + if (aPacket.type) { + this.notify(aPacket.type, aPacket); + } - if (onResponse) { - onResponse(aPacket); + if (onResponse) { + onResponse(aPacket); + } + } catch(ex) { + dumpn("Error handling response: " + ex + " - stack:\n" + ex.stack); + Cu.reportError(ex + "\n" + ex.stack); } this._sendRequests(); - }, function (ex) { - dumpn("Error handling response: " + ex + " - stack:\n" + ex.stack); - Cu.reportError(ex.message + "\n" + ex.stack); - }); + }.bind(this)); }, /** diff --git a/toolkit/devtools/debugger/server/dbg-script-actors.js b/toolkit/devtools/debugger/server/dbg-script-actors.js index d54c1bd7aec2..a5875e1e3a8b 100644 --- a/toolkit/devtools/debugger/server/dbg-script-actors.js +++ b/toolkit/devtools/debugger/server/dbg-script-actors.js @@ -30,6 +30,7 @@ function ThreadActor(aHooks, aGlobal) this._frameActors = []; this._environmentActors = []; this._hooks = aHooks; + this._sources = {}; this.global = aGlobal; // 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.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; }, - get sources() { - if (!this._sources) { - this._sources = new ThreadSources(this, this._options.useSourceMaps, - this._allowSource, this.onNewSource); - } - return this._sources; - }, - clearDebuggees: function TA_clearDebuggees() { if (this.dbg) { this.dbg.removeAllDebuggees(); } this.conn.removeActorPool(this._threadLifetimePool || undefined); this._threadLifetimePool = null; - this._sources = null; + this._sources = {}; }, /** @@ -214,14 +202,11 @@ ThreadActor.prototype = { this._state = "attached"; - update(this._options, aRequest.options || {}); - if (!this.dbg) { this._initDebugger(); } this.findGlobals(); this.dbg.enabled = true; - try { // Put ourselves in the paused state. let packet = this._paused(); @@ -237,20 +222,19 @@ ThreadActor.prototype = { // Start a nested event loop. this._nest(); + // We already sent a response to this request, don't send one // now. return null; - } catch (e) { - reportError(e); + } catch(e) { + Cu.reportError(e); return { error: "notAttached", message: e.toString() }; } }, onDetach: function TA_onDetach(aRequest) { this.disconnect(); - return { - type: "detached" - }; + return { type: "detached" }; }, /** @@ -261,19 +245,15 @@ ThreadActor.prototype = { * The newest debuggee frame in the stack. * @param object aReason * 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, - onPacket=function (k) k) { + _pauseAndRespond: function TA__pauseAndRespond(aFrame, aReason) { try { let packet = this._paused(aFrame); if (!packet) { return undefined; } packet.why = aReason; - resolve(onPacket(packet)).then(this.conn.send.bind(this.conn)); + this.conn.send(packet); return this._nest(); } catch(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. */ 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 // different tabs or multiple debugger clients connected to the same tab) // only allow resumption in a LIFO order. @@ -467,23 +439,14 @@ ThreadActor.prototype = { // Return request.count frames, or all remaining // frames if count is not defined. let frames = []; - let promises = []; - for (; frame && (!count || i < (start + count)); i++, frame=frame.older) { + for (; frame && (!count || i < (start + count)); i++) { let form = this._createFrameActor(frame).form(); form.depth = i; frames.push(form); - - let promise = this.sources.getOriginalLocation(form.where.url, - form.where.line) - .then(function (aOrigLocation) { - form.where = aOrigLocation; - }); - promises.push(promise); + frame = frame.older; } - return Promise.all(promises).then(function () { - return { frames: frames }; - }); + return { frames: frames }; }, onReleaseMany: function TA_onReleaseMany(aRequest) { @@ -516,58 +479,25 @@ ThreadActor.prototype = { message: "Breakpoints can only be set while the debuggee is paused."}; } - // XXX: `originalColumn` is never used. See bug 827639. - let { url: originalSource, - line: originalLine, - column: originalColumn } = aRequest.location; + let location = aRequest.location; + let line = location.line; + if (this.dbg.findScripts({ url: location.url }).length == 0 || line < 0) { + return { error: "noScript" }; + } - let locationPromise = this.sources.getGeneratedLocation(originalSource, - originalLine) - return locationPromise.then(function (aLocation) { - let line = aLocation.line; - if (this.dbg.findScripts({ url: aLocation.url }).length == 0 || line < 0) { - return { error: "noScript" }; - } + // Add the breakpoint to the store for later reuse, in case it belongs to a + // script that hasn't appeared yet. + if (!this._breakpointStore[location.url]) { + this._breakpointStore[location.url] = []; + } + 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 - // 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)); + return this._setBreakpoint(location); }, /** @@ -678,16 +608,17 @@ ThreadActor.prototype = { * Get the script and source lists from the debugger. */ _discoverScriptsAndSources: function TA__discoverScriptsAndSources() { - return Promise.all([this._addScript(s) - for (s of this.dbg.findScripts())]); + for (let s of this.dbg.findScripts()) { + this._addScript(s); + } }, onSources: function TA_onSources(aRequest) { - return this._discoverScriptsAndSources().then(function () { - return { - sources: [s.form() for (s of this.sources.iter())] - }; - }.bind(this)); + this._discoverScriptsAndSources(); + let urls = Object.getOwnPropertyNames(this._sources); + return { + sources: [this._getSource(url).form() for (url of urls)] + }; }, /** @@ -724,8 +655,8 @@ ThreadActor.prototype = { // We already sent a response to this request, don't send one // now. return null; - } catch (e) { - reportError(e); + } catch(e) { + Cu.reportError(e); return { error: "notInterrupted", message: e.toString() }; } }, @@ -796,6 +727,7 @@ ThreadActor.prototype = { if (aFrame) { packet.frame = this._createFrameActor(aFrame).form(); } + if (poppedFrames) { packet.poppedFrames = poppedFrames; } @@ -1101,9 +1033,8 @@ ThreadActor.prototype = { * Create a source grip for the given script. */ sourceGrip: function TA_sourceGrip(aScript) { - // TODO bug 637572: Once we have Debugger.Source, this should be replaced - // with a weakmap mapping Debugger.Source instances to SourceActor - // instances. + // TODO: Once we have Debugger.Source, this should be replaced with a + // weakmap mapping Debugger.Source instances to SourceActor instances. if (!this.threadLifetimePool.sourceActors) { this.threadLifetimePool.sourceActors = {}; } @@ -1163,7 +1094,7 @@ ThreadActor.prototype = { exception: this.createValueGrip(aValue) }; this.conn.send(packet); return this._nest(); - } catch (e) { + } catch(e) { Cu.reportError("Got an exception during TA_onExceptionUnwind: " + e + ": " + e.stack); return undefined; @@ -1183,14 +1114,6 @@ ThreadActor.prototype = { 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 * the cache. @@ -1199,7 +1122,7 @@ ThreadActor.prototype = { * The url of the script's source that will be stored. * @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). if (!aSourceUrl) return false; @@ -1223,30 +1146,28 @@ ThreadActor.prototype = { */ _addScript: function TA__addScript(aScript) { if (!this._allowSource(aScript.url)) { - return resolve(false); + return false; } // TODO bug 637572: we should be dealing with sources directly, not // inferring them through scripts. - return this.sources.sourcesForScript(aScript).then(function () { + this._addSource(aScript.url); - // Set any stored breakpoints. - let existing = this._breakpointStore[aScript.url]; - if (existing) { - let endLine = aScript.startLine + aScript.lineCount - 1; - // Iterate over the lines backwards, so that sliding breakpoints don't - // affect the loop. - for (let line = existing.length - 1; line >= 0; line--) { - let bp = existing[line]; - // Limit search to the line numbers contained in the new script. - if (bp && line >= aScript.startLine && line <= endLine) { - this._setBreakpoint(bp); - } + // Set any stored breakpoints. + let existing = this._breakpointStore[aScript.url]; + if (existing) { + let endLine = aScript.startLine + aScript.lineCount - 1; + // Iterate over the lines backwards, so that sliding breakpoints don't + // affect the loop. + for (let line = existing.length - 1; line >= 0; line--) { + let bp = existing[line]; + // Limit search to the line numbers contained in the new script. + if (bp && line >= aScript.startLine && line <= endLine) { + this._setBreakpoint(bp); } } - - return true; - }.bind(this)); + } + return true; }, /** @@ -1294,6 +1215,48 @@ ThreadActor.prototype = { 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 = { @@ -1400,7 +1363,6 @@ SourceActor.prototype = { actorPrefix: "source", get threadActor() { return this._threadActor; }, - get url() { return this._url; }, form: function SA_form() { return { @@ -1420,9 +1382,10 @@ SourceActor.prototype = { * Handler for the "source" packet. */ onSource: function SA_onSource(aRequest) { - return fetch(this._url) + return this + ._loadSource() .then(function(aSource) { - return this.threadActor.createValueGrip( + return this._threadActor.createValueGrip( aSource, this.threadActor.threadLifetimePool); }.bind(this)) .then(function (aSourceGrip) { @@ -1431,17 +1394,121 @@ SourceActor.prototype = { source: aSourceGrip }; }.bind(this), function (aError) { - let msg = "Got an exception during SA_onSource: " + aError + - "\n" + aError.stack; - Cu.reportError(msg); - dumpn(msg); return { "from": this.actorID, "error": "loadSourceError", "message": "Could not load the source for " + this._url + "." }; }.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 = { @@ -2028,14 +2095,7 @@ BreakpointActor.prototype = { hit: function BA_hit(aFrame) { // TODO: add the rest of the breakpoints on that line (bug 676602). let reason = { type: "breakpoint", actors: [ this.actorID ] }; - return this.threadActor._pauseAndRespond(aFrame, reason, function (aPacket) { - let { url, line } = aPacket.frame.where; - return this.threadActor.sources.getOriginalLocation(url, line) - .then(function (aOrigPosition) { - aPacket.frame.where = aOrigPosition; - return aPacket; - }); - }.bind(this)); + return this.threadActor._pauseAndRespond(aFrame, reason); }, /** @@ -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. /** @@ -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); -} diff --git a/toolkit/devtools/debugger/server/dbg-server.js b/toolkit/devtools/debugger/server/dbg-server.js index 68c4b056c66b..f3bde2d0c021 100644 --- a/toolkit/devtools/debugger/server/dbg-server.js +++ b/toolkit/devtools/debugger/server/dbg-server.js @@ -26,9 +26,6 @@ addDebuggerToGlobal(this); Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); const { defer, resolve, reject } = Promise; -Promise.all = Promise.promised(Array); - -Cu.import("resource://gre/modules/devtools/SourceMap.jsm"); function dumpn(str) { if (wantLogging) { @@ -603,17 +600,6 @@ DebuggerServerConnection.prototype = { 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. /** @@ -636,9 +622,12 @@ DebuggerServerConnection.prototype = { try { instance = new actor(); } catch (e) { - this.transport.send(this._unknownError( - "Error occurred while creating actor '" + actor.name, - e)); + Cu.reportError(e); + this.transport.send({ + error: "unknownError", + message: ("error occurred while creating actor '" + actor.name + + "': " + safeErrorString(e)) + }); } instance.parentID = actor.parentID; // We want the newly-constructed actor to completely replace the factory @@ -650,14 +639,16 @@ DebuggerServerConnection.prototype = { } var ret = null; + // Dispatch the request to the actor. if (actor.requestTypes && actor.requestTypes[aPacket.type]) { try { ret = actor.requestTypes[aPacket.type].bind(actor)(aPacket); } catch(e) { - this.transport.send(this._unknownError( - "error occurred while processing '" + aPacket.type, - e)); + Cu.reportError(e); + ret = { error: "unknownError", + message: ("error occurred while processing '" + aPacket.type + + "' request: " + safeErrorString(e)) }; } } else { ret = { error: "unrecognizedPacketType", @@ -672,19 +663,12 @@ DebuggerServerConnection.prototype = { return; } - resolve(ret) - .then(null, function (e) { - return this._unknownError( - "error occurred while processing '" + aPacket.type, - e); - }.bind(this)) - .then(function (aResponse) { - if (!aResponse.from) { - aResponse.from = aPacket.to; - } - return aResponse; - }) - .then(this.transport.send.bind(this.transport)); + resolve(ret).then(function(returnPacket) { + if (!returnPacket.from) { + returnPacket.from = aPacket.to; + } + this.transport.send(returnPacket); + }.bind(this)); }, /** diff --git a/toolkit/devtools/debugger/tests/unit/head_dbg.js b/toolkit/devtools/debugger/tests/unit/head_dbg.js index 525ae7e46552..1e13cf8b8168 100644 --- a/toolkit/devtools/debugger/tests/unit/head_dbg.js +++ b/toolkit/devtools/debugger/tests/unit/head_dbg.js @@ -111,7 +111,7 @@ function getTestGlobalContext(aClient, aName, aCallback) { function attachTestGlobalClient(aClient, aName, aCallback) { 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) { aCallback(aResponse, aTabClient, aThreadClient); }); - }, { useSourceMaps: true }); + }); }); } diff --git a/toolkit/devtools/debugger/tests/unit/test_breakpoint-04.js b/toolkit/devtools/debugger/tests/unit/test_breakpoint-04.js index c83c26c445aa..6c91aa956ef7 100644 --- a/toolkit/devtools/debugger/tests/unit/test_breakpoint-04.js +++ b/toolkit/devtools/debugger/tests/unit/test_breakpoint-04.js @@ -61,8 +61,8 @@ function test_child_breakpoint() gDebuggee.eval("var line0 = Error().lineNumber;\n" + "function foo() {\n" + // line0 + 1 - " this.a = 1;\n" + // line0 + 2 - " this.b = 2;\n" + // line0 + 3 + " this.a = 1;\n" + // line0 + 2 + " this.b = 2;\n" + // line0 + 3 "}\n" + // line0 + 4 "debugger;\n" + // line0 + 5 "foo();\n"); // line0 + 6 diff --git a/toolkit/devtools/debugger/tests/unit/test_dbgactor.js b/toolkit/devtools/debugger/tests/unit/test_dbgactor.js index 131acda9fb23..9802638048e2 100644 --- a/toolkit/devtools/debugger/tests/unit/test_dbgactor.js +++ b/toolkit/devtools/debugger/tests/unit/test_dbgactor.js @@ -38,7 +38,6 @@ function run_test() function test_attach(aContext) { gClient.request({ to: aContext.actor, type: "attach" }, function(aResponse) { - do_check_true(!aResponse.error); do_check_eq(aResponse.type, "paused"); // Resume the thread and test the debugger statement. diff --git a/toolkit/devtools/debugger/tests/unit/test_listsources-01.js b/toolkit/devtools/debugger/tests/unit/test_listsources-01.js index c3b009d6788c..2dccad8c9b05 100644 --- a/toolkit/devtools/debugger/tests/unit/test_listsources-01.js +++ b/toolkit/devtools/debugger/tests/unit/test_listsources-01.js @@ -16,6 +16,14 @@ function run_test() initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); 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 () { attachTestGlobalClientAndResume(gClient, "test-stack", function (aResponse, aThreadClient) { gThreadClient = aThreadClient; diff --git a/toolkit/devtools/debugger/tests/unit/test_listsources-02.js b/toolkit/devtools/debugger/tests/unit/test_listsources-02.js index 23049ecc3818..044f5eaba267 100644 --- a/toolkit/devtools/debugger/tests/unit/test_listsources-02.js +++ b/toolkit/devtools/debugger/tests/unit/test_listsources-02.js @@ -16,7 +16,6 @@ function run_test() initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); - gClient.request = (function (request) { return function (aRequest, aOnResponse) { if (aRequest.type === "sources") { @@ -34,7 +33,6 @@ function run_test() test_listing_zero_sources(); }); }); - do_test_pending(); } @@ -49,6 +47,6 @@ function test_listing_zero_sources() "Should only send one sources request at most, even though we" + " might have had to send one to determine feature support."); - finishClient(gClient); + finishClient(gClient); }); } diff --git a/toolkit/devtools/debugger/tests/unit/test_listsources-03.js b/toolkit/devtools/debugger/tests/unit/test_listsources-03.js deleted file mode 100644 index 7325f4a887e5..000000000000 --- a/toolkit/devtools/debugger/tests/unit/test_listsources-03.js +++ /dev/null @@ -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;"); -} diff --git a/toolkit/devtools/debugger/tests/unit/test_pause_exceptions-01.js b/toolkit/devtools/debugger/tests/unit/test_pause_exceptions-01.js index 578e50037cd1..a588c8eba0b9 100644 --- a/toolkit/devtools/debugger/tests/unit/test_pause_exceptions-01.js +++ b/toolkit/devtools/debugger/tests/unit/test_pause_exceptions-01.js @@ -30,12 +30,10 @@ function test_pause_frame() gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) { do_check_eq(aPacket.why.type, "exception"); do_check_eq(aPacket.why.exception, 42); - gThreadClient.resume(function () { finishClient(gClient); }); }); - gThreadClient.pauseOnExceptions(true); gThreadClient.resume(); }); diff --git a/toolkit/devtools/debugger/tests/unit/test_profiler_actor.js b/toolkit/devtools/debugger/tests/unit/test_profiler_actor.js index cb30a0db4256..ef38552ccbe4 100644 --- a/toolkit/devtools/debugger/tests/unit/test_profiler_actor.js +++ b/toolkit/devtools/debugger/tests/unit/test_profiler_actor.js @@ -114,15 +114,21 @@ function test_profile(aClient, aProfiler) do_check_eq(typeof aResponse.profile.threads[0].samples, "object"); 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. - 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)" && typeof sample.frames == "object" && sample.frames.length != 0 && sample.frames.some(function(f) { 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; do_check_false(Profiler.IsActive()); - client.request({ - to: profiler, - type: "startProfiler", - features: [] - }, (aResponse) => { + client.request({ to: profiler, type: "startProfiler", features: [] }, (aResponse) => { do_check_true(Profiler.IsActive()); - client.close(); + client.close(function () {}); }); }); }); diff --git a/toolkit/devtools/debugger/tests/unit/test_sourcemaps-01.js b/toolkit/devtools/debugger/tests/unit/test_sourcemaps-01.js deleted file mode 100644 index 3c00183ccd63..000000000000 --- a/toolkit/devtools/debugger/tests/unit/test_sourcemaps-01.js +++ /dev/null @@ -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); -} diff --git a/toolkit/devtools/debugger/tests/unit/test_sourcemaps-02.js b/toolkit/devtools/debugger/tests/unit/test_sourcemaps-02.js deleted file mode 100644 index 4310884a08bd..000000000000 --- a/toolkit/devtools/debugger/tests/unit/test_sourcemaps-02.js +++ /dev/null @@ -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); -} diff --git a/toolkit/devtools/debugger/tests/unit/test_sourcemaps-03.js b/toolkit/devtools/debugger/tests/unit/test_sourcemaps-03.js deleted file mode 100644 index 802277861c9b..000000000000 --- a/toolkit/devtools/debugger/tests/unit/test_sourcemaps-03.js +++ /dev/null @@ -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); -} diff --git a/toolkit/devtools/debugger/tests/unit/test_sources_backwards_compat-01.js b/toolkit/devtools/debugger/tests/unit/test_sources_backwards_compat-01.js index 2f8722d47545..c7efcbd8a496 100644 --- a/toolkit/devtools/debugger/tests/unit/test_sources_backwards_compat-01.js +++ b/toolkit/devtools/debugger/tests/unit/test_sources_backwards_compat-01.js @@ -18,7 +18,6 @@ function run_test() initSourcesBackwardsCompatDebuggerServer(); gDebuggee = addTestGlobal("test-sources-compat"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); - gClient.request = (function (request) { return function (aRequest, aOnResponse) { if (aRequest.type === "sources") { @@ -27,7 +26,6 @@ function run_test() return request.call(this, aRequest, aOnResponse); }; }(gClient.request)); - gClient.connect(function() { attachTestTabAndResume(gClient, "test-sources-compat", function (aResponse, aTabClient, diff --git a/toolkit/devtools/debugger/tests/unit/test_sources_backwards_compat-02.js b/toolkit/devtools/debugger/tests/unit/test_sources_backwards_compat-02.js index 2955978307e5..184af26e3ade 100644 --- a/toolkit/devtools/debugger/tests/unit/test_sources_backwards_compat-02.js +++ b/toolkit/devtools/debugger/tests/unit/test_sources_backwards_compat-02.js @@ -17,7 +17,6 @@ function run_test() initSourcesBackwardsCompatDebuggerServer(); gDebuggee = addTestGlobal("test-sources-compat"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); - gClient.request = (function (request) { return function (aRequest, aOnResponse) { if (aRequest.type === "sources") { diff --git a/toolkit/devtools/debugger/tests/unit/testcompatactors.js b/toolkit/devtools/debugger/tests/unit/testcompatactors.js index 0b778e51e1b3..7eb44846ff2f 100644 --- a/toolkit/devtools/debugger/tests/unit/testcompatactors.js +++ b/toolkit/devtools/debugger/tests/unit/testcompatactors.js @@ -30,26 +30,26 @@ function createRootActor() }; actor.thread.requestTypes["scripts"] = function (aRequest) { - return this._discoverScriptsAndSources().then(function () { - 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); - } + this._discoverScriptsAndSources(); - return { - from: this.actorID, - scripts: scripts + 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._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 @@ -70,7 +70,7 @@ function createRootActor() url: aScript.url, startLine: aScript.startLine, lineCount: aScript.lineCount, - source: actor.thread.sources.source(aScript.url).form() + source: actor.thread._getSource(aScript.url).form() }); }; }(actor.thread.onNewScript)); diff --git a/toolkit/devtools/debugger/tests/unit/xpcshell.ini b/toolkit/devtools/debugger/tests/unit/xpcshell.ini index bdf4d89ad351..21b3aaa6be10 100644 --- a/toolkit/devtools/debugger/tests/unit/xpcshell.ini +++ b/toolkit/devtools/debugger/tests/unit/xpcshell.ini @@ -74,13 +74,9 @@ skip-if = toolkit == "gonk" reason = bug 820380 [test_listsources-01.js] [test_listsources-02.js] -[test_listsources-03.js] [test_new_source-01.js] [test_sources_backwards_compat-01.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-02.js] [test_objectgrips-03.js] diff --git a/toolkit/devtools/sourcemap/SourceMap.jsm b/toolkit/devtools/sourcemap/SourceMap.jsm index b8f9bd4258a3..0dc4063c10cf 100644 --- a/toolkit/devtools/sourcemap/SourceMap.jsm +++ b/toolkit/devtools/sourcemap/SourceMap.jsm @@ -44,7 +44,6 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou * - sources: An array of URLs to the original source files. * - names: An array of identifiers which can be referrenced by individual mappings. * - 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. * - 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 names = util.getArg(sourceMap, 'names'); var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); - var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); var mappings = util.getArg(sourceMap, 'mappings'); 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._sources = ArraySet.fromArray(sources); - this.sourceRoot = sourceRoot; - this.sourcesContent = sourcesContent; + this._sourceRoot = sourceRoot; this.file = file; // `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', { get: function () { 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); } }); @@ -168,7 +165,12 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { // Original source. 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; str = temp.rest; 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); - 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, "generatedLine", "generatedColumn", - this._compareGeneratedPositions); + this._compareGeneratedPositions) if (mapping) { - var source = util.getArg(mapping, 'source', null); - if (source && this.sourceRoot) { - source = util.join(this.sourceRoot, source); - } return { - source: source, + source: util.getArg(mapping, 'source', null), line: util.getArg(mapping, 'originalLine', null), column: util.getArg(mapping, 'originalColumn', 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, * 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') }; - if (this.sourceRoot) { - needle.source = util.relative(this.sourceRoot, needle.source); - } - var mapping = this._findMapping(needle, this._originalMappings, "originalLine", "originalColumn", - this._compareOriginalPositions); + this._compareOriginalPositions) if (mapping) { return { @@ -393,7 +359,8 @@ define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'sou * generated line/column in this source map. * * @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 * Optional. If specified, this object will be the value of `this` every * 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."); } - var sourceRoot = this.sourceRoot; - 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); + mappings.forEach(aCallback, context); }; exports.SourceMapConsumer = SourceMapConsumer; @@ -473,37 +426,10 @@ define('source-map/util', ['require', 'exports', 'module' , ], function(require, function join(aRoot, aPath) { return aPath.charAt(0) === '/' ? aPath - : aRoot.replace(/\/$/, '') + '/' + 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; -*- */ /* @@ -589,9 +515,7 @@ define('source-map/binary-search', ['require', 'exports', 'module' , ], function * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -define('source-map/array-set', ['require', 'exports', 'module' , 'source-map/util'], function(require, exports, module) { - - var util = require('source-map/util'); +define('source-map/array-set', ['require', 'exports', 'module' , ], function(require, exports, module) { /** * 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; }; + /** + * 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. * @@ -627,7 +564,7 @@ define('source-map/array-set', ['require', 'exports', 'module' , 'source-map/ut } var idx = this._array.length; 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) { 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) { 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.'); }; @@ -882,58 +819,10 @@ define('source-map/source-map-generator', ['require', 'exports', 'module' , 'so this._sources = new ArraySet(); this._names = new ArraySet(); this._mappings = []; - this._sourcesContents = null; } 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 * 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: * @@ -1193,17 +978,6 @@ define('source-map/source-map-generator', ['require', 'exports', 'module' , 'so if (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; }; @@ -1224,10 +998,9 @@ define('source-map/source-map-generator', ['require', 'exports', 'module' , 'so * Licensed under the New BSD license. See LICENSE or: * 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 util = require('source-map/util'); /** * 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 aChunks Optional. An array of strings which are snippets of * 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.sourceContents = {}; - this.line = aLine === undefined ? null : aLine; - this.column = aColumn === undefined ? null : aColumn; - this.source = aSource === undefined ? null : aSource; - this.name = aName === undefined ? null : aName; + this.line = aLine; + this.column = aColumn; + this.source = aSource; 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. * @@ -1416,10 +1083,7 @@ define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/ } else { if (chunk !== '') { - aFn(chunk, { source: this.source, - line: this.line, - column: this.column, - name: this.name }); + aFn(chunk, { source: this.source, line: this.line, column: this.column }); } } }, this); @@ -1434,7 +1098,7 @@ define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/ SourceNode.prototype.join = function SourceNode_join(aSep) { var newChildren; var i; - var len = this.children.length; + var len = this.children.length if (len > 0) { newChildren = []; for (i = 0; i < len-1; i++) { @@ -1468,36 +1132,6 @@ define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/ 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 * 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 }; var map = new SourceMapGenerator(aArgs); - var sourceMappingActive = false; this.walk(function (chunk, original) { generated.code += chunk; - if (original.source !== null - && original.line !== null - && original.column !== null) { + if (original.source != null + && original.line != null + && original.column != null) { map.addMapping({ source: original.source, original: { line: original.line, column: original.column }, - generated: { - line: generated.line, - column: generated.column - }, - name: original.name - }); - sourceMappingActive = true; - } else if (sourceMappingActive) { - map.addMapping({ generated: { line: generated.line, column: generated.column } }); - sourceMappingActive = false; } - chunk.split('').forEach(function (ch) { - if (ch === '\n') { + chunk.split('').forEach(function (char) { + if (char === '\n') { generated.line++; generated.column = 0; } 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 }; }; @@ -1571,6 +1191,6 @@ define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/ /* -*- Mode: js; js-indent-level: 2; -*- */ /////////////////////////////////////////////////////////////////////////////// -this.SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer; -this.SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator; -this.SourceNode = require('source-map/source-node').SourceNode; +let SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer; +let SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator; +let SourceNode = require('source-map/source-node').SourceNode; diff --git a/toolkit/devtools/sourcemap/tests/unit/Utils.jsm b/toolkit/devtools/sourcemap/tests/unit/Utils.jsm index ceb12e0141d3..5f7c81d529f2 100644 --- a/toolkit/devtools/sourcemap/tests/unit/Utils.jsm +++ b/toolkit/devtools/sourcemap/tests/unit/Utils.jsm @@ -15,7 +15,7 @@ Components.utils.import('resource://gre/modules/devtools/Require.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; -*- */ /* * 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: * http://opensource.org/licenses/BSD-3-Clause */ -define('test/source-map/util', ['require', 'exports', 'module' , 'lib/source-map/util'], function(require, exports, module) { - - var util = require('source-map/util'); +define('test/source-map/util', ['require', 'exports', 'module' , ], function(require, exports, module) { // This is a test mapping which maps functions from two different files // (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);}; // 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 = { version: 3, file: 'min.js', @@ -111,22 +107,6 @@ define('test/source-map/util', ['require', 'exports', 'module' , 'lib/source-ma sourceRoot: '/the/root', 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, 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, 'Incorrect column, expected ' + JSON.stringify(originalColumn) + ', got ' + JSON.stringify(origMapping.column)); - assert.equal(origMapping.source, - originalSource ? util.join(map._sourceRoot, originalSource) : null, + assert.equal(origMapping.source, originalSource, 'Incorrect source, expected ' + JSON.stringify(originalSource) + ', got ' + JSON.stringify(origMapping.source)); } @@ -167,111 +146,6 @@ define('test/source-map/util', ['require', 'exports', 'module' , 'lib/source-ma } 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; -*- */ /* @@ -293,4 +167,3 @@ function runSourceMapTests(modName, do_throw) { } } -this.runSourceMapTests = runSourceMapTests; diff --git a/toolkit/devtools/sourcemap/tests/unit/test_source_map_consumer.js b/toolkit/devtools/sourcemap/tests/unit/test_source_map_consumer.js index 3b7a59e7e11d..e3438fc87f6a 100644 --- a/toolkit/devtools/sourcemap/tests/unit/test_source_map_consumer.js +++ b/toolkit/devtools/sourcemap/tests/unit/test_source_map_consumer.js @@ -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) { 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) { assert.doesNotThrow(function () { @@ -98,10 +97,6 @@ define("test/source-map/test-source-map-consumer", ["require", "exports", "modul map.eachMapping(function (mapping) { assert.ok(mapping.generatedLine >= previousLine); - if (mapping.source) { - assert.equal(mapping.source.indexOf(util.testMap.sourceRoot), 0); - } - if (mapping.generatedLine === previousLine) { assert.ok(mapping.generatedColumn >= previousColumn); previousColumn = mapping.generatedColumn; @@ -149,112 +144,6 @@ define("test/source-map/test-source-map-consumer", ["require", "exports", "modul }, 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() { runSourceMapTests('test/source-map/test-source-map-consumer', do_throw); diff --git a/toolkit/devtools/sourcemap/tests/unit/test_source_map_generator.js b/toolkit/devtools/sourcemap/tests/unit/test_source_map_generator.js index 4811438935dc..e585755e22d2 100644 --- a/toolkit/devtools/sourcemap/tests/unit/test_source_map_generator.js +++ b/toolkit/devtools/sourcemap/tests/unit/test_source_map_generator.js @@ -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) { 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) { var map = new SourceMapGenerator({ @@ -179,100 +176,19 @@ define("test/source-map/test-source-map-generator", ["require", "exports", "modu map = JSON.parse(map.toString()); - util.assertEqualMaps(assert, map, util.testMap); - }; - - exports['test that source content can be set'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'min.js', - sourceRoot: '/the/root' - }); - 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.version, 3); + assert.equal(map.file, 'min.js'); + assert.equal(map.names.length, 3); + assert.equal(map.names[0], 'bar'); + assert.equal(map.names[1], 'baz'); + assert.equal(map.names[2], 'n'); + assert.equal(map.sources.length, 2); assert.equal(map.sources[0], 'one.js'); assert.equal(map.sources[1], 'two.js'); - assert.equal(map.sourcesContent[0], 'one file content'); - assert.equal(map.sourcesContent[1], null); + assert.equal(map.sourceRoot, '/the/root'); + 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() { runSourceMapTests('test/source-map/test-source-map-generator', do_throw); diff --git a/toolkit/devtools/sourcemap/tests/unit/test_source_node.js b/toolkit/devtools/sourcemap/tests/unit/test_source_node.js index 5b0163282a05..afdbc781d9d4 100644 --- a/toolkit/devtools/sourcemap/tests/unit/test_source_node.js +++ b/toolkit/devtools/sourcemap/tests/unit/test_source_node.js @@ -136,10 +136,7 @@ define("test/source-map/test-source-node", ["require", "exports", "module"], fun exports['test .toStringWithSourceMap()'] = function (assert, util) { var node = new SourceNode(null, null, null, ['(function () {\n', - ' ', - new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'), - new SourceNode(1, 8, 'a.js', '()'), - ';\n', + ' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n', ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', '}());']); var map = node.toStringWithSourceMap({ @@ -151,14 +148,6 @@ define("test/source-map/test-source-node", ["require", "exports", "module"], fun 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({ line: 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.line, 1); assert.equal(actual.column, 0); - assert.equal(actual.name, 'originalCall'); actual = map.originalPositionFor({ 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.line, 2); 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() { runSourceMapTests('test/source-map/test-source-node', do_throw);