import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,50 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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",
propTypes: {
open: PropTypes.bool.isRequired,
title: PropTypes.string,
},
getDefaultProps: function () {
return {
title: l10n.getStr("messageToggleDetails")
};
},
render: function () {
const { open, onClick, title } = this.props;
let classes = ["theme-twisty"];
if (open) {
classes.push("open");
}
return dom.a({
className: classes.join(" "),
onClick,
title: title,
});
}
});
module.exports = CollapseButton;

View file

@ -0,0 +1,125 @@
/* 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";
const {
createClass,
createFactory,
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const {
getAllMessages,
getAllMessagesUiById,
getAllMessagesTableDataById,
getAllGroupsById,
} = require("devtools/client/webconsole/new-console-output/selectors/messages");
const { getScrollSetting } = require("devtools/client/webconsole/new-console-output/selectors/ui");
const MessageContainer = createFactory(require("devtools/client/webconsole/new-console-output/components/message-container").MessageContainer);
const ConsoleOutput = createClass({
displayName: "ConsoleOutput",
propTypes: {
messages: PropTypes.object.isRequired,
messagesUi: PropTypes.object.isRequired,
serviceContainer: PropTypes.shape({
attachRefToHud: PropTypes.func.isRequired,
}),
autoscroll: PropTypes.bool.isRequired,
},
componentDidMount() {
scrollToBottom(this.outputNode);
this.props.serviceContainer.attachRefToHud("outputScroller", this.outputNode);
},
componentWillUpdate(nextProps, nextState) {
if (!this.outputNode) {
return;
}
const outputNode = this.outputNode;
// Figure out if we are at the bottom. If so, then any new message should be scrolled
// into view.
if (this.props.autoscroll && outputNode.lastChild) {
this.shouldScrollBottom = isScrolledToBottom(outputNode.lastChild, outputNode);
}
},
componentDidUpdate() {
if (this.shouldScrollBottom) {
scrollToBottom(this.outputNode);
}
},
render() {
let {
dispatch,
autoscroll,
messages,
messagesUi,
messagesTableData,
serviceContainer,
groups,
} = this.props;
let messageNodes = messages.map((message) => {
const parentGroups = message.groupId ? (
(groups.get(message.groupId) || [])
.concat([message.groupId])
) : [];
return (
MessageContainer({
dispatch,
message,
key: message.id,
serviceContainer,
open: messagesUi.includes(message.id),
tableData: messagesTableData.get(message.id),
autoscroll,
indent: parentGroups.length,
})
);
});
return (
dom.div({
className: "webconsole-output",
ref: node => {
this.outputNode = node;
},
}, messageNodes
)
);
}
});
function scrollToBottom(node) {
node.scrollTop = node.scrollHeight;
}
function isScrolledToBottom(outputNode, scrollNode) {
let lastNodeHeight = outputNode.lastChild ?
outputNode.lastChild.clientHeight : 0;
return scrollNode.scrollTop + scrollNode.clientHeight >=
scrollNode.scrollHeight - lastNodeHeight / 2;
}
function mapStateToProps(state, props) {
return {
messages: getAllMessages(state),
messagesUi: getAllMessagesUiById(state),
messagesTableData: getAllMessagesTableDataById(state),
autoscroll: getScrollSetting(state),
groups: getAllGroupsById(state),
};
}
module.exports = connect(mapStateToProps)(ConsoleOutput);

View file

@ -0,0 +1,202 @@
/* 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";
const {
createClass,
createFactory,
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
const { ObjectClient } = require("devtools/shared/client/main");
const actions = require("devtools/client/webconsole/new-console-output/actions/messages");
const {l10n} = require("devtools/client/webconsole/new-console-output/utils/messages");
const GripMessageBody = createFactory(require("devtools/client/webconsole/new-console-output/components/grip-message-body"));
const TABLE_ROW_MAX_ITEMS = 1000;
const TABLE_COLUMN_MAX_ITEMS = 10;
const ConsoleTable = createClass({
displayName: "ConsoleTable",
propTypes: {
dispatch: PropTypes.func.isRequired,
parameters: PropTypes.array.isRequired,
serviceContainer: PropTypes.shape({
hudProxyClient: PropTypes.object.isRequired,
}),
id: PropTypes.string.isRequired,
},
componentWillMount: function () {
const {id, dispatch, serviceContainer, parameters} = this.props;
if (!Array.isArray(parameters) || parameters.length === 0) {
return;
}
const client = new ObjectClient(serviceContainer.hudProxyClient, parameters[0]);
let dataType = getParametersDataType(parameters);
// Get all the object properties.
dispatch(actions.messageTableDataGet(id, client, dataType));
},
getHeaders: function (columns) {
let headerItems = [];
columns.forEach((value, key) => headerItems.push(dom.th({}, value)));
return headerItems;
},
getRows: function (columns, items) {
return items.map(item => {
let cells = [];
columns.forEach((value, key) => {
cells.push(
dom.td(
{},
GripMessageBody({
grip: item[key]
})
)
);
});
return dom.tr({}, cells);
});
},
render: function () {
const {parameters, tableData} = this.props;
const headersGrip = parameters[1];
const headers = headersGrip && headersGrip.preview ? headersGrip.preview.items : null;
// if tableData is nullable, we don't show anything.
if (!tableData) {
return null;
}
const {columns, items} = getTableItems(
tableData,
getParametersDataType(parameters),
headers
);
return (
dom.table({className: "new-consoletable devtools-monospace"},
dom.thead({}, this.getHeaders(columns)),
dom.tbody({}, this.getRows(columns, items))
)
);
}
});
function getParametersDataType(parameters = null) {
if (!Array.isArray(parameters) || parameters.length === 0) {
return null;
}
return parameters[0].class;
}
function getTableItems(data = {}, type, headers = null) {
const INDEX_NAME = "_index";
const VALUE_NAME = "_value";
const namedIndexes = {
[INDEX_NAME]: (
["Object", "Array"].includes(type) ?
l10n.getStr("table.index") : l10n.getStr("table.iterationIndex")
),
[VALUE_NAME]: l10n.getStr("table.value"),
key: l10n.getStr("table.key")
};
let columns = new Map();
let items = [];
let addItem = function (item) {
items.push(item);
Object.keys(item).forEach(key => addColumn(key));
};
let addColumn = function (columnIndex) {
let columnExists = columns.has(columnIndex);
let hasMaxColumns = columns.size == TABLE_COLUMN_MAX_ITEMS;
let hasCustomHeaders = Array.isArray(headers);
if (
!columnExists &&
!hasMaxColumns && (
!hasCustomHeaders ||
headers.includes(columnIndex) ||
columnIndex === INDEX_NAME
)
) {
columns.set(columnIndex, namedIndexes[columnIndex] || columnIndex);
}
};
for (let index of Object.keys(data)) {
if (type !== "Object" && index == parseInt(index, 10)) {
index = parseInt(index, 10);
}
let item = {
[INDEX_NAME]: index
};
let property = data[index].value;
if (property.preview) {
let {preview} = property;
let entries = preview.ownProperties || preview.items;
if (entries) {
for (let key of Object.keys(entries)) {
let entry = entries[key];
item[key] = entry.value || entry;
}
} else {
if (preview.key) {
item.key = preview.key;
}
item[VALUE_NAME] = preview.value || property;
}
} else {
item[VALUE_NAME] = property;
}
addItem(item);
if (items.length === TABLE_ROW_MAX_ITEMS) {
break;
}
}
// Some headers might not be present in the items, so we make sure to
// return all the headers set by the user.
if (Array.isArray(headers)) {
headers.forEach(header => addColumn(header));
}
// We want to always have the index column first
if (columns.has(INDEX_NAME)) {
let index = columns.get(INDEX_NAME);
columns.delete(INDEX_NAME);
columns = new Map([[INDEX_NAME, index], ...columns.entries()]);
}
// We want to always have the values column last
if (columns.has(VALUE_NAME)) {
let index = columns.get(VALUE_NAME);
columns.delete(VALUE_NAME);
columns.set(VALUE_NAME, index);
}
return {
columns,
items
};
}
module.exports = ConsoleTable;

View file

@ -0,0 +1,170 @@
/* 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";
const {
createFactory,
createClass,
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { getAllFilters } = require("devtools/client/webconsole/new-console-output/selectors/filters");
const { getAllUi } = require("devtools/client/webconsole/new-console-output/selectors/ui");
const { filterTextSet, filtersClear } = require("devtools/client/webconsole/new-console-output/actions/index");
const { messagesClear } = require("devtools/client/webconsole/new-console-output/actions/index");
const uiActions = require("devtools/client/webconsole/new-console-output/actions/index");
const {
MESSAGE_LEVEL
} = require("../constants");
const FilterButton = createFactory(require("devtools/client/webconsole/new-console-output/components/filter-button"));
const FilterBar = createClass({
displayName: "FilterBar",
propTypes: {
filter: PropTypes.object.isRequired,
serviceContainer: PropTypes.shape({
attachRefToHud: PropTypes.func.isRequired,
}).isRequired,
ui: PropTypes.object.isRequired
},
componentDidMount() {
this.props.serviceContainer.attachRefToHud("filterBox",
this.wrapperNode.querySelector(".text-filter"));
},
onClickMessagesClear: function () {
this.props.dispatch(messagesClear());
},
onClickFilterBarToggle: function () {
this.props.dispatch(uiActions.filterBarToggle());
},
onClickFiltersClear: function () {
this.props.dispatch(filtersClear());
},
onSearchInput: function (e) {
this.props.dispatch(filterTextSet(e.target.value));
},
render() {
const {dispatch, filter, ui} = this.props;
let filterBarVisible = ui.filterBarVisible;
let children = [];
children.push(dom.div({className: "devtools-toolbar webconsole-filterbar-primary"},
dom.button({
className: "devtools-button devtools-clear-icon",
title: "Clear output",
onClick: this.onClickMessagesClear
}),
dom.button({
className: "devtools-button devtools-filter-icon" + (
filterBarVisible ? " checked" : ""),
title: "Toggle filter bar",
onClick: this.onClickFilterBarToggle
}),
dom.input({
className: "devtools-plaininput text-filter",
type: "search",
value: filter.text,
placeholder: "Filter output",
onInput: this.onSearchInput
})
));
if (filterBarVisible) {
children.push(
dom.div({className: "devtools-toolbar webconsole-filterbar-secondary"},
FilterButton({
active: filter.error,
label: "Errors",
filterKey: MESSAGE_LEVEL.ERROR,
dispatch
}),
FilterButton({
active: filter.warn,
label: "Warnings",
filterKey: MESSAGE_LEVEL.WARN,
dispatch
}),
FilterButton({
active: filter.log,
label: "Logs",
filterKey: MESSAGE_LEVEL.LOG,
dispatch
}),
FilterButton({
active: filter.info,
label: "Info",
filterKey: MESSAGE_LEVEL.INFO,
dispatch
}),
FilterButton({
active: filter.debug,
label: "Debug",
filterKey: MESSAGE_LEVEL.DEBUG,
dispatch
}),
dom.span({
className: "devtools-separator",
}),
FilterButton({
active: filter.netxhr,
label: "XHR",
filterKey: "netxhr",
dispatch
}),
FilterButton({
active: filter.net,
label: "Requests",
filterKey: "net",
dispatch
})
)
);
}
if (ui.filteredMessageVisible) {
children.push(
dom.div({className: "devtools-toolbar"},
dom.span({
className: "clear"},
"You have filters set that may hide some results. " +
"Learn more about our filtering syntax ",
dom.a({}, "here"),
"."),
dom.button({
className: "menu-filter-button",
onClick: this.onClickFiltersClear
}, "Remove filters")
)
);
}
return (
dom.div({
className: "webconsole-filteringbar-wrapper",
ref: node => {
this.wrapperNode = node;
}
}, ...children
)
);
}
});
function mapStateToProps(state) {
return {
filter: getAllFilters(state),
ui: getAllUi(state)
};
}
module.exports = connect(mapStateToProps)(FilterBar);

View file

@ -0,0 +1,46 @@
/* 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";
const {
createClass,
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
const actions = require("devtools/client/webconsole/new-console-output/actions/index");
const FilterButton = createClass({
displayName: "FilterButton",
propTypes: {
label: PropTypes.string.isRequired,
filterKey: PropTypes.string.isRequired,
active: PropTypes.bool.isRequired,
dispatch: PropTypes.func.isRequired,
},
onClick: function () {
this.props.dispatch(actions.filterToggle(this.props.filterKey));
},
render() {
const {active, label, filterKey} = this.props;
let classList = [
"menu-filter-button",
filterKey,
];
if (active) {
classList.push("checked");
}
return dom.button({
className: classList.join(" "),
onClick: this.onClick
}, label);
}
});
module.exports = FilterButton;

View file

@ -0,0 +1,102 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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";
// 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 { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
const { Rep } = createFactories(require("devtools/client/shared/components/reps/rep"));
const StringRep = createFactories(require("devtools/client/shared/components/reps/string").StringRep).rep;
const VariablesViewLink = createFactory(require("devtools/client/webconsole/new-console-output/components/variables-view-link"));
const { Grip } = require("devtools/client/shared/components/reps/grip");
GripMessageBody.displayName = "GripMessageBody";
GripMessageBody.propTypes = {
grip: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.object,
]).isRequired,
serviceContainer: PropTypes.shape({
createElement: PropTypes.func.isRequired,
}),
userProvidedStyle: PropTypes.string,
};
function GripMessageBody(props) {
const { grip, userProvidedStyle, serviceContainer } = props;
let styleObject;
if (userProvidedStyle && userProvidedStyle !== "") {
styleObject = cleanupStyle(userProvidedStyle, serviceContainer.createElement);
}
return (
// @TODO once there is a longString rep, also turn off quotes for those.
typeof grip === "string"
? StringRep({
object: grip,
useQuotes: false,
mode: props.mode,
style: styleObject
})
: Rep({
object: grip,
objectLink: VariablesViewLink,
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 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,
];
// 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]
.filter(name => {
return allowedStylesRegex.test(name)
&& !forbiddenValuesRegexs.some(regex => regex.test(dummy.style[name]));
})
.reduce((object, name) => {
return Object.assign({
[name]: dummy.style[name]
}, object);
}, {});
}
module.exports = GripMessageBody;

View file

@ -0,0 +1,92 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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,
createFactory,
PropTypes
} = require("devtools/client/shared/vendor/react");
const {
MESSAGE_SOURCE,
MESSAGE_TYPE
} = require("devtools/client/webconsole/new-console-output/constants");
const componentMap = new Map([
["ConsoleApiCall", require("./message-types/console-api-call")],
["ConsoleCommand", require("./message-types/console-command")],
["DefaultRenderer", require("./message-types/default-renderer")],
["EvaluationResult", require("./message-types/evaluation-result")],
["NetworkEventMessage", require("./message-types/network-event-message")],
["PageError", require("./message-types/page-error")]
]);
const MessageContainer = createClass({
displayName: "MessageContainer",
propTypes: {
message: PropTypes.object.isRequired,
open: PropTypes.bool.isRequired,
serviceContainer: PropTypes.object.isRequired,
autoscroll: PropTypes.bool.isRequired,
indent: PropTypes.number.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;
return repeatChanged || openChanged || tableDataChanged;
},
render() {
const { message } = this.props;
let MessageComponent = createFactory(getMessageComponent(message));
return MessageComponent(this.props);
}
});
function getMessageComponent(message) {
switch (message.source) {
case MESSAGE_SOURCE.CONSOLE_API:
return componentMap.get("ConsoleApiCall");
case MESSAGE_SOURCE.NETWORK:
return componentMap.get("NetworkEventMessage");
case MESSAGE_SOURCE.JAVASCRIPT:
switch (message.type) {
case MESSAGE_TYPE.COMMAND:
return componentMap.get("ConsoleCommand");
case MESSAGE_TYPE.RESULT:
return componentMap.get("EvaluationResult");
// @TODO this is probably not the right behavior, but works for now.
// Chrome doesn't distinguish between page errors and log messages. We
// may want to remove the PageError component and just handle errors
// with ConsoleApiCall.
case MESSAGE_TYPE.LOG:
return componentMap.get("PageError");
default:
return componentMap.get("DefaultRenderer");
}
}
return componentMap.get("DefaultRenderer");
}
module.exports.MessageContainer = MessageContainer;
// Exported so we can test it with unit tests.
module.exports.getMessageComponent = getMessageComponent;

View file

@ -0,0 +1,32 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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 {
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
const {l10n} = require("devtools/client/webconsole/new-console-output/utils/messages");
MessageIcon.displayName = "MessageIcon";
MessageIcon.propTypes = {
level: PropTypes.string.isRequired,
};
function MessageIcon(props) {
const { level } = props;
const title = l10n.getStr("level." + level);
return dom.div({
className: "icon",
title
});
}
module.exports = MessageIcon;

View file

@ -0,0 +1,37 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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}
});
}
});
module.exports.MessageIndent = MessageIndent;
// Exported so we can test it with unit tests.
module.exports.INDENT_WIDTH = INDENT_WIDTH;

View file

@ -0,0 +1,36 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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 {
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");
MessageRepeat.displayName = "MessageRepeat";
MessageRepeat.propTypes = {
repeat: PropTypes.number.isRequired
};
function MessageRepeat(props) {
const { repeat } = props;
const visibility = repeat > 1 ? "visible" : "hidden";
return dom.span({
className: "message-repeats",
style: {visibility},
title: PluralForm.get(repeat, l10n.getStr("messageRepeats.tooltip2"))
.replace("#1", repeat)
}, repeat);
}
module.exports = MessageRepeat;

View file

@ -0,0 +1,132 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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,
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
const GripMessageBody = createFactory(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,
};
ConsoleApiCall.defaultProps = {
open: false,
indent: 0,
};
function ConsoleApiCall(props) {
const {
dispatch,
message,
open,
tableData,
serviceContainer,
indent,
} = props;
const {
id: messageId,
source,
type,
level,
repeat,
stacktrace,
frame,
parameters,
messageText,
userProvidedStyles,
} = message;
let messageBody;
if (type === "trace") {
messageBody = dom.span({className: "cm-variable"}, "console.trace()");
} else if (type === "assert") {
let reps = formatReps(parameters);
messageBody = dom.span({ className: "cm-variable" }, "Assertion failed: ", reps);
} else if (type === "table") {
// TODO: Chrome does not output anything, see if we want to keep this
messageBody = dom.span({className: "cm-variable"}, "console.table()");
} else if (parameters) {
messageBody = formatReps(parameters, userProvidedStyles, serviceContainer);
} else {
messageBody = messageText;
}
let attachment = null;
if (type === "table") {
attachment = ConsoleTable({
dispatch,
id: message.id,
serviceContainer,
parameters: message.parameters,
tableData
});
}
let collapseTitle = null;
if (isGroupType(type)) {
collapseTitle = l10n.getStr("groupToggle");
}
const collapsible = isGroupType(type)
|| (type === "error" && Array.isArray(stacktrace));
const topLevelClasses = ["cm-s-mozilla"];
return Message({
messageId,
open,
collapsible,
collapseTitle,
source,
type,
level,
topLevelClasses,
messageBody,
repeat,
frame,
stacktrace,
attachment,
serviceContainer,
dispatch,
indent,
});
}
function formatReps(parameters, userProvidedStyles, serviceContainer) {
return (
parameters
// Get all the grips.
.map((grip, key) => GripMessageBody({
grip,
key,
userProvidedStyle: userProvidedStyles ? userProvidedStyles[key] : null,
serviceContainer
}))
// Interleave spaces.
.reduce((arr, v, i) => {
return i + 1 < parameters.length
? arr.concat(v, dom.span({}, " "))
: arr.concat(v);
}, [])
);
}
module.exports = ConsoleApiCall;

View file

@ -0,0 +1,57 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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,
PropTypes
} = require("devtools/client/shared/vendor/react");
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,
};
ConsoleCommand.defaultProps = {
indent: 0,
};
/**
* Displays input from the console.
*/
function ConsoleCommand(props) {
const { autoscroll, indent, message } = props;
const {
source,
type,
level,
messageText: messageBody,
} = message;
const {
serviceContainer,
} = props;
const childProps = {
source,
type,
level,
topLevelClasses: [],
messageBody,
scrollToMessage: autoscroll,
serviceContainer,
indent: indent,
};
return Message(childProps);
}
module.exports = ConsoleCommand;

