зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1317962 - use source maps in stack traces in the console; r=jryans
MozReview-Commit-ID: 9SPZDi50XZv --HG-- extra : rebase_source : 86ba1dbdc32a02d3ac46e3fc0f1cf2063b2a2291
This commit is contained in:
Родитель
20f27ffe75
Коммит
cdba52c5a8
|
@ -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");
|
||||
});
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ support-files =
|
|||
[test_notification_box_03.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,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче