Source code

Revision control

Copy as Markdown

Other Tools

/* 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";
// React & Redux
const {
createFactory,
const {
MESSAGE_TYPE,
const Message = createFactory(
);
JSTracerTrace.displayName = "JSTracerTrace";
JSTracerTrace.propTypes = {
dispatch: PropTypes.func.isRequired,
message: PropTypes.object.isRequired,
serviceContainer: PropTypes.object.isRequired,
timestampsVisible: PropTypes.bool.isRequired,
maybeScrollToBottom: PropTypes.func,
};
function JSTracerTrace(props) {
const {
dispatch,
message,
serviceContainer,
timestampsVisible,
repeat,
maybeScrollToBottom,
setExpanded,
} = props;
const {
// List of common attributes for all tracer messages
timeStamp,
prefix,
depth,
source,
// Attribute specific to DOM event
eventName,
// Attributes specific to function calls
frame,
implementation,
displayName,
parameters,
// Attributes specific to function call returns
returnedValue,
relatedTraceId,
// See tracer.sys.mjs FRAME_EXIT_REASONS
why,
// Attributes specific to DOM Mutations
mutationType,
mutationElement,
} = message;
let messageBodyConfig;
if (parameters || why || mutationType) {
messageBodyConfig = {
dispatch,
serviceContainer,
maybeScrollToBottom,
setExpanded,
type: "",
useQuotes: true,
// Disable custom formatter for now in traces
customFormat: false,
};
}
// When we are logging a DOM event, we have the `eventName` defined.
let messageBody;
if (eventName) {
messageBody = [dom.span({ className: "jstracer-dom-event" }, eventName)];
} else if (typeof relatedTraceId == "number") {
messageBody = [
dom.span({ className: "jstracer-io" }, "⟵ "),
dom.span({ className: "jstracer-display-name" }, displayName),
];
} else if (mutationType) {
messageBody = [
dom.span(
{ className: "jstracer-dom-mutation" },
// Add an extra space at the end to have nice copy-paste messages
"— DOM Mutation | " + mutationType + " "
),
formatRep(messageBodyConfig, mutationElement),
];
} else if (displayName) {
messageBody = [
dom.span({ className: "jstracer-io" }, "⟶ "),
dom.span({ className: "jstracer-implementation" }, implementation),
// Add a space in order to improve copy paste rendering
dom.span({ className: "jstracer-display-name" }, " " + displayName),
];
} else {
messageBody = [dom.span({ className: "jstracer-io" }, "—")];
}
// Arguments will only be passed on-demand
if (parameters) {
messageBody.push("(", ...formatReps(messageBodyConfig, parameters), ")");
}
// Returned value will also only be passed on-demand
if (why) {
messageBody.push(
// Add a spaces in order to improve copy paste rendering
dom.span({ className: "jstracer-exit-frame-reason" }, " " + why + " ")
);
if (returnedValue !== undefined) {
messageBody.push(formatRep(messageBodyConfig, returnedValue));
}
}
if (prefix) {
messageBody.unshift(
dom.span(
{
className: "console-message-prefix",
},
`${prefix}`
)
);
}
const topLevelClasses = ["cm-s-mozilla"];
return Message({
collapsible: false,
source,
level: MESSAGE_TYPE.JSTRACER,
topLevelClasses,
messageBody,
repeat,
frame,
stacktrace: null,
attachment: null,
serviceContainer,
dispatch,
indent: depth,
timeStamp,
timestampsVisible,
parameters,
message,
maybeScrollToBottom,
});
}
/**
* Generated the list of GripMessageBody for a list of objects.
* GripMessageBody is Rep's rendering for a given Object, via its object actor's front.
*/
function formatReps(messageBodyConfig, objects) {
const elements = [];
const length = objects.length;
for (let i = 0; i < length; i++) {
elements.push(formatRep(messageBodyConfig, objects[i], i));
// We need to interleave a comma if we are not on the last element
if (i !== length - 1) {
elements.push(", ");
}
}
return elements;
}
function formatRep(messageBodyConfig, grip, key) {
return GripMessageBody({
...messageBodyConfig,
grip,
key,
});
}
module.exports = JSTracerTrace;