View file

@ -0,0 +1,22 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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 {
DOM: dom,
} = require("devtools/client/shared/vendor/react");
DefaultRenderer.displayName = "DefaultRenderer";
function DefaultRenderer(props) {
return dom.div({},
"This message type is not supported yet."
);
}
module.exports = DefaultRenderer;

View file

@ -0,0 +1,64 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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,
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"));
EvaluationResult.displayName = "EvaluationResult";
EvaluationResult.propTypes = {
message: PropTypes.object.isRequired,
indent: PropTypes.number.isRequired,
};
EvaluationResult.defaultProps = {
indent: 0,
};
function EvaluationResult(props) {
const { message, serviceContainer, indent } = props;
const {
source,
type,
level,
id: messageId,
exceptionDocURL,
frame,
} = message;
let messageBody;
if (message.messageText) {
messageBody = message.messageText;
} else {
messageBody = GripMessageBody({grip: message.parameters});
}
const topLevelClasses = ["cm-s-mozilla"];
const childProps = {
source,
type,
level,
indent,
topLevelClasses,
messageBody,
messageId,
scrollToMessage: props.autoscroll,
serviceContainer,
exceptionDocURL,
frame,
};
return Message(childProps);
}
module.exports = EvaluationResult;

View file

@ -0,0 +1,13 @@
# vim: set filetype=python:
# 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/.
DevToolsModules(
'console-api-call.js',
'console-command.js',
'default-renderer.js',
'evaluation-result.js',
'network-event-message.js',
'page-error.js',
)

