Bug 1416201 - HTTP request stack trace should be lazy loaded;r=rickychien

MozReview-Commit-ID: 5SWLLcNqORz

--HG--
extra : rebase_source : 400e5d48848b087f8965652df6b9c37686fb4b40
This commit is contained in:
Jan Odvarko 2017-11-23 13:35:04 +01:00
Родитель c5440617e9
Коммит 3bd627cefb
6 изменённых файлов: 134 добавлений и 30 удалений

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

@ -4,7 +4,7 @@
"use strict";
const { createFactory } = require("devtools/client/shared/vendor/react");
const { Component, createFactory } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
@ -17,35 +17,75 @@ const StackTrace = createFactory(require("devtools/client/shared/components/Stac
* This component represents a side panel responsible for
* rendering stack-trace info for selected request.
*/
function StackTracePanel({
connector,
openLink,
request,
sourceMapService,
}) {
let { stacktrace } = request.cause;
class StackTracePanel extends Component {
static get propTypes() {
return {
connector: PropTypes.object.isRequired,
request: PropTypes.object.isRequired,
sourceMapService: PropTypes.object,
openLink: PropTypes.func,
};
}
return (
div({ className: "panel-container" },
StackTrace({
stacktrace,
onViewSourceInDebugger: ({ url, line }) => {
return connector.viewSourceInDebugger(url, line);
},
sourceMapService,
openLink,
}),
)
);
/**
* `componentDidMount` is called when opening the StackTracePanel
* for the first time
*/
componentDidMount() {
this.maybeFetchStackTrace(this.props);
}
/**
* `componentWillReceiveProps` is the only method called when
* switching between two requests while this panel is displayed.
*/
componentWillReceiveProps(nextProps) {
this.maybeFetchStackTrace(nextProps);
}
/**
* When switching to another request, lazily fetch stack-trace
* from the backend. This Panel will first be empty and then
* display the content.
*/
maybeFetchStackTrace(props) {
// Fetch stack trace only if it's available and not yet
// on the client.
if (!props.request.stacktrace &&
props.request.cause.stacktraceAvailable) {
// This method will set `props.request.stacktrace`
// asynchronously and force another render.
props.connector.requestData(props.request.id, "stackTrace");
}
}
// Rendering
render() {
let {
connector,
openLink,
request,
sourceMapService,
} = this.props;
let {
stacktrace = []
} = request;
return (
div({ className: "panel-container" },
StackTrace({
stacktrace,
onViewSourceInDebugger: ({ url, line }) => {
return connector.viewSourceInDebugger(url, line);
},
sourceMapService,
openLink,
}),
)
);
}
}
StackTracePanel.displayName = "StackTracePanel";
StackTracePanel.propTypes = {
connector: PropTypes.object.isRequired,
request: PropTypes.object.isRequired,
sourceMapService: PropTypes.object,
openLink: PropTypes.func,
};
module.exports = StackTracePanel;

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

@ -84,7 +84,7 @@ function TabboxPanel({
},
TimingsPanel({ request }),
),
request.cause && request.cause.stacktrace && request.cause.stacktrace.length > 0 &&
request.cause && request.cause.stacktraceAvailable &&
TabPanel({
id: PANELS.STACK_TRACE,
title: STACK_TRACE_TITLE,

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

@ -66,6 +66,12 @@ class FirefoxDataProvider {
url,
isXHR,
cause,
// Compatibility code to support Firefox 58 and earlier that always
// send stack-trace immediately on networkEvent message.
// FF59+ supports fetching the traces lazily via requestData.
stacktrace: cause.stacktrace,
fromCache,
fromServiceWorker},
true,
@ -661,6 +667,19 @@ class FirefoxDataProvider {
emit(EVENTS.RECEIVED_EVENT_TIMINGS, response.from);
});
}
/**
* Handles information received for a "stackTrace" packet.
*
* @param {object} response the message received from the server.
*/
onStackTrace(response) {
return this.updateRequest(response.from, {
stacktrace: response.stacktrace
}).then(() => {
emit(EVENTS.RECEIVED_EVENT_STACKTRACE, response.from);
});
}
}
/**

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

@ -93,6 +93,9 @@ const EVENTS = {
UPDATING_RESPONSE_CONTENT: "NetMonitor:NetworkEventUpdating:ResponseContent",
RECEIVED_RESPONSE_CONTENT: "NetMonitor:NetworkEventUpdated:ResponseContent",
// When stack-trace finishes receiving.
RECEIVED_EVENT_STACKTRACE: "NetMonitor:NetworkEventUpdated:StackTrace",
// Fired once the connection is established
CONNECTED: "connected",
@ -126,6 +129,7 @@ const UPDATE_PROPS = [
"responseContent",
"responseContentAvailable",
"formDataSections",
"stacktrace",
];
const PANELS = {

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

@ -1936,6 +1936,7 @@ function NetworkEventActor(webConsoleActor) {
};
this._timings = {};
this._stackTrace = {};
// Keep track of LongStringActors owned by this NetworkEventActor.
this._longStringActors = new Set();
@ -2008,6 +2009,14 @@ NetworkEventActor.prototype =
this._fromCache = networkEvent.fromCache;
this._fromServiceWorker = networkEvent.fromServiceWorker;
// Stack trace info isn't sent automatically. The client
// needs to request it explicitly using getStackTrace
// packet.
this._stackTrace = networkEvent.cause.stacktrace;
delete networkEvent.cause.stacktrace;
networkEvent.cause.stacktraceAvailable =
!!(this._stackTrace && this._stackTrace.length);
for (let prop of ["method", "url", "httpVersion", "headersSize"]) {
this._request[prop] = networkEvent[prop];
}
@ -2129,6 +2138,19 @@ NetworkEventActor.prototype =
};
},
/**
* The "getStackTrace" packet type handler.
*
* @return object
* The response packet - stack trace.
*/
onGetStackTrace: function () {
return {
from: this.actorID,
stacktrace: this._stackTrace,
};
},
/** ****************************************************************
* Listeners for new network event data coming from NetworkMonitor.
******************************************************************/
@ -2377,4 +2399,5 @@ NetworkEventActor.prototype.requestTypes =
"getResponseContent": NetworkEventActor.prototype.onGetResponseContent,
"getEventTimings": NetworkEventActor.prototype.onGetEventTimings,
"getSecurityInfo": NetworkEventActor.prototype.onGetSecurityInfo,
"getStackTrace": NetworkEventActor.prototype.onGetStackTrace,
};

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

@ -566,6 +566,24 @@ WebConsoleClient.prototype = {
return this._client.request(packet, onResponse);
},
/**
* Retrieve the stack-trace information for the given NetworkEventActor.
*
* @param string actor
* The NetworkEventActor ID.
* @param function onResponse
* The function invoked when the stack-trace is received.
* @return request
* Request object that implements both Promise and EventEmitter interfaces
*/
getStackTrace: function (actor, onResponse) {
let packet = {
to: actor,
type: "getStackTrace",
};
return this._client.request(packet, onResponse);
},
/**
* Send a HTTP request with the given data.
*