Bug 1317962 - use source maps in stack traces in the console; r=jryans

MozReview-Commit-ID: 9SPZDi50XZv

--HG--
extra : rebase_source : e8d9e5eaeb0de0f18b34eae13499d394df696f52
This commit is contained in:
Tom Tromey 2017-05-02 12:51:51 -06:00
Родитель 4e93490c73
Коммит 9f4ebe5770
13 изменённых файлов: 142 добавлений и 15 удалений

Просмотреть файл

@ -83,7 +83,13 @@ SourceMapURLService.prototype.originalPositionFor = async function (url, line, c
await this._sourceMapService.getOriginalURLs(urlInfo);
const location = { sourceId: urlInfo.id, line, column, sourceUrl: url };
let resolvedLocation = await this._sourceMapService.getOriginalLocation(location);
return resolvedLocation === location ? null : resolvedLocation;
if (!resolvedLocation ||
(resolvedLocation.line === location.line &&
resolvedLocation.column === location.column &&
resolvedLocation.sourceUrl === location.sourceUrl)) {
return null;
}
return resolvedLocation;
};
exports.SourceMapURLService = SourceMapURLService;

Просмотреть файл

@ -35,13 +35,16 @@ const StackTrace = createClass({
stacktrace: PropTypes.array.isRequired,
onViewSourceInDebugger: PropTypes.func.isRequired,
onViewSourceInScratchpad: PropTypes.func,
// Service to enable the source map feature.
sourceMapService: PropTypes.object,
},
render() {
let {
stacktrace,
onViewSourceInDebugger,
onViewSourceInScratchpad
onViewSourceInScratchpad,
sourceMapService,
} = this.props;
let frames = [];
@ -67,7 +70,8 @@ const StackTrace = createClass({
showFullSourceUrl: true,
onClick: (/^Scratchpad\/\d+$/.test(source))
? onViewSourceInScratchpad
: onViewSourceInDebugger
: onViewSourceInDebugger,
sourceMapService,
}), "\n");
});

Просмотреть файл

@ -11,6 +11,7 @@ support-files =
[test_searchbox-with-autocomplete.html]
[test_sidebar_toggle.html]
[test_stack-trace.html]
[test_stack-trace-source-maps.html]
[test_tabs_accessibility.html]
[test_tabs_menu.html]
[test_tree_01.html]

Просмотреть файл

@ -0,0 +1,105 @@
<!-- 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/. -->
<!DOCTYPE HTML>
<html>
<!--
Test the rendering of a stack trace with source maps
-->
<head>
<meta charset="utf-8">
<title>StackTrace component test</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script src="head.js"></script>
<script>
/* import-globals-from head.js */
"use strict";
window.onload = function () {
let ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
let React = browserRequire("devtools/client/shared/vendor/react");
let StackTrace = React.createFactory(
browserRequire("devtools/client/shared/components/stack-trace")
);
ok(StackTrace, "Got the StackTrace factory");
add_task(function* () {
let stacktrace = [
{
filename: "https://bugzilla.mozilla.org/bundle.js",
lineNumber: 99,
columnNumber: 10
},
{
functionName: "loadFunc",
filename: "https://bugzilla.mozilla.org/bundle.js",
lineNumber: 108,
}
];
let props = {
stacktrace,
onViewSourceInDebugger: () => {},
onViewSourceInScratchpad: () => {},
// A mock source map service.
sourceMapService: {
originalPositionFor: function (url, line, column) {
let newLine = line === 99 ? 1 : 7;
// Return a phony promise-like thing that resolves
// immediately.
return {
then: function (consequence) {
consequence({
sourceId: "whatever",
sourceUrl: "https://bugzilla.mozilla.org/original.js",
line: newLine,
column,
});
},
};
}
},
};
let trace = ReactDOM.render(StackTrace(props), window.document.body);
yield forceRender(trace);
let traceEl = ReactDOM.findDOMNode(trace);
ok(traceEl, "Rendered StackTrace has an element");
// Get the child nodes and filter out the text-only whitespace ones
let frameEls = Array.from(traceEl.childNodes)
.filter(n => n.className && n.className.includes("frame"));
ok(frameEls, "Rendered StackTrace has frames");
is(frameEls.length, 2, "StackTrace has 2 frames");
checkFrameString({
el: frameEls[0],
functionName: "<anonymous>",
source: "https://bugzilla.mozilla.org/original.js",
file: "original.js",
line: 1,
column: 10,
shouldLink: true,
tooltip: "View source in Debugger → https://bugzilla.mozilla.org/original.js:1:10",
});
checkFrameString({
el: frameEls[1],
functionName: "loadFunc",
source: "https://bugzilla.mozilla.org/original.js",
file: "original.js",
line: 7,
column: null,
shouldLink: true,
tooltip: "View source in Debugger → https://bugzilla.mozilla.org/original.js:7",
});
});
};
</script>
</body>
</html>