View file

@ -0,0 +1,63 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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,
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
const Message = createFactory(require("devtools/client/webconsole/new-console-output/components/message"));
const { l10n } = require("devtools/client/webconsole/new-console-output/utils/messages");
NetworkEventMessage.displayName = "NetworkEventMessage";
NetworkEventMessage.propTypes = {
message: PropTypes.object.isRequired,
serviceContainer: PropTypes.shape({
openNetworkPanel: PropTypes.func.isRequired,
}),
indent: PropTypes.number.isRequired,
};
NetworkEventMessage.defaultProps = {
indent: 0,
};
function NetworkEventMessage(props) {
const { message, serviceContainer, indent } = props;
const { actor, source, type, level, request, isXHR } = message;
const topLevelClasses = [ "cm-s-mozilla" ];
function onUrlClick() {
serviceContainer.openNetworkPanel(actor);
}
const method = dom.span({className: "method" }, request.method);
const xhr = isXHR
? dom.span({ className: "xhr" }, l10n.getStr("webConsoleXhrIndicator"))
: null;
const url = dom.a({ className: "url", title: request.url, onClick: onUrlClick },
request.url.replace(/\?.+/, ""));
const messageBody = dom.span({}, method, xhr, url);
const childProps = {
source,
type,
level,
indent,
topLevelClasses,
messageBody,
serviceContainer,
};
return Message(childProps);
}
module.exports = NetworkEventMessage;

View file

@ -0,0 +1,69 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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,
PropTypes
} = require("devtools/client/shared/vendor/react");
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,
};
PageError.defaultProps = {
open: false,
indent: 0,
};
function PageError(props) {
const {
dispatch,
message,
open,
serviceContainer,
indent,
} = props;
const {
id: messageId,
source,
type,
level,
messageText: messageBody,
repeat,
stacktrace,
frame,
exceptionDocURL,
} = message;
const childProps = {
dispatch,
messageId,
open,
collapsible: Array.isArray(stacktrace),
source,
type,
level,
topLevelClasses: [],
indent,
messageBody,
repeat,
frame,
stacktrace,
serviceContainer,
exceptionDocURL,
};
return Message(childProps);
}
module.exports = PageError;

View file

@ -0,0 +1,176 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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,
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 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 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,
collapsible: PropTypes.bool,
collapseTitle: PropTypes.string,
source: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
level: PropTypes.string.isRequired,
indent: PropTypes.number.isRequired,
topLevelClasses: PropTypes.array.isRequired,
messageBody: PropTypes.any.isRequired,
repeat: PropTypes.any,
frame: PropTypes.any,
attachment: PropTypes.any,
stacktrace: PropTypes.any,
messageId: PropTypes.string,
scrollToMessage: PropTypes.bool,
exceptionDocURL: PropTypes.string,
serviceContainer: PropTypes.shape({
emitNewMessage: PropTypes.func.isRequired,
onViewSourceInDebugger: PropTypes.func.isRequired,
sourceMapService: PropTypes.any,
}),
},
getDefaultProps: function () {
return {
indent: 0
};
},
componentDidMount() {
if (this.messageNode) {
if (this.props.scrollToMessage) {
this.messageNode.scrollIntoView();
}
// Event used in tests. Some message types don't pass it in because existing tests
// did not emit for them.
if (this.props.serviceContainer) {
this.props.serviceContainer.emitNewMessage(this.messageNode, this.props.messageId);
}
}
},
onLearnMoreClick: function () {
let {exceptionDocURL} = this.props;
this.props.serviceContainer.openLink(exceptionDocURL);
},
render() {
const {
messageId,
open,
collapsible,
collapseTitle,
source,
type,
level,
indent,
topLevelClasses,
messageBody,
frame,
stacktrace,
serviceContainer,
dispatch,
exceptionDocURL,
} = this.props;
topLevelClasses.push("message", source, type, level);
if (open) {
topLevelClasses.push("open");
}
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
}) : null;
attachment = dom.div({ className: "stacktrace devtools-monospace" }, child);
}
// If there is an expandable part, make it collapsible.
let collapse = null;
if (collapsible) {
collapse = CollapseButton({
open,
title: collapseTitle,
onClick: function () {
if (open) {
dispatch(actions.messageClose(messageId));
} else {
dispatch(actions.messageOpen(messageId));
}
},
});
}
const repeat = this.props.repeat ? MessageRepeat({repeat: this.props.repeat}) : null;
// Configure the location.
const location = dom.span({ className: "message-location devtools-monospace" },
frame ? FrameView({
frame,
onClick: serviceContainer ? serviceContainer.onViewSourceInDebugger : undefined,
showEmptyPathAsHost: true,
sourceMapService: serviceContainer ? serviceContainer.sourceMapService : undefined
}) : null
);
let learnMore;
if (exceptionDocURL) {
learnMore = dom.a({
className: "learn-more-link webconsole-learn-more-link",
title: exceptionDocURL.split("?")[0],
onClick: this.onLearnMoreClick,
}, `[${l10n.getStr("webConsoleMoreInfoLabel")}]`);
}
return dom.div({
className: topLevelClasses.join(" "),
ref: node => {
this.messageNode = node;
}
},
// @TODO add timestamp
MessageIndent({indent}),
icon,
collapse,
dom.span({ className: "message-body-wrapper" },
dom.span({ className: "message-flex-body" },
dom.span({ className: "message-body devtools-monospace" },
messageBody,
learnMore
),
repeat,
location
),
attachment
)
);
}
});
module.exports = Message;

View file

@ -0,0 +1,23 @@
# vim: set filetype=python:
# 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/.
DIRS += [
'message-types'
]
DevToolsModules(
'collapse-button.js',
'console-output.js',
'console-table.js',
'filter-bar.js',
'filter-button.js',
'grip-message-body.js',
'message-container.js',
'message-icon.js',
'message-indent.js',
'message-repeat.js',
'message.js',
'variables-view-link.js'
)

View file

@ -0,0 +1,34 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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 {
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
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 { object, children } = props;
return (
dom.a({
onClick: openVariablesView.bind(null, object),
className: "cm-variable",
draggable: false,
}, children)
);
}
module.exports = VariablesViewLink;