Bug 1107541 - Display eval sources with a sourceURL pragma correctly in the debugger. r=fitzgen

This commit is contained in:
James Long 2014-12-09 15:00:00 -05:00
parent f408149257
commit e78a300772
9 changed files with 121 additions and 21 deletions

View File

@ -171,7 +171,7 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
let url = fullUrl.split(" -> ").pop();
let label = aSource.addonPath ? aSource.addonPath : SourceUtils.getSourceLabel(url);
if (aSource.introductionUrl) {
if (!aSource.url && aSource.introductionUrl) {
label += ' > eval';
}

View File

@ -405,7 +405,9 @@ skip-if = e10s && debug
skip-if = e10s # Bug 1093535
[browser_dbg_sources-cache.js]
skip-if = e10s && debug
[browser_dbg_sources-eval.js]
[browser_dbg_sources-eval-01.js]
skip-if = e10s && debug
[browser_dbg_sources-eval-02.js]
skip-if = e10s && debug
[browser_dbg_sources-labels.js]
skip-if = e10s && debug

View File

@ -18,15 +18,8 @@ function test() {
gSources = gDebugger.DebuggerView.Sources;
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
waitForSourceShown(gPanel, "-eval.js")
.then(run)
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
function run() {
return Task.spawn(function*() {
yield waitForSourceShown(gPanel, "-eval.js");
is(gSources.values.length, 1, "Should have 1 source");
let newSource = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.NEW_SOURCE);
@ -37,5 +30,5 @@ function test() {
yield closeDebuggerAndFinish(gPanel);
});
}
});
}

View File

@ -0,0 +1,47 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure eval scripts with the sourceURL pragma are correctly
* displayed
*/
const TAB_URL = EXAMPLE_URL + "doc_script-eval.html";
function test() {
let gTab, gPanel, gDebugger;
let gSources, gBreakpoints, gEditor;
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
gTab = aTab;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gSources = gDebugger.DebuggerView.Sources;
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
gEditor = gDebugger.DebuggerView.editor;
return Task.spawn(function*() {
yield waitForSourceShown(gPanel, "-eval.js");
is(gSources.values.length, 1, "Should have 1 source");
let newSource = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.NEW_SOURCE);
callInTab(gTab, "evalSourceWithSourceURL");
yield newSource;
is(gSources.values.length, 2, "Should have 2 sources");
let item = gSources.getItemForAttachment(e => e.label == "bar.js");
ok(item, "Source label is incorrect.");
ok(item.attachment.group === 'http://example.com', 'Source group is incorrect');
let shown = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN);
gSources.selectedItem = item;
yield shown;
ok(gEditor.getText().indexOf('bar = function() {') === 0,
'Correct source is shown');
yield closeDebuggerAndFinish(gPanel);
});
});
}

View File

@ -4,3 +4,7 @@ var bar;
function evalSource() {
eval('bar = function() {\nvar x = 5;\n}');
}
function evalSourceWithSourceURL() {
eval('bar = function() {\nvar x = 6;\n} //# sourceURL=bar.js');
}

View File

@ -13,5 +13,4 @@
<script type="text/javascript" src="code_script-eval.js"></script>
</body>
</html>

View File

@ -34,6 +34,7 @@ EXTRA_JS_MODULES.devtools += [
'event-emitter.js',
'event-parsers.js',
'output-parser.js',
'path.js',
'touch-events.js',
'worker-loader.js',
]

38
toolkit/devtools/path.js Normal file
View File

@ -0,0 +1,38 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Services = require("Services");
/*
* Returns the directory name of the path
*/
exports.dirname = path => {
return Services.io.newURI(
".", null, Services.io.newURI(path, null, null)).spec;
}
/*
* Join all the arguments together and normalize the resulting URI.
* The initial path must be an full URI with a protocol (i.e. http://).
*/
exports.joinURI = (initialPath, ...paths) => {
let uri;
try {
uri = Services.io.newURI(initialPath, null, null);
}
catch(e) {
return;
}
for(let path of paths) {
if(path) {
uri = Services.io.newURI(path, null, uri);
}
}
return uri.spec;
}

View File

@ -12,6 +12,7 @@ const { ActorPool, getOffsetColumn } = require("devtools/server/actors/common");
const { DebuggerServer } = require("devtools/server/main");
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
const { dbg_assert, dumpn, update, fetch } = DevToolsUtils;
const { dirname, joinURI } = require("devtools/toolkit/path");
const { SourceMapConsumer, SourceMapGenerator } = require("source-map");
const promise = require("promise");
const PromiseDebugging = require("PromiseDebugging");
@ -5373,7 +5374,9 @@ ThreadSources.prototype = {
* Only to be used when we aren't source mapping.
*/
_sourceForScript: function (aScript) {
let url = getSourceURL(aScript.source);
// Don't use getSourceURL because we don't want to consider the
// displayURL property if it's an eval source
let url = isEvalSource(aScript.source) ? null : aScript.source.url;
let spec = {
source: aScript.source
};
@ -5864,17 +5867,30 @@ function getSymbolName(symbol) {
return name || undefined;
}
function getSourceURL(source) {
function isEvalSource(source) {
let introType = source.introductionType;
// These are all the sources that are essentially eval-ed (either
// by calling eval or passing a string to one of these functions).
// Current these have a `url` property when the shouldn't, so
// forcefully only consider displayURL
if (introType === 'eval' ||
introType === 'Function' ||
introType === 'eventHandler' ||
introType === 'setTimeout' ||
introType === 'setInterval') {
return (introType === 'eval' ||
introType === 'Function' ||
introType === 'eventHandler' ||
introType === 'setTimeout' ||
introType === 'setInterval');
}
function getSourceURL(source) {
if(isEvalSource(source)) {
// Eval sources have no urls, but they might have a `displayURL`
// created with the sourceURL pragma. If the introduction script
// is a non-eval script, generate an full absolute URL relative to it.
if(source.displayURL &&
source.introductionScript &&
!isEvalSource(source.introductionScript.source)) {
return joinURI(dirname(source.introductionScript.source.url),
source.displayURL);
}
return source.displayURL;
}
return source.url;