mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 17:31:47 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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',
|
||||
)
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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'
|
||||
)
|
||||
|
|
@ -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;
|
||||
Loading…
Add table
Add a link
Reference in a new issue