Просмотреть файл

@ -3556,9 +3556,12 @@ Widgets.Stacktrace.prototype = extend(Widgets.BaseWidget.prototype, {
result.className = "stacktrace devtools-monospace";
if (this.stacktrace) {
const target = this.message.output.toolboxTarget;
const toolbox = gDevTools.getToolbox(target);
this.output.owner.ReactDOM.render(this.output.owner.StackTraceView({
stacktrace: this.stacktrace,
onViewSourceInDebugger: frame => this.output.openLocationInDebugger(frame)
onViewSourceInDebugger: frame => this.output.openLocationInDebugger(frame),
sourceMapService: toolbox ? toolbox.sourceMapURLService : null,
}), result);
}

Просмотреть файл

@ -38,7 +38,9 @@ var NetInfoBody = React.createClass({
data: PropTypes.shape({
request: PropTypes.object.isRequired,
response: PropTypes.object.isRequired
})
}),
// Service to enable the source map feature.
sourceMapService: PropTypes.object,
},
displayName: "NetInfoBody",
@ -76,7 +78,7 @@ var NetInfoBody = React.createClass({
},
getTabPanels() {
let actions = this.props.actions;
let { actions, sourceMapService } = this.props;
let data = this.state.data;
let {request} = data;
@ -153,7 +155,8 @@ var NetInfoBody = React.createClass({
title: Locale.$STR("netRequest.callstack")},
StackTraceTab({
data: data,
actions: actions
actions: actions,
sourceMapService: sourceMapService,
})
)
);

Просмотреть файл

@ -13,15 +13,17 @@ const StackTraceTab = createClass({
data: PropTypes.object.isRequired,
actions: PropTypes.shape({
onViewSourceInDebugger: PropTypes.func.isRequired
})
}),
// Service to enable the source map feature.
sourceMapService: PropTypes.object,
},
render() {
let { stacktrace } = this.props.data.cause;
let { actions } = this.props;
let { actions, sourceMapService } = this.props;
let onViewSourceInDebugger = actions.onViewSourceInDebugger.bind(actions);
return StackTrace({ stacktrace, onViewSourceInDebugger });
return StackTrace({ stacktrace, onViewSourceInDebugger, sourceMapService });
}
});

Просмотреть файл

@ -163,7 +163,8 @@ NetRequest.prototype = {
// As soon as Redux is in place state and actions will come from
// separate modules.
let body = NetInfoBody({
actions: this
actions: this,
sourceMapService: this.owner.sourceMapURLService,
});
// Render net info body!

Просмотреть файл

@ -30,6 +30,7 @@ const ConsoleOutput = createClass({
serviceContainer: PropTypes.shape({
attachRefToHud: PropTypes.func.isRequired,
openContextMenu: PropTypes.func.isRequired,
sourceMapService: PropTypes.object,
}),
autoscroll: PropTypes.bool.isRequired,
dispatch: PropTypes.func.isRequired,

Просмотреть файл

@ -20,6 +20,7 @@ ConsoleCommand.propTypes = {
autoscroll: PropTypes.bool.isRequired,
indent: PropTypes.number.isRequired,
timestampsVisible: PropTypes.bool.isRequired,
serviceContainer: PropTypes.object,
};
ConsoleCommand.defaultProps = {
@ -35,6 +36,7 @@ function ConsoleCommand(props) {
indent,
message,
timestampsVisible,
serviceContainer,
} = props;
const {
@ -44,10 +46,6 @@ function ConsoleCommand(props) {
messageText: messageBody,
} = message;
const {
serviceContainer,
} = props;
return Message({
source,
type,

Просмотреть файл

@ -20,6 +20,7 @@ EvaluationResult.propTypes = {
message: PropTypes.object.isRequired,
indent: PropTypes.number.isRequired,
timestampsVisible: PropTypes.bool.isRequired,
serviceContainer: PropTypes.object,
};
EvaluationResult.defaultProps = {

Просмотреть файл

@ -20,6 +20,7 @@ PageError.propTypes = {
open: PropTypes.bool,
indent: PropTypes.number.isRequired,
timestampsVisible: PropTypes.bool.isRequired,
serviceContainer: PropTypes.object,
};
PageError.defaultProps = {

Просмотреть файл

@ -148,6 +148,7 @@ const Message = createClass({
stacktrace: stacktrace,
onViewSourceInDebugger: serviceContainer.onViewSourceInDebugger,
onViewSourceInScratchpad: serviceContainer.onViewSourceInScratchpad,
sourceMapService: serviceContainer.sourceMapService,
})
);
}