--- a/devtools/client/webconsole/new-console-output/components/collapse-button.js
+++ b/devtools/client/webconsole/new-console-output/components/collapse-button.js
@@ -3,49 +3,35 @@
/* 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 {
- createClass,
DOM: dom,
- PropTypes,
} = require("devtools/client/shared/vendor/react");
const { l10n } = require("devtools/client/webconsole/new-console-output/utils/messages");
-
-const CollapseButton = createClass({
-
- displayName: "CollapseButton",
+const messageToggleDetails = l10n.getStr("messageToggleDetails");
- propTypes: {
- onClick: PropTypes.func.isRequired,
- open: PropTypes.bool.isRequired,
- title: PropTypes.string,
- },
+function CollapseButton(props) {
+ const {
+ open,
+ onClick,
+ title = messageToggleDetails,
+ } = props;
- getDefaultProps: function () {
- return {
- title: l10n.getStr("messageToggleDetails")
- };
- },
+ let classes = ["theme-twisty"];
- render: function () {
- const { open, onClick, title } = this.props;
-
- let classes = ["theme-twisty"];
+ if (open) {
+ classes.push("open");
+ }
- if (open) {
- classes.push("open");
- }
-
- return dom.a({
- className: classes.join(" "),
- onClick,
- title: title,
- });
- }
-});
+ return dom.a({
+ className: classes.join(" "),
+ onClick,
+ title: title,
+ });
+}
module.exports = CollapseButton;
--- a/devtools/client/webconsole/new-console-output/components/console-output.js
+++ b/devtools/client/webconsole/new-console-output/components/console-output.js
@@ -96,29 +96,24 @@ const ConsoleOutput = createClass({
dispatch,
message,
key: message.id,
serviceContainer,
open: messagesUi.includes(message.id),
tableData: messagesTableData.get(message.id),
autoscroll,
indent: parentGroups.length,
+ timestampsVisible,
})
);
});
- let classList = ["webconsole-output"];
-
- if (!timestampsVisible) {
- classList.push("hideTimestamps");
- }
-
return (
dom.div({
- className: classList.join(" "),
+ className: "webconsole-output",
onContextMenu: this.onContextMenu,
ref: node => {
this.outputNode = node;
},
}, messageNodes
)
);
}
--- a/devtools/client/webconsole/new-console-output/components/grip-message-body.js
+++ b/devtools/client/webconsole/new-console-output/components/grip-message-body.js
@@ -9,21 +9,20 @@
// If this is being run from Mocha, then the browser loader hasn't set up
// define. We need to do that before loading Rep.
if (typeof define === "undefined") {
require("amd-loader");
}
// React
const {
- createFactory,
PropTypes
} = require("devtools/client/shared/vendor/react");
-const VariablesViewLink = createFactory(require("devtools/client/webconsole/new-console-output/components/variables-view-link"));
+const VariablesViewLink = require("devtools/client/webconsole/new-console-output/components/variables-view-link");
const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
const Rep = REPS.Rep;
const Grip = REPS.Grip;
const StringRep = REPS.StringRep.rep;
GripMessageBody.displayName = "GripMessageBody";
@@ -89,33 +88,33 @@ function GripMessageBody(props) {
onDOMNodeMouseOut,
onInspectIconClick,
defaultRep: Grip,
mode: props.mode,
})
);
}
-function cleanupStyle(userProvidedStyle, createElement) {
- // Regular expression that matches the allowed CSS property names.
- const allowedStylesRegex = new RegExp(
- "^(?:-moz-)?(?:background|border|box|clear|color|cursor|display|float|font|line|" +
- "margin|padding|text|transition|outline|white-space|word|writing|" +
- "(?:min-|max-)?width|(?:min-|max-)?height)"
- );
+// Regular expression that matches the allowed CSS property names.
+const allowedStylesRegex = new RegExp(
+ "^(?:-moz-)?(?:background|border|box|clear|color|cursor|display|float|font|line|" +
+ "margin|padding|text|transition|outline|white-space|word|writing|" +
+ "(?:min-|max-)?width|(?:min-|max-)?height)"
+);
- // Regular expression that matches the forbidden CSS property values.
- const forbiddenValuesRegexs = [
- // url(), -moz-element()
- /\b(?:url|(?:-moz-)?element)[\s('"]+/gi,
+// Regular expression that matches the forbidden CSS property values.
+const forbiddenValuesRegexs = [
+ // url(), -moz-element()
+ /\b(?:url|(?:-moz-)?element)[\s('"]+/gi,
- // various URL protocols
- /['"(]*(?:chrome|resource|about|app|data|https?|ftp|file):+\/*/gi,
- ];
+ // various URL protocols
+ /['"(]*(?:chrome|resource|about|app|data|https?|ftp|file):+\/*/gi,
+];
+function cleanupStyle(userProvidedStyle, createElement) {
// Use a dummy element to parse the style string.
let dummy = createElement("div");
dummy.style = userProvidedStyle;
// Return a style object as expected by React DOM components, e.g.
// {color: "red"}
// without forbidden properties and values.
return [...dummy.style]
--- a/devtools/client/webconsole/new-console-output/components/message-container.js
+++ b/devtools/client/webconsole/new-console-output/components/message-container.js
@@ -4,17 +4,17 @@
* 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 {
createClass,
- createFactory,
+
PropTypes
} = require("devtools/client/shared/vendor/react");
const {
MESSAGE_SOURCE,
MESSAGE_TYPE
} = require("devtools/client/webconsole/new-console-output/constants");
@@ -32,39 +32,47 @@ const MessageContainer = createClass({
propTypes: {
message: PropTypes.object.isRequired,
open: PropTypes.bool.isRequired,
serviceContainer: PropTypes.object.isRequired,
autoscroll: PropTypes.bool.isRequired,
indent: PropTypes.number.isRequired,
tableData: PropTypes.object,
+ timestampsVisible: PropTypes.bool.isRequired,
},
getDefaultProps: function () {
return {
open: false,
indent: 0,
};
},
shouldComponentUpdate(nextProps, nextState) {
const repeatChanged = this.props.message.repeat !== nextProps.message.repeat;
const openChanged = this.props.open !== nextProps.open;
const tableDataChanged = this.props.tableData !== nextProps.tableData;
const responseChanged = this.props.message.response !== nextProps.message.response;
const totalTimeChanged = this.props.message.totalTime !== nextProps.message.totalTime;
- return repeatChanged || openChanged || tableDataChanged || responseChanged ||
- totalTimeChanged;
+ const timestampVisibleChanged =
+ this.props.timestampsVisible !== nextProps.timestampsVisible;
+
+ return repeatChanged
+ || openChanged
+ || tableDataChanged
+ || responseChanged
+ || totalTimeChanged
+ || timestampVisibleChanged;
},
render() {
const { message } = this.props;
- let MessageComponent = createFactory(getMessageComponent(message));
+ let MessageComponent = getMessageComponent(message);
return MessageComponent(this.props);
}
});
function getMessageComponent(message) {
switch (message.source) {
case MESSAGE_SOURCE.CONSOLE_API:
return componentMap.get("ConsoleApiCall");
--- a/devtools/client/webconsole/new-console-output/components/message-icon.js
+++ b/devtools/client/webconsole/new-console-output/components/message-icon.js
@@ -18,15 +18,15 @@ MessageIcon.displayName = "MessageIcon";
MessageIcon.propTypes = {
level: PropTypes.string.isRequired,
};
function MessageIcon(props) {
const { level } = props;
const title = l10n.getStr("level." + level);
- return dom.div({
+ return dom.span({
className: "icon",
title
});
}
module.exports = MessageIcon;
--- a/devtools/client/webconsole/new-console-output/components/message-indent.js
+++ b/devtools/client/webconsole/new-console-output/components/message-indent.js
@@ -3,35 +3,25 @@
/* 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 {
- createClass,
DOM: dom,
- PropTypes,
} = require("devtools/client/shared/vendor/react");
const INDENT_WIDTH = 12;
-const MessageIndent = createClass({
- displayName: "MessageIndent",
-
- propTypes: {
- indent: PropTypes.number.isRequired,
- },
-
- render: function () {
- const { indent } = this.props;
- return dom.span({
- className: "indent",
- style: {"width": indent * INDENT_WIDTH}
- });
- }
-});
+function MessageIndent(props) {
+ const { indent } = props;
+ return dom.span({
+ className: "indent",
+ style: {"width": indent * INDENT_WIDTH}
+ });
+}
module.exports.MessageIndent = MessageIndent;
// Exported so we can test it with unit tests.
module.exports.INDENT_WIDTH = INDENT_WIDTH;
--- a/devtools/client/webconsole/new-console-output/components/message-repeat.js
+++ b/devtools/client/webconsole/new-console-output/components/message-repeat.js
@@ -9,28 +9,30 @@
// React & Redux
const {
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
const { PluralForm } = require("devtools/shared/plural-form");
const { l10n } = require("devtools/client/webconsole/new-console-output/utils/messages");
+const messageRepeatsTooltip = l10n.getStr("messageRepeats.tooltip2");
MessageRepeat.displayName = "MessageRepeat";
MessageRepeat.propTypes = {
repeat: PropTypes.number.isRequired
};
function MessageRepeat(props) {
const { repeat } = props;
- const visibility = repeat > 1 ? "visible" : "hidden";
+
+ if (!repeat || repeat < 2) {
+ return null;
+ }
return dom.span({
className: "message-repeats",
- style: {visibility},
- title: PluralForm.get(repeat, l10n.getStr("messageRepeats.tooltip2"))
- .replace("#1", repeat)
+ title: PluralForm.get(repeat, messageRepeatsTooltip).replace("#1", repeat)
}, repeat);
}
module.exports = MessageRepeat;
--- a/devtools/client/webconsole/new-console-output/components/message-types/console-api-call.js
+++ b/devtools/client/webconsole/new-console-output/components/message-types/console-api-call.js
@@ -7,44 +7,46 @@
"use strict";
// React & Redux
const {
createFactory,
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
-const GripMessageBody = createFactory(require("devtools/client/webconsole/new-console-output/components/grip-message-body"));
+const GripMessageBody = require("devtools/client/webconsole/new-console-output/components/grip-message-body");
const ConsoleTable = createFactory(require("devtools/client/webconsole/new-console-output/components/console-table"));
const {isGroupType, l10n} = require("devtools/client/webconsole/new-console-output/utils/messages");
const Message = createFactory(require("devtools/client/webconsole/new-console-output/components/message"));
ConsoleApiCall.displayName = "ConsoleApiCall";
ConsoleApiCall.propTypes = {
message: PropTypes.object.isRequired,
open: PropTypes.bool,
serviceContainer: PropTypes.object.isRequired,
indent: PropTypes.number.isRequired,
+ timestampsVisible: PropTypes.bool.isRequired,
};
ConsoleApiCall.defaultProps = {
open: false,
indent: 0,
};
function ConsoleApiCall(props) {
const {
dispatch,
message,
open,
tableData,
serviceContainer,
indent,
+ timestampsVisible,
} = props;
const {
id: messageId,
source,
type,
level,
repeat,
stacktrace,
@@ -103,16 +105,17 @@ function ConsoleApiCall(props) {
repeat,
frame,
stacktrace,
attachment,
serviceContainer,
dispatch,
indent,
timeStamp,
+ timestampsVisible,
});
}
function formatReps(parameters, userProvidedStyles, serviceContainer) {
return (
parameters
// Get all the grips.
.map((grip, key) => GripMessageBody({
--- a/devtools/client/webconsole/new-console-output/components/message-types/console-command.js
+++ b/devtools/client/webconsole/new-console-output/components/message-types/console-command.js
@@ -14,44 +14,51 @@ const {
const Message = createFactory(require("devtools/client/webconsole/new-console-output/components/message"));
ConsoleCommand.displayName = "ConsoleCommand";
ConsoleCommand.propTypes = {
message: PropTypes.object.isRequired,
autoscroll: PropTypes.bool.isRequired,
indent: PropTypes.number.isRequired,
+ timestampsVisible: PropTypes.bool.isRequired,
};
ConsoleCommand.defaultProps = {
indent: 0,
};
/**
* Displays input from the console.
*/
function ConsoleCommand(props) {
- const { autoscroll, indent, message } = props;
+ const {
+ autoscroll,
+ indent,
+ message,
+ timestampsVisible,
+ } = props;
+
const {
source,
type,
level,
messageText: messageBody,
} = message;
const {
serviceContainer,
} = props;
- const childProps = {
+ return Message({
source,
type,
level,
topLevelClasses: [],
messageBody,
scrollToMessage: autoscroll,
serviceContainer,
- indent: indent,
- };
- return Message(childProps);
+ indent,
+ timestampsVisible,
+ });
}
module.exports = ConsoleCommand;
--- a/devtools/client/webconsole/new-console-output/components/message-types/evaluation-result.js
+++ b/devtools/client/webconsole/new-console-output/components/message-types/evaluation-result.js
@@ -7,31 +7,38 @@
"use strict";
// React & Redux
const {
createFactory,
PropTypes
} = require("devtools/client/shared/vendor/react");
const Message = createFactory(require("devtools/client/webconsole/new-console-output/components/message"));
-const GripMessageBody = createFactory(require("devtools/client/webconsole/new-console-output/components/grip-message-body"));
+const GripMessageBody = require("devtools/client/webconsole/new-console-output/components/grip-message-body");
EvaluationResult.displayName = "EvaluationResult";
EvaluationResult.propTypes = {
message: PropTypes.object.isRequired,
indent: PropTypes.number.isRequired,
+ timestampsVisible: PropTypes.bool.isRequired,
};
EvaluationResult.defaultProps = {
indent: 0,
};
function EvaluationResult(props) {
- const { message, serviceContainer, indent } = props;
+ const {
+ message,
+ serviceContainer,
+ indent,
+ timestampsVisible,
+ } = props;
+
const {
source,
type,
level,
id: messageId,
exceptionDocURL,
frame,
timeStamp,
@@ -55,28 +62,28 @@ function EvaluationResult(props) {
serviceContainer,
useQuotes: true,
escapeWhitespace: false,
});
}
const topLevelClasses = ["cm-s-mozilla"];
- const childProps = {
+ return Message({
source,
type,
level,
indent,
topLevelClasses,
messageBody,
messageId,
scrollToMessage: props.autoscroll,
serviceContainer,
exceptionDocURL,
frame,
timeStamp,
parameters,
notes,
- };
- return Message(childProps);
+ timestampsVisible,
+ });
}
module.exports = EvaluationResult;
--- a/devtools/client/webconsole/new-console-output/components/message-types/network-event-message.js
+++ b/devtools/client/webconsole/new-console-output/components/message-types/network-event-message.js
@@ -18,26 +18,28 @@ const { l10n } = require("devtools/clien
NetworkEventMessage.displayName = "NetworkEventMessage";
NetworkEventMessage.propTypes = {
message: PropTypes.object.isRequired,
serviceContainer: PropTypes.shape({
openNetworkPanel: PropTypes.func.isRequired,
}),
indent: PropTypes.number.isRequired,
+ timestampsVisible: PropTypes.bool.isRequired,
};
NetworkEventMessage.defaultProps = {
indent: 0,
};
function NetworkEventMessage({
indent,
message = {},
serviceContainer,
+ timestampsVisible,
}) {
const {
actor,
source,
type,
level,
request,
response: {
@@ -68,23 +70,23 @@ function NetworkEventMessage({
const url = dom.a({ className: "url", title: request.url, onClick: openNetworkMonitor },
request.url.replace(/\?.+/, ""));
const statusBody = statusInfo
? dom.a({ className: "status", onClick: openNetworkMonitor }, statusInfo)
: null;
const messageBody = [method, xhr, url, statusBody];
- const childProps = {
+ return Message({
source,
type,
level,
indent,
topLevelClasses,
timeStamp,
messageBody,
serviceContainer,
request,
- };
- return Message(childProps);
+ timestampsVisible,
+ });
}
module.exports = NetworkEventMessage;
--- a/devtools/client/webconsole/new-console-output/components/message-types/page-error.js
+++ b/devtools/client/webconsole/new-console-output/components/message-types/page-error.js
@@ -14,30 +14,32 @@ const {
const Message = createFactory(require("devtools/client/webconsole/new-console-output/components/message"));
PageError.displayName = "PageError";
PageError.propTypes = {
message: PropTypes.object.isRequired,
open: PropTypes.bool,
indent: PropTypes.number.isRequired,
+ timestampsVisible: PropTypes.bool.isRequired,
};
PageError.defaultProps = {
open: false,
indent: 0,
};
function PageError(props) {
const {
dispatch,
message,
open,
serviceContainer,
indent,
+ timestampsVisible,
} = props;
const {
id: messageId,
source,
type,
level,
messageText,
repeat,
@@ -50,17 +52,17 @@ function PageError(props) {
let messageBody;
if (typeof messageText === "string") {
messageBody = messageText;
} else if (typeof messageText === "object" && messageText.type === "longString") {
messageBody = `${message.messageText.initial}…`;
}
- const childProps = {
+ return Message({
dispatch,
messageId,
open,
collapsible: Array.isArray(stacktrace),
source,
type,
level,
topLevelClasses: [],
@@ -68,13 +70,13 @@ function PageError(props) {
messageBody,
repeat,
frame,
stacktrace,
serviceContainer,
exceptionDocURL,
timeStamp,
notes,
- };
- return Message(childProps);
+ timestampsVisible,
+ });
}
module.exports = PageError;
--- a/devtools/client/webconsole/new-console-output/components/message.js
+++ b/devtools/client/webconsole/new-console-output/components/message.js
@@ -11,20 +11,20 @@ const {
createClass,
createFactory,
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
const { l10n } = require("devtools/client/webconsole/new-console-output/utils/messages");
const actions = require("devtools/client/webconsole/new-console-output/actions/index");
const {MESSAGE_SOURCE} = require("devtools/client/webconsole/new-console-output/constants");
-const CollapseButton = createFactory(require("devtools/client/webconsole/new-console-output/components/collapse-button"));
-const MessageIndent = createFactory(require("devtools/client/webconsole/new-console-output/components/message-indent").MessageIndent);
-const MessageIcon = createFactory(require("devtools/client/webconsole/new-console-output/components/message-icon"));
-const MessageRepeat = createFactory(require("devtools/client/webconsole/new-console-output/components/message-repeat"));
+const CollapseButton = require("devtools/client/webconsole/new-console-output/components/collapse-button");
+const MessageIndent = require("devtools/client/webconsole/new-console-output/components/message-indent").MessageIndent;
+const MessageIcon = require("devtools/client/webconsole/new-console-output/components/message-icon");
+const MessageRepeat = require("devtools/client/webconsole/new-console-output/components/message-repeat");
const FrameView = createFactory(require("devtools/client/shared/components/frame"));
const StackTrace = createFactory(require("devtools/client/shared/components/stack-trace"));
const Message = createClass({
displayName: "Message",
propTypes: {
open: PropTypes.bool,
@@ -42,16 +42,17 @@ const Message = createClass({
stacktrace: PropTypes.any,
messageId: PropTypes.string,
scrollToMessage: PropTypes.bool,
exceptionDocURL: PropTypes.string,
parameters: PropTypes.object,
request: PropTypes.object,
dispatch: PropTypes.func,
timeStamp: PropTypes.number,
+ timestampsVisible: PropTypes.bool.isRequired,
serviceContainer: PropTypes.shape({
emitNewMessage: PropTypes.func.isRequired,
onViewSourceInDebugger: PropTypes.func,
onViewSourceInScratchpad: PropTypes.func,
onViewSourceInStyleEditor: PropTypes.func,
openContextMenu: PropTypes.func.isRequired,
openLink: PropTypes.func.isRequired,
sourceMapService: PropTypes.any,
@@ -111,41 +112,49 @@ const Message = createClass({
topLevelClasses,
messageBody,
frame,
stacktrace,
serviceContainer,
dispatch,
exceptionDocURL,
timeStamp = Date.now(),
+ timestampsVisible,
notes,
} = this.props;
topLevelClasses.push("message", source, type, level);
if (open) {
topLevelClasses.push("open");
}
- const timestampEl = dom.span({
- className: "timestamp devtools-monospace"
- }, l10n.timestampString(timeStamp));
+ let timestampEl;
+ if (timestampsVisible === true) {
+ timestampEl = dom.span({
+ className: "timestamp devtools-monospace"
+ }, l10n.timestampString(timeStamp));
+ }
const icon = MessageIcon({level});
// Figure out if there is an expandable part to the message.
let attachment = null;
if (this.props.attachment) {
attachment = this.props.attachment;
- } else if (stacktrace) {
- const child = open ? StackTrace({
- stacktrace: stacktrace,
- onViewSourceInDebugger: serviceContainer.onViewSourceInDebugger,
- onViewSourceInScratchpad: serviceContainer.onViewSourceInScratchpad,
- }) : null;
- attachment = dom.div({ className: "stacktrace devtools-monospace" }, child);
+ } else if (stacktrace && open) {
+ attachment = dom.div(
+ {
+ className: "stacktrace devtools-monospace"
+ },
+ StackTrace({
+ stacktrace: stacktrace,
+ onViewSourceInDebugger: serviceContainer.onViewSourceInDebugger,
+ onViewSourceInScratchpad: serviceContainer.onViewSourceInScratchpad,
+ })
+ );
}
// If there is an expandable part, make it collapsible.
let collapse = null;
if (collapsible) {
collapse = CollapseButton({
open,
title: collapseTitle,
@@ -177,17 +186,17 @@ const Message = createClass({
? serviceContainer.sourceMapService
: undefined
}) : null
)));
} else {
notesNodes = [];
}
- const repeat = this.props.repeat ? MessageRepeat({repeat: this.props.repeat}) : null;
+ const repeat = MessageRepeat({repeat: this.props.repeat});
let onFrameClick;
if (serviceContainer && frame) {
if (source === MESSAGE_SOURCE.CSS) {
onFrameClick = serviceContainer.onViewSourceInStyleEditor;
} else if (/^Scratchpad\/\d+$/.test(frame.source)) {
onFrameClick = serviceContainer.onViewSourceInScratchpad;
} else {
@@ -225,21 +234,23 @@ const Message = createClass({
},
timestampEl,
MessageIndent({indent}),
icon,
collapse,
dom.span({ className: "message-body-wrapper" },
dom.span({ className: "message-flex-body" },
// Add whitespaces for formatting when copying to the clipboard.
- " ", dom.span({ className: "message-body devtools-monospace" },
+ timestampEl ? " " : null,
+ dom.span({ className: "message-body devtools-monospace" },
messageBody,
learnMore
),
- " ", repeat,
+ repeat ? " " : null,
+ repeat,
" ", location
),
// Add a newline for formatting when copying to the clipboard.
"\n",
// If an attachment is displayed, the final newline is handled by the attachment.
attachment,
...notesNodes
)
--- a/devtools/client/webconsole/new-console-output/components/variables-view-link.js
+++ b/devtools/client/webconsole/new-console-output/components/variables-view-link.js
@@ -14,26 +14,26 @@ const {
const {openVariablesView} = require("devtools/client/webconsole/new-console-output/utils/variables-view");
VariablesViewLink.displayName = "VariablesViewLink";
VariablesViewLink.propTypes = {
object: PropTypes.object.isRequired
};
-function VariablesViewLink(props) {
- const { className, object, children } = props;
+function VariablesViewLink(props, ...children) {
+ const { className, object } = props;
const classes = ["cm-variable"];
if (className) {
classes.push(className);
}
return (
dom.a({
onClick: openVariablesView.bind(null, object),
// Context menu can use this actor id information to enable additional menu items.
"data-link-actor-id": object.actor,
className: classes.join(" "),
draggable: false,
- }, children)
+ }, ...children)
);
}
module.exports = VariablesViewLink;