author | Jason Laster <jason.laster.11@gmail.com> |
Sun, 15 Apr 2018 00:03:03 +0200 | |
changeset 413443 | 244ecba50f11b3cf54288242c80262b5342ba665 |
parent 413442 | c80bf1d63a2afbf5c6a8921f17fcf00bc513d6dd |
child 413444 | f291b07fa1f869fd3f9af9f5fe940d47b842edcf |
push id | 33850 |
push user | apavel@mozilla.com |
push date | Mon, 16 Apr 2018 09:53:48 +0000 |
treeherder | mozilla-central@6276ec7ebbf3 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jdescottes |
bugs | 1453946 |
milestone | 61.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/devtools/client/debugger/new/README.mozilla +++ b/devtools/client/debugger/new/README.mozilla @@ -1,13 +1,13 @@ This is the debugger.html project output. See https://github.com/devtools-html/debugger.html -Version 37.0 +Version 38.0 -Comparison: https://github.com/devtools-html/debugger.html/compare/release-36...release-37 +Comparison: https://github.com/devtools-html/debugger.html/compare/release-37...release-38 Packages: - babel-plugin-transform-es2015-modules-commonjs @6.26.0 - babel-preset-react @6.24.1 - react @16.2.0 - react-dom @16.2.0 - webpack @3.11.0
--- a/devtools/client/debugger/new/debugger.css +++ b/devtools/client/debugger/new/debugger.css @@ -1359,18 +1359,19 @@ html[dir="rtl"] .tree-node img.arrow { .sources-list .managed-tree .tree .node img.blackBox { mask: url("chrome://devtools/skin/images/debugger/blackBox.svg") no-repeat; mask-size: 100%; background-color: var(--theme-highlight-blue); width: 13px; height: 13px; display: inline-block; - margin-inline-end: 5px; - margin-bottom: -2px; + margin-inline-end: 6px; + margin-inline-start: 1px; + margin-top: 2px; } .sources-list .managed-tree .tree .node.focused img { background-color: white; } .theme-dark .sources-list .managed-tree .tree .node:not(.focused) img.blackBox { background-color: var(--theme-comment); @@ -1943,17 +1944,16 @@ html .toggle-button.end.vertical svg { --null-color: var(--theme-comment); --object-color: var(--theme-highlight-blue); --caption-color: var(--theme-highlight-blue); --location-color: var(--theme-comment); --source-link-color: var(--theme-highlight-blue); --node-color: var(--theme-highlight-purple); --reference-color: var(--theme-highlight-blue); --comment-node-color: var(--theme-comment); - --stack-function-color: var(--theme-highlight-red); } .theme-firebug { --number-color: #000088; --string-color: #FF0000; --null-color: #787878; --object-color: DarkGreen; --caption-color: #444444; @@ -2005,37 +2005,60 @@ html .toggle-button.end.vertical svg { cursor: pointer; } .objectBox-string a:hover { text-decoration: underline; } .objectBox-function, -.objectBox-stackTrace, .objectBox-profile { color: var(--object-color); } +.objectBox-stackTrace { + color: var(--error-color); +} + .objectBox-stackTrace-grid { display: inline-grid; grid-template-columns: auto auto; margin-top: 3px; } .objectBox-stackTrace-fn::before { content: "\3BB"; /* The "lambda" symbol */ - color: var(--theme-body-color); display: inline-block; margin: 0 0.3em; } .objectBox-stackTrace-fn { - color: var(--stack-function-color); + color: var(--console-output-color); padding-inline-start: 17px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + margin-inline-end: 5px; +} + +.objectBox-stackTrace-location { + color: var(--frame-link-source, currentColor); + direction: rtl; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + text-align: end; +} + +.objectBox-stackTrace-location:hover { + text-decoration: underline; +} + +.objectBox-stackTrace-location { + cursor: pointer; } .objectBox-Location, .location { color: var(--location-color); } .objectBox-null, @@ -2954,16 +2977,20 @@ html[dir="rtl"] .breakpoints-list .break .CodeMirror.cm-s-mozilla-breakpoint .CodeMirror-code, .CodeMirror.cm-s-mozilla-breakpoint .CodeMirror-scroll { cursor: default; } /* 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/>. */ +.watch-expressions-pane .plus { + margin-top: -2px; +} + .expression-input-form { width: 100%; } .input-expression { width: 100%; margin: 0; border: 1px;
--- a/devtools/client/debugger/new/debugger.js +++ b/devtools/client/debugger/new/debugger.js @@ -2321,18 +2321,17 @@ var _path = __webpack_require__(1393); var _url = __webpack_require__(334); var _sourcesTree = __webpack_require__(1442); const sourceTypes = exports.sourceTypes = { coffee: "coffeescript", js: "javascript", jsx: "react", - ts: "typescript", - css: "css" + ts: "typescript" }; /** * Trims the query part or reference identifier of a url string, if necessary. * * @memberof utils/source * @static */ @@ -7068,28 +7067,19 @@ class ManagedTree extends _react.Compone } highlightItem(highlightItems) { const { expanded } = this.state; // This file is visible, so we highlight it. if (expanded.has(this.props.getPath(highlightItems[0]))) { this.focusItem(highlightItems[0]); } else { - // Look at folders starting from the top-level and expand all the items - // which lie in the path of the item to be highlighted - highlightItems.reverse(); - let index = highlightItems.findIndex(item => !expanded.has(this.props.getPath(item))); - - if (this.props.autoExpandOnHighlight) { - while (index < highlightItems.length - 1) { - this.setExpanded(highlightItems[index], true, false); - index++; - } - } - + // Look at folders starting from the top-level until finds a + // closed folder and highlights this folder + const index = highlightItems.reverse().findIndex(item => !expanded.has(this.props.getPath(item))); this.focusItem(highlightItems[index]); } } render() { const { expanded, focusedItem } = this.state; return _react2.default.createElement( "div", @@ -10213,17 +10203,17 @@ var _initialiseProps = function () { className: (0, _classnames2.default)("result-item", { selected: index === selected }) }; return _react2.default.createElement( "li", props, - _react2.default.createElement( + item.icon && _react2.default.createElement( "div", null, _react2.default.createElement("img", { className: item.icon }) ), _react2.default.createElement( "div", { id: `${item.id}-title`, className: "title" }, item.title @@ -10594,17 +10584,18 @@ function supportsObject(object, noGrip = return getGripType(object, noGrip) == "string"; } // Exports from this module module.exports = { rep: wrapRender(StringRep), - supportsObject + supportsObject, + isLongString }; /***/ }), /***/ 1448: /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -16989,17 +16980,16 @@ class SourcesTree extends _react.Compone if (isEmpty && !isCustomRoot) { return this.renderEmptyElement(L10N.getStr("sources.noSourcesAvailable")); } const treeProps = { autoExpandAll: false, autoExpandDepth: expanded ? 0 : 1, - autoExpandOnHighlight: true, expanded, getChildren: item => (0, _sourcesTree.nodeHasChildren)(item) ? item.contents : [], getParent: item => parentMap.get(item), getPath: this.getPath, getRoots: roots, highlightItems, itemHeight: 21, key: isEmpty ? "empty" : "full", @@ -18649,17 +18639,20 @@ class Popup extends _react.Component { async componentWillMount() { const { value, expression, setPopupObjectProperties, popupObjectProperties } = this.props; - const root = createNode(null, expression, expression, { value }); + const root = createNode({ + name: expression, + contents: { value } + }); if (!nodeIsPrimitive(root) && value && value.actor && !popupObjectProperties[value.actor]) { const onLoadItemProperties = loadItemProperties(root, _firefox.createObjectClient); if (onLoadItemProperties !== null) { const properties = await onLoadItemProperties; setPopupObjectProperties(value, properties); } } @@ -18763,17 +18756,17 @@ class Popup extends _react.Component { _react2.default.createElement(_Svg2.default, { name: "immutable", className: "immutable-logo" }), _react2.default.createElement( "h3", null, immutableHeader ) ); - const roots = [createNode(null, "entries", "entries", { value: immutable.entries })]; + const roots = [createNode({ name: "entries", contents: { value: immutable.entries } })]; return _react2.default.createElement( "div", { className: "preview-popup" }, header, this.renderObjectInspector(roots) ); } @@ -20470,20 +20463,22 @@ module.exports = { const PropTypes = __webpack_require__(20); // Utils const { getGripType, isGrip, wrapRender } = __webpack_require__(1353); const { cleanFunctionName } = __webpack_require__(1573); +const { isLongString } = __webpack_require__(1447); const { MODE } = __webpack_require__(1357); const dom = __webpack_require__(1758); const { span } = dom; +const IGNORED_SOURCE_URLS = ["debugger eval code"]; /** * Renders Error objects. */ ErrorRep.propTypes = { object: PropTypes.object.isRequired, // @TODO Change this to Object.values once it's supported in Node's version of V8 mode: PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])) @@ -20513,17 +20508,17 @@ function ErrorRep(props) { if (props.mode === MODE.TINY) { content.push(name); } else { content.push(`${name}: "${preview.message}"`); } if (preview.stack && props.mode !== MODE.TINY) { - content.push("\n", getStacktraceElements(preview)); + content.push("\n", getStacktraceElements(props, preview)); } return span({ "data-link-actor-id": object.actor, className: "objectBox-stackTrace" }, content); } @@ -20538,52 +20533,86 @@ function ErrorRep(props) { * * Into a column layout: * * semicolon (<anonymous>:8:10) * jkl (<anonymous>:5:10) * asdf (<anonymous>:2:10) * (<anonymous>:11:1) */ -function getStacktraceElements(preview) { +function getStacktraceElements(props, preview) { const stack = []; - preview.stack.split("\n").forEach((line, index) => { - if (!line) { + if (!preview.stack) { + return stack; + } + + const isStacktraceALongString = isLongString(preview.stack); + const stackString = isStacktraceALongString ? preview.stack.initial : preview.stack; + + stackString.split("\n").forEach((frame, index) => { + if (!frame) { // Skip any blank lines return; } let functionName; let location; // Given the input: "functionName@scriptLocation:2:100" // Result: // ["functionName@scriptLocation:2:100", "functionName", "scriptLocation:2:100"] - const result = line.match(/^(.*)@(.*)$/); + const result = frame.match(/^(.*)@(.*)$/); if (result && result.length === 3) { functionName = result[1]; // If the resource was loaded by base-loader.js, the location looks like: // resource://devtools/shared/base-loader.js -> resource://path/to/file.js . // What's needed is only the last part after " -> ". location = result[2].split(" -> ").pop(); } if (!functionName) { functionName = "<anonymous>"; } + let onLocationClick; + // Given the input: "scriptLocation:2:100" + // Result: + // ["scriptLocation:2:100", "scriptLocation", "2", "100"] + const locationParts = location.match(/^(.*):(\d+):(\d+)$/); + if (props.onViewSourceInDebugger && location && !IGNORED_SOURCE_URLS.includes(locationParts[1]) && locationParts) { + let [, url, line, column] = locationParts; + onLocationClick = e => { + // Don't trigger ObjectInspector expand/collapse. + e.stopPropagation(); + props.onViewSourceInDebugger({ + url, + line: Number(line), + column: Number(column) + }); + }; + } + stack.push(span({ key: "fn" + index, className: "objectBox-stackTrace-fn" }, cleanFunctionName(functionName)), span({ key: "location" + index, - className: "objectBox-stackTrace-location" - }, ` (${location})`)); - }); + className: "objectBox-stackTrace-location", + onClick: onLocationClick, + title: onLocationClick ? "View source in debugger → " + location : undefined + }, location)); + }); + + if (isStacktraceALongString) { + // Remove the last frame (i.e. 2 last elements in the array, the function name and the + // location) which is certainly incomplete. + // Can be removed when https://bugzilla.mozilla.org/show_bug.cgi?id=1448833 is fixed. + stack.splice(-2); + } return span({ key: "stack", className: "objectBox-stackTrace-grid" }, stack); } // Registration @@ -21027,16 +21056,21 @@ module.exports = { /* 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/. */ const { createElement, createFactory, PureComponent } = __webpack_require__(0); const { Provider } = __webpack_require__(3592); const ObjectInspector = createFactory(__webpack_require__(3615)); const createStore = __webpack_require__(3618); +const Utils = __webpack_require__(1938); +const { + renderRep, + shouldRenderRootsInReps +} = Utils; class OI extends PureComponent { constructor(props) { super(props); this.store = createStore(props); } @@ -21044,17 +21078,23 @@ class OI extends PureComponent { return this.store; } render() { return createElement(Provider, { store: this.store }, ObjectInspector(this.props)); } } -module.exports = OI; +module.exports = props => { + let { roots } = props; + if (shouldRenderRootsInReps(roots)) { + return renderRep(roots[0], props); + } + return new OI(props); +}; /***/ }), /***/ 1586: /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -24242,17 +24282,16 @@ exports.default = Accordion; /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.debugBtn = debugBtn; var _propTypes = __webpack_require__(20); var _propTypes2 = _interopRequireDefault(_propTypes); var _react = __webpack_require__(0); var _react2 = _interopRequireDefault(_react); @@ -24272,18 +24311,16 @@ var _selectors = __webpack_require__(359 var _text = __webpack_require__(1387); var _actions = __webpack_require__(1354); var _actions2 = _interopRequireDefault(_actions); var _CommandBarButton = __webpack_require__(1764); -var _CommandBarButton2 = _interopRequireDefault(_CommandBarButton); - __webpack_require__(1295); var _devtoolsModules = __webpack_require__(1376); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* -*- indent-tabs-mode: nil; js-indent-level: 2; js-indent-level: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public @@ -24335,31 +24372,16 @@ function formatKey(action) { if (isMacOS) { const winKey = getKeyForOS("WINNT", `${action}Display`) || getKeyForOS("WINNT", action); // display both Windows type and Mac specific keys return (0, _text.formatKeyShortcut)([key, winKey].join(" ")); } return (0, _text.formatKeyShortcut)(key); } -function debugBtn(onClick, type, className, tooltip, disabled = false, ariaPressed = false) { - return _react2.default.createElement( - _CommandBarButton2.default, - { - className: (0, _classnames2.default)(type, className), - disabled: disabled, - key: type, - onClick: onClick, - pressed: ariaPressed, - title: tooltip - }, - _react2.default.createElement("img", { className: type }) - ); -} - class CommandBar extends _react.Component { componentWillUnmount() { const shortcuts = this.context.shortcuts; COMMANDS.forEach(action => shortcuts.off(getKey(action))); if (isMacOS) { COMMANDS.forEach(action => shortcuts.off(getKeyForOS("WINNT", action))); } } @@ -24391,44 +24413,44 @@ class CommandBar extends _react.Componen const { isPaused, canRewind } = this.props; const className = isPaused ? "active" : "disabled"; const isDisabled = !isPaused; if (canRewind || !isPaused && _prefs.features.removeCommandBarOptions) { return; } - return [debugBtn(this.props.stepOver, "stepOver", className, L10N.getFormatStr("stepOverTooltip", formatKey("stepOver")), isDisabled), debugBtn(this.props.stepIn, "stepIn", className, L10N.getFormatStr("stepInTooltip", formatKey("stepIn")), isDisabled), debugBtn(this.props.stepOut, "stepOut", className, L10N.getFormatStr("stepOutTooltip", formatKey("stepOut")), isDisabled)]; + return [(0, _CommandBarButton.debugBtn)(this.props.stepOver, "stepOver", className, L10N.getFormatStr("stepOverTooltip", formatKey("stepOver")), isDisabled), (0, _CommandBarButton.debugBtn)(this.props.stepIn, "stepIn", className, L10N.getFormatStr("stepInTooltip", formatKey("stepIn")), isDisabled), (0, _CommandBarButton.debugBtn)(this.props.stepOut, "stepOut", className, L10N.getFormatStr("stepOutTooltip", formatKey("stepOut")), isDisabled)]; } resume() { this.props.resume(); this.props.clearHistory(); } renderPauseButton() { const { isPaused, breakOnNext, isWaitingOnBreak, canRewind } = this.props; if (canRewind) { return; } if (isPaused) { - return debugBtn(() => this.resume(), "resume", "active", L10N.getFormatStr("resumeButtonTooltip", formatKey("resume"))); + return (0, _CommandBarButton.debugBtn)(() => this.resume(), "resume", "active", L10N.getFormatStr("resumeButtonTooltip", formatKey("resume"))); } if (_prefs.features.removeCommandBarOptions && !this.props.canRewind) { return; } if (isWaitingOnBreak) { - return debugBtn(null, "pause", "disabled", L10N.getStr("pausePendingButtonTooltip"), true); - } - - return debugBtn(breakOnNext, "pause", "active", L10N.getFormatStr("pauseButtonTooltip", formatKey("pause"))); + return (0, _CommandBarButton.debugBtn)(null, "pause", "disabled", L10N.getStr("pausePendingButtonTooltip"), true); + } + + return (0, _CommandBarButton.debugBtn)(breakOnNext, "pause", "active", L10N.getFormatStr("pauseButtonTooltip", formatKey("pause"))); } /* * The pause on exception button has three states in this order: * 1. don't pause on exceptions [false, false] * 2. pause on uncaught exceptions [true, true] * 3. pause on all exceptions [true, false] */ @@ -24440,62 +24462,62 @@ class CommandBar extends _react.Componen canRewind } = this.props; if (canRewind || _prefs.features.breakpointsDropdown) { return; } if (!shouldPauseOnExceptions && !shouldIgnoreCaughtExceptions) { - return debugBtn(() => pauseOnExceptions(true, true), "pause-exceptions", "enabled", L10N.getStr("ignoreExceptions"), false, false); + return (0, _CommandBarButton.debugBtn)(() => pauseOnExceptions(true, true), "pause-exceptions", "enabled", L10N.getStr("ignoreExceptions"), false, false); } if (shouldPauseOnExceptions && shouldIgnoreCaughtExceptions) { - return debugBtn(() => pauseOnExceptions(true, false), "pause-exceptions", "uncaught enabled", L10N.getStr("pauseOnUncaughtExceptions"), false, true); - } - - return debugBtn(() => pauseOnExceptions(false, false), "pause-exceptions", "all enabled", L10N.getStr("pauseOnExceptions"), false, true); + return (0, _CommandBarButton.debugBtn)(() => pauseOnExceptions(true, false), "pause-exceptions", "uncaught enabled", L10N.getStr("pauseOnUncaughtExceptions"), false, true); + } + + return (0, _CommandBarButton.debugBtn)(() => pauseOnExceptions(false, false), "pause-exceptions", "all enabled", L10N.getStr("pauseOnExceptions"), false, true); } renderTimeTravelButtons() { const { isPaused, canRewind } = this.props; if (!canRewind || !isPaused) { return null; } const isDisabled = !isPaused; - return [debugBtn(this.props.rewind, "rewind", "active", "Rewind Execution"), debugBtn(() => this.props.resume, "resume", "active", L10N.getFormatStr("resumeButtonTooltip", formatKey("resume"))), _react2.default.createElement("div", { className: "divider" }), debugBtn(this.props.reverseStepOver, "reverseStepOver", "active", "Reverse step over"), debugBtn(this.props.stepOver, "stepOver", "active", L10N.getFormatStr("stepOverTooltip", formatKey("stepOver")), isDisabled), _react2.default.createElement("div", { className: "divider" }), debugBtn(this.props.stepOut, "stepOut", "active", L10N.getFormatStr("stepOutTooltip", formatKey("stepOut")), isDisabled), debugBtn(this.props.stepIn, "stepIn", "active", L10N.getFormatStr("stepInTooltip", formatKey("stepIn")), isDisabled)]; + return [(0, _CommandBarButton.debugBtn)(this.props.rewind, "rewind", "active", "Rewind Execution"), (0, _CommandBarButton.debugBtn)(() => this.props.resume, "resume", "active", L10N.getFormatStr("resumeButtonTooltip", formatKey("resume"))), _react2.default.createElement("div", { className: "divider" }), (0, _CommandBarButton.debugBtn)(this.props.reverseStepOver, "reverseStepOver", "active", "Reverse step over"), (0, _CommandBarButton.debugBtn)(this.props.stepOver, "stepOver", "active", L10N.getFormatStr("stepOverTooltip", formatKey("stepOver")), isDisabled), _react2.default.createElement("div", { className: "divider" }), (0, _CommandBarButton.debugBtn)(this.props.stepOut, "stepOut", "active", L10N.getFormatStr("stepOutTooltip", formatKey("stepOut")), isDisabled), (0, _CommandBarButton.debugBtn)(this.props.stepIn, "stepIn", "active", L10N.getFormatStr("stepInTooltip", formatKey("stepIn")), isDisabled)]; } replayPreviousButton() { const { history, historyPosition, canRewind } = this.props; const historyLength = history.length; if (canRewind || !historyLength || historyLength <= 1 || !_prefs.features.replay) { return null; } const enabled = historyPosition === 0; const activeClass = enabled ? "replay-inactive" : ""; - return debugBtn(() => this.setHistory(-1), `replay-previous ${activeClass}`, "active", L10N.getStr("replayPrevious"), enabled); + return (0, _CommandBarButton.debugBtn)(() => this.setHistory(-1), `replay-previous ${activeClass}`, "active", L10N.getStr("replayPrevious"), enabled); } replayNextButton() { const { history, historyPosition, canRewind } = this.props; const historyLength = history.length; if (canRewind || !historyLength || historyLength <= 1 || !_prefs.features.replay) { return null; } const enabled = historyPosition + 1 === historyLength; const activeClass = enabled ? "replay-inactive" : ""; - return debugBtn(() => this.setHistory(1), `replay-next ${activeClass}`, "active", L10N.getStr("replayNext"), enabled); + return (0, _CommandBarButton.debugBtn)(() => this.setHistory(1), `replay-next ${activeClass}`, "active", L10N.getStr("replayNext"), enabled); } renderStepPosition() { const { history, historyPosition, canRewind } = this.props; const historyLength = history.length; if (canRewind || !historyLength || !_prefs.features.replay) { return null; @@ -24577,29 +24599,29 @@ Object.defineProperty(exports, "__esModu var _react = __webpack_require__(0); var _react2 = _interopRequireDefault(_react); var _classnames = __webpack_require__(175); var _classnames2 = _interopRequireDefault(_classnames); -var _CommandBar = __webpack_require__(1608); +var _CommandBarButton = __webpack_require__(1764); __webpack_require__(1295); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* 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/>. */ class UtilsBar extends _react.Component { renderUtilButtons() { - return [(0, _CommandBar.debugBtn)(this.props.toggleShortcutsModal, "shortcuts", "active", L10N.getStr("shortcuts.buttonName"), false)]; + return [(0, _CommandBarButton.debugBtn)(this.props.toggleShortcutsModal, "shortcuts", "active", L10N.getStr("shortcuts.buttonName"), false)]; } render() { return _react2.default.createElement( "div", { className: (0, _classnames2.default)("command-bar bottom", { vertical: !this.props.horizontal @@ -26272,17 +26294,17 @@ function buildGeneratedBindingList(scope } } } } // Sort so we can binary-search. return generatedBindings.sort((a, b) => { const aStart = a.loc.start; - const bStart = a.loc.start; + const bStart = b.loc.start; if (aStart.line === bStart.line) { return (0, _locColumn.locColumn)(aStart) - (0, _locColumn.locColumn)(bStart); } return aStart.line - bStart.line; }); } @@ -29232,32 +29254,49 @@ InlineSVG.propTypes = { Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; +exports.debugBtn = debugBtn; + var _classnames = __webpack_require__(175); var _classnames2 = _interopRequireDefault(_classnames); var _react = __webpack_require__(0); var _react2 = _interopRequireDefault(_react); __webpack_require__(1788); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /* 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/>. */ +function debugBtn(onClick, type, className, tooltip, disabled = false, ariaPressed = false) { + return _react2.default.createElement( + CommandBarButton, + { + className: (0, _classnames2.default)(type, className), + disabled: disabled, + key: type, + onClick: onClick, + pressed: ariaPressed, + title: tooltip + }, + _react2.default.createElement("img", { className: type }) + ); +} + const CommandBarButton = props => { const { children, className, pressed = false } = props, rest = _objectWithoutProperties(props, ["children", "className", "pressed"]); return _react2.default.createElement( "button", _extends({ "aria-pressed": pressed, @@ -32542,23 +32581,54 @@ module.exports = ReactPropTypesSecret; /* 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/. */ const client = __webpack_require__(1939); const loadProperties = __webpack_require__(2017); const node = __webpack_require__(1940); +const { nodeIsError, nodeIsPrimitive } = node; const selection = __webpack_require__(3616); +const { MODE } = __webpack_require__(1357); +const { + REPS: { + Rep, + Grip + } +} = __webpack_require__(1372); + + +function shouldRenderRootsInReps(roots) { + if (roots.length > 1) { + return false; + } + + const root = roots[0]; + const name = root && root.name; + return (name === null || typeof name === "undefined") && (nodeIsPrimitive(root) || nodeIsError(root)); +} + +function renderRep(item, props) { + return Rep({ + ...props, + object: node.getValue(item), + mode: props.mode || MODE.TINY, + defaultRep: Grip + }); +} + module.exports = { client, loadProperties, node, - selection + renderRep, + selection, + shouldRenderRootsInReps }; /***/ }), /***/ 1939: /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -32645,21 +32715,22 @@ module.exports = { * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ const { get, has } = __webpack_require__(2); const { maybeEscapePropertyName } = __webpack_require__(1353); const ArrayRep = __webpack_require__(1448); const GripArrayRep = __webpack_require__(1450); const GripMap = __webpack_require__(1584); const GripMapEntryRep = __webpack_require__(1451); +const ErrorRep = __webpack_require__(1580); const MAX_NUMERICAL_PROPERTIES = 100; const NODE_TYPES = { - BUCKET: Symbol("[n…n]"), + BUCKET: Symbol("[n…m]"), DEFAULT_PROPERTIES: Symbol("<default properties>"), ENTRIES: Symbol("<entries>"), GET: Symbol("<get>"), GRIP: Symbol("GRIP"), MAP_ENTRY_KEY: Symbol("<key>"), MAP_ENTRY_VALUE: Symbol("<value>"), PROMISE_REASON: Symbol("<reason>"), PROMISE_STATE: Symbol("<state>"), @@ -32672,18 +32743,16 @@ const NODE_TYPES = { }; let WINDOW_PROPERTIES = {}; if (typeof window === "object") { WINDOW_PROPERTIES = Object.getOwnPropertyNames(window); } -const SAFE_PATH_PREFIX = "##-"; - function getType(item) { return item.type; } function getValue(item) { if (has(item, "contents.value")) { return get(item, "contents.value"); } @@ -32815,16 +32884,20 @@ function nodeIsGetter(item) { function nodeIsSetter(item) { return getType(item) === NODE_TYPES.SET; } function nodeIsBlock(item) { return getType(item) === NODE_TYPES.BLOCK; } +function nodeIsError(item) { + return ErrorRep.supportsObject(getValue(item)); +} + function nodeHasAccessors(item) { return !!getNodeGetter(item) || !!getNodeSetter(item); } function nodeSupportsNumericalBucketing(item) { // We exclude elements with entries since it's the <entries> node // itself that can have buckets. return nodeIsArrayLike(item) && !nodeHasEntries(item) || nodeIsEntries(item) || nodeIsBucket(item); @@ -32864,94 +32937,155 @@ function nodeNeedsNumericalBuckets(item) } function makeNodesForPromiseProperties(item) { const { promiseState: { reason, value, state } } = getValue(item); const properties = []; if (state) { - properties.push(createNode(item, "<state>", `${item.path}/${SAFE_PATH_PREFIX}state`, { value: state }, NODE_TYPES.PROMISE_STATE)); + properties.push(createNode({ + parent: item, + name: "<state>", + contents: { value: state }, + type: NODE_TYPES.PROMISE_STATE + })); } if (reason) { - properties.push(createNode(item, "<reason>", `${item.path}/${SAFE_PATH_PREFIX}reason`, { value: reason }, NODE_TYPES.PROMISE_REASON)); + properties.push(createNode({ + parent: item, + name: "<reason>", + contents: { value: reason }, + type: NODE_TYPES.PROMISE_REASON + })); } if (value) { - properties.push(createNode(item, "<value>", `${item.path}/${SAFE_PATH_PREFIX}value`, { value: value }, NODE_TYPES.PROMISE_VALUE)); + properties.push(createNode({ + parent: item, + name: "<value>", + contents: { value: value }, + type: NODE_TYPES.PROMISE_VALUE + })); } return properties; } function makeNodesForProxyProperties(item) { const { proxyHandler, proxyTarget } = getValue(item); - return [createNode(item, "<target>", `${item.path}/${SAFE_PATH_PREFIX}target`, { value: proxyTarget }, NODE_TYPES.PROXY_TARGET), createNode(item, "<handler>", `${item.path}/${SAFE_PATH_PREFIX}handler`, { value: proxyHandler }, NODE_TYPES.PROXY_HANDLER)]; + return [createNode({ + parent: item, + name: "<target>", + contents: { value: proxyTarget }, + type: NODE_TYPES.PROXY_TARGET + }), createNode({ + parent: item, + name: "<handler>", + contents: { value: proxyHandler }, + type: NODE_TYPES.PROXY_HANDLER + })]; } function makeNodesForEntries(item) { - const { path } = item; const nodeName = "<entries>"; - const entriesPath = `${path}/${SAFE_PATH_PREFIX}entries`; + const entriesPath = "<entries>"; if (nodeHasAllEntriesInPreview(item)) { let entriesNodes = []; const { preview } = getValue(item); if (preview.entries) { entriesNodes = preview.entries.map(([key, value], index) => { - return createNode(item, index, `${entriesPath}/${index}`, { - value: GripMapEntryRep.createGripMapEntry(key, value) + return createNode({ + parent: item, + name: index, + path: `${entriesPath}/${index}`, + contents: { value: GripMapEntryRep.createGripMapEntry(key, value) } }); }); } else if (preview.items) { entriesNodes = preview.items.map((value, index) => { - return createNode(item, index, `${entriesPath}/${index}`, { value }); - }); - } - return createNode(item, nodeName, entriesPath, entriesNodes, NODE_TYPES.ENTRIES); - } - return createNode(item, nodeName, entriesPath, null, NODE_TYPES.ENTRIES); + return createNode({ + parent: item, + name: index, + path: `${entriesPath}/${index}`, + contents: { value } + }); + }); + } + return createNode({ + parent: item, + name: nodeName, + contents: entriesNodes, + type: NODE_TYPES.ENTRIES + }); + } + return createNode({ + parent: item, + name: nodeName, + contents: null, + type: NODE_TYPES.ENTRIES + }); } function makeNodesForMapEntry(item) { const nodeValue = getValue(item); if (!nodeValue || !nodeValue.preview) { return []; } const { key, value } = nodeValue.preview; - const path = item.path; - - return [createNode(item, "<key>", `${path}/##key`, { value: key }, NODE_TYPES.MAP_ENTRY_KEY), createNode(item, "<value>", `${path}/##value`, { value }, NODE_TYPES.MAP_ENTRY_VALUE)]; + + return [createNode({ + parent: item, + name: "<key>", + contents: { value: key }, + type: NODE_TYPES.MAP_ENTRY_KEY + }), createNode({ + parent: item, + name: "<value>", + contents: { value }, + type: NODE_TYPES.MAP_ENTRY_VALUE + })]; } function getNodeGetter(item) { return get(item, "contents.get", undefined); } function getNodeSetter(item) { return get(item, "contents.set", undefined); } function makeNodesForAccessors(item) { const accessors = []; const getter = getNodeGetter(item); if (getter && getter.type !== "undefined") { - accessors.push(createNode(item, "<get>", `${item.path}/${SAFE_PATH_PREFIX}get`, { value: getter }, NODE_TYPES.GET)); + accessors.push(createNode({ + parent: item, + name: "<get>", + contents: { value: getter }, + type: NODE_TYPES.GET + })); } const setter = getNodeSetter(item); if (setter && setter.type !== "undefined") { - accessors.push(createNode(item, "<set>", `${item.path}/${SAFE_PATH_PREFIX}set`, { value: setter }, NODE_TYPES.SET)); + accessors.push(createNode({ + parent: item, + name: "<set>", + contents: { value: setter }, + type: NODE_TYPES.SET + })); } return accessors; } function sortProperties(properties) { return properties.sort((a, b) => { // Sort numbers in ascending order and sort strings lexicographically @@ -32962,80 +33096,94 @@ function sortProperties(properties) { return a > b ? 1 : -1; } return aInt - bInt; }); } function makeNumericalBuckets(parent) { - const parentPath = parent.path; const numProperties = getNumericalPropertiesCount(parent); // We want to have at most a hundred slices. const bucketSize = 10 ** Math.max(2, Math.ceil(Math.log10(numProperties)) - 2); const numBuckets = Math.ceil(numProperties / bucketSize); let buckets = []; for (let i = 1; i <= numBuckets; i++) { const minKey = (i - 1) * bucketSize; const maxKey = Math.min(i * bucketSize - 1, numProperties - 1); const startIndex = nodeIsBucket(parent) ? parent.meta.startIndex : 0; const minIndex = startIndex + minKey; const maxIndex = startIndex + maxKey; - const bucketKey = `${SAFE_PATH_PREFIX}bucket_${minIndex}-${maxIndex}`; const bucketName = `[${minIndex}…${maxIndex}]`; - buckets.push(createNode(parent, bucketName, `${parentPath}/${bucketKey}`, null, NODE_TYPES.BUCKET, { - startIndex: minIndex, - endIndex: maxIndex + buckets.push(createNode({ + parent, + name: bucketName, + contents: null, + type: NODE_TYPES.BUCKET, + meta: { + startIndex: minIndex, + endIndex: maxIndex + } })); } return buckets; } function makeDefaultPropsBucket(propertiesNames, parent, ownProperties) { - const parentPath = parent.path; - const userPropertiesNames = []; const defaultProperties = []; propertiesNames.forEach(name => { if (isDefaultWindowProperty(name)) { defaultProperties.push(name); } else { userPropertiesNames.push(name); } }); let nodes = makeNodesForOwnProps(userPropertiesNames, parent, ownProperties); if (defaultProperties.length > 0) { - const defaultPropertiesNode = createNode(parent, "<default properties>", `${parentPath}/${SAFE_PATH_PREFIX}default`, null, NODE_TYPES.DEFAULT_PROPERTIES); - - const defaultNodes = defaultProperties.map((name, index) => createNode(defaultPropertiesNode, maybeEscapePropertyName(name), `${parentPath}/${SAFE_PATH_PREFIX}bucket${index}/${name}`, ownProperties[name])); + const defaultPropertiesNode = createNode({ + parent, + name: "<default properties>", + contents: null, + type: NODE_TYPES.DEFAULT_PROPERTIES + }); + + const defaultNodes = defaultProperties.map((name, index) => createNode({ + parent: defaultPropertiesNode, + name: maybeEscapePropertyName(name), + path: `${index}/${name}`, + contents: ownProperties[name] + })); nodes.push(setNodeChildren(defaultPropertiesNode, defaultNodes)); } return nodes; } function makeNodesForOwnProps(propertiesNames, parent, ownProperties) { - const parentPath = parent.path; - return propertiesNames.map(name => createNode(parent, maybeEscapePropertyName(name), `${parentPath}/${name}`, ownProperties[name])); + return propertiesNames.map(name => createNode({ + parent, + name: maybeEscapePropertyName(name), + contents: ownProperties[name] + })); } function makeNodesForProperties(objProps, parent) { const { ownProperties = {}, ownSymbols, prototype, safeGetterValues } = objProps; - const parentPath = parent.path; const parentValue = getValue(parent); let allProperties = { ...ownProperties, ...safeGetterValues }; // Ignore properties that are neither non-concrete nor getters/setters. const propertiesNames = sortProperties(Object.keys(allProperties)).filter(name => { if (!allProperties[name]) { return false; @@ -33049,17 +33197,22 @@ function makeNodesForProperties(objProps if (parentValue && parentValue.class == "Window") { nodes = makeDefaultPropsBucket(propertiesNames, parent, allProperties); } else { nodes = makeNodesForOwnProps(propertiesNames, parent, allProperties); } if (Array.isArray(ownSymbols)) { ownSymbols.forEach((ownSymbol, index) => { - nodes.push(createNode(parent, ownSymbol.name, `${parentPath}/${SAFE_PATH_PREFIX}symbol-${index}`, ownSymbol.descriptor || null)); + nodes.push(createNode({ + parent, + name: ownSymbol.name, + path: `symbol-${index}`, + contents: ownSymbol.descriptor || null + })); }, this); } if (nodeIsPromise(parent)) { nodes.push(...makeNodesForPromiseProperties(parent)); } if (nodeHasEntries(parent)) { @@ -33076,42 +33229,61 @@ function makeNodesForProperties(objProps function makeNodeForPrototype(objProps, parent) { const { prototype } = objProps || {}; // Add the prototype if it exists and is not null if (prototype && prototype.type !== "null") { - return createNode(parent, "<prototype>", `${parent.path}/<prototype>`, { value: prototype }, NODE_TYPES.PROTOTYPE); + return createNode({ + parent, + name: "<prototype>", + contents: { value: prototype }, + type: NODE_TYPES.PROTOTYPE + }); } return null; } -function createNode(parent, name, path, contents, type = NODE_TYPES.GRIP, meta) { +function createNode(options) { + const { + parent, + name, + path, + contents, + type = NODE_TYPES.GRIP, + meta + } = options; + if (contents === undefined) { return null; } // The path is important to uniquely identify the item in the entire // tree. This helps debugging & optimizes React's rendering of large - // lists. The path will be separated by property name, - // i.e. `{ foo: { bar: { baz: 5 }}}` will have a path of `foo/bar/baz` + // lists. The path will be separated by property name, wrapped in a Symbol to avoid + // name clashing, + // i.e. `{ foo: { bar: { baz: 5 }}}` will have a path of Symbol(`foo/bar/baz`) // for the inner object. return { parent, name, - path, + path: parent ? Symbol(`${getSymbolDescriptor(parent.path)}/${path || name}`) : Symbol(path || name), contents, type, meta }; } +function getSymbolDescriptor(symbol) { + return symbol.toString().replace(/^(Symbol\()(.*)(\))$/, "$2"); +} + function setNodeChildren(node, children) { node.contents = children; return node; } function getChildren(options) { const { cachedNodes, @@ -33120,23 +33292,17 @@ function getChildren(options) { } = options; const key = item.path; if (cachedNodes && cachedNodes.has(key)) { return cachedNodes.get(key); } const loadedProps = loadedProperties.get(key); - const { - ownProperties, - ownSymbols, - safeGetterValues, - prototype - } = loadedProps || {}; - const hasLoadedProps = ownProperties || ownSymbols || safeGetterValues || prototype; + const hasLoadedProps = loadedProperties.has(key); // Because we are dynamically creating the tree as the user // expands it (not precalculated tree structure), we cache child // arrays. This not only helps performance, but is necessary // because the expanded state depends on instances of nodes // being the same across renders. If we didn't do this, each // node would be a new instance every render. // If the node needs properties, we only add children to @@ -33158,35 +33324,24 @@ function getChildren(options) { return addToCache(makeNodesForAccessors(item)); } if (nodeIsMapEntry(item)) { return addToCache(makeNodesForMapEntry(item)); } if (nodeIsProxy(item)) { - const nodes = makeNodesForProxyProperties(item); - const protoNode = makeNodeForPrototype(loadedProps, item); - if (protoNode) { - return addToCache(nodes.concat(protoNode)); - } - return nodes; - } - - if (nodeNeedsNumericalBuckets(item)) { + return addToCache(makeNodesForProxyProperties(item)); + } + + if (nodeNeedsNumericalBuckets(item) && hasLoadedProps) { + // Even if we have numerical buckets, we should have loaded non indexed properties, + // like length for example. const bucketNodes = makeNumericalBuckets(item); - // Even if we have numerical buckets, we might have loaded non indexed properties, - // like length for example. - if (hasLoadedProps) { - return addToCache(bucketNodes.concat(makeNodesForProperties(loadedProps, item))); - } - - // We don't cache the result here so we can have the prototype, properties and symbols - // when they are loaded. - return bucketNodes; + return addToCache(bucketNodes.concat(makeNodesForProperties(loadedProps, item))); } if (!nodeIsEntries(item) && !nodeIsBucket(item) && !nodeHasProperties(item)) { return []; } if (!hasLoadedProps) { return []; @@ -33269,16 +33424,17 @@ module.exports = { nodeHasAllEntriesInPreview, nodeHasChildren, nodeHasEntries, nodeHasProperties, nodeIsBlock, nodeIsBucket, nodeIsDefaultProperties, nodeIsEntries, + nodeIsError, nodeIsFunction, nodeIsGetter, nodeIsMapEntry, nodeIsMissingArguments, nodeIsObject, nodeIsOptimizedOut, nodeIsPrimitive, nodeIsPromise, @@ -33288,19 +33444,17 @@ module.exports = { nodeIsUninitializedBinding, nodeIsUnmappedBinding, nodeIsUnscopedBinding, nodeIsWindow, nodeNeedsNumericalBuckets, nodeSupportsNumericalBucketing, setNodeChildren, sortProperties, - NODE_TYPES, - // Export for testing purpose. - SAFE_PATH_PREFIX + NODE_TYPES }; /***/ }), /***/ 1941: /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -34465,17 +34619,17 @@ module.exports = "<!-- This Source Code module.exports = "<!-- 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/. --><svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 28 28\"><path d=\"M9.633 7.968h3.751v10.514c0 4.738-2.271 6.392-5.899 6.392-0.888 0-2.024-0.148-2.764-0.395l0.42-3.036c0.518 0.173 1.185 0.296 1.925 0.296 1.58 0 2.567-0.716 2.567-3.282v-10.489zM16.641 20.753c0.987 0.518 2.567 1.037 4.171 1.037 1.728 0 2.641-0.716 2.641-1.826 0-1.012-0.79-1.629-2.789-2.32-2.764-0.987-4.59-2.517-4.59-4.961 0-2.838 2.394-4.985 6.293-4.985 1.9 0 3.258 0.37 4.245 0.839l-0.839 3.011c-0.642-0.321-1.851-0.79-3.455-0.79-1.629 0-2.419 0.765-2.419 1.604 0 1.061 0.913 1.53 3.085 2.369 2.937 1.086 4.294 2.616 4.294 4.985 0 2.789-2.122 5.158-6.688 5.158-1.9 0-3.776-0.518-4.714-1.037l0.765-3.085z\"></path></svg>" /***/ }), /***/ 2252: /***/ (function(module, exports) { -module.exports = "<!-- 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/. --><svg viewBox=\"0 0 128 128\"><path xmlns=\"http://www.w3.org/2000/svg\" class=\"cls-2\" id=\"original-2\" d=\"M 1.5 63.91 v 62.5 h 125 V 1.41 H 1.5 Z m 100.73 -5 a 15.56 15.56 0 0 1 7.82 4.5 a 20.58 20.58 0 0 1 3 4 c 0 0.16 -5.4 3.81 -8.69 5.85 c -0.12 0.08 -0.6 -0.44 -1.13 -1.23 a 7.09 7.09 0 0 0 -5.87 -3.53 c -3.79 -0.26 -6.23 1.73 -6.21 5 a 4.58 4.58 0 0 0 0.54 2.34 c 0.83 1.73 2.38 2.76 7.24 4.86 c 8.95 3.85 12.78 6.39 15.16 10 c 2.66 4 3.25 10.46 1.45 15.24 c -2 5.2 -6.9 8.73 -13.83 9.9 a 38.32 38.32 0 0 1 -9.52 -0.1 a 23 23 0 0 1 -12.72 -6.63 c -1.15 -1.27 -3.39 -4.58 -3.25 -4.82 a 9.34 9.34 0 0 1 1.15 -0.73 L 82 101 l 3.59 -2.08 l 0.75 1.11 a 16.78 16.78 0 0 0 4.74 4.54 c 4 2.1 9.46 1.81 12.16 -0.62 a 5.43 5.43 0 0 0 0.69 -6.92 c -1 -1.39 -3 -2.56 -8.59 -5 c -6.45 -2.78 -9.23 -4.5 -11.77 -7.24 a 16.48 16.48 0 0 1 -3.43 -6.25 a 25 25 0 0 1 -0.22 -8 c 1.33 -6.23 6 -10.58 12.82 -11.87 A 31.66 31.66 0 0 1 102.23 58.93 Z M 72.89 64.15 l 0 5.12 H 56.66 V 115.5 H 45.15 V 69.26 H 28.88 v -5 A 49.19 49.19 0 0 1 29 59.09 C 29.08 59 39 59 51 59 L 72.83 59 Z\" data-name=\"original\"></path></svg>" +module.exports = "<!-- 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/. --><svg viewBox=\"0 0 128 128\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M 1.5 63.91 v 62.5 h 125 V 1.41 H 1.5 Z m 100.73 -5 a 15.56 15.56 0 0 1 7.82 4.5 a 20.58 20.58 0 0 1 3 4 c 0 0.16 -5.4 3.81 -8.69 5.85 c -0.12 0.08 -0.6 -0.44 -1.13 -1.23 a 7.09 7.09 0 0 0 -5.87 -3.53 c -3.79 -0.26 -6.23 1.73 -6.21 5 a 4.58 4.58 0 0 0 0.54 2.34 c 0.83 1.73 2.38 2.76 7.24 4.86 c 8.95 3.85 12.78 6.39 15.16 10 c 2.66 4 3.25 10.46 1.45 15.24 c -2 5.2 -6.9 8.73 -13.83 9.9 a 38.32 38.32 0 0 1 -9.52 -0.1 a 23 23 0 0 1 -12.72 -6.63 c -1.15 -1.27 -3.39 -4.58 -3.25 -4.82 a 9.34 9.34 0 0 1 1.15 -0.73 L 82 101 l 3.59 -2.08 l 0.75 1.11 a 16.78 16.78 0 0 0 4.74 4.54 c 4 2.1 9.46 1.81 12.16 -0.62 a 5.43 5.43 0 0 0 0.69 -6.92 c -1 -1.39 -3 -2.56 -8.59 -5 c -6.45 -2.78 -9.23 -4.5 -11.77 -7.24 a 16.48 16.48 0 0 1 -3.43 -6.25 a 25 25 0 0 1 -0.22 -8 c 1.33 -6.23 6 -10.58 12.82 -11.87 A 31.66 31.66 0 0 1 102.23 58.93 Z M 72.89 64.15 l 0 5.12 H 56.66 V 115.5 H 45.15 V 69.26 H 28.88 v -5 A 49.19 49.19 0 0 1 29 59.09 C 29.08 59 39 59 51 59 L 72.83 59 Z\" data-name=\"original\"></path></svg>" /***/ }), /***/ 2253: /***/ (function(module, exports) { // removed by extract-text-webpack-plugin @@ -34875,29 +35029,36 @@ var _extends = Object.assign || function * 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/>. */ // eslint-disable-next-line max-len exports.findGeneratedBindingFromPosition = findGeneratedBindingFromPosition; -var _lodash = __webpack_require__(2); - var _locColumn = __webpack_require__(2349); +var _filtering = __webpack_require__(3635); + var _firefox = __webpack_require__(1500); async function findGeneratedBindingFromPosition(sourceMaps, client, source, pos, name, type, generatedAstBindings) { const range = await getGeneratedLocationRange(pos, source, sourceMaps); if (range) { - const result = await findGeneratedReference(type, generatedAstBindings, _extends({ - type: pos.type - }, range)); + let result; + if (type === "import") { + result = await findGeneratedImportReference(type, generatedAstBindings, _extends({ + type: pos.type + }, range)); + } else { + result = await findGeneratedReference(type, generatedAstBindings, _extends({ + type: pos.type + }, range)); + } if (result) { return result; } } if (type === "import" && pos.type === "decl") { let importRange = range; @@ -34921,38 +35082,82 @@ async function findGeneratedBindingFromP return await findGeneratedImportDeclaration(generatedAstBindings, _extends({ importName }, importRange)); } return null; } +function filterApplicableBindings(bindings, mapped) { + // Any binding overlapping a part of the mapping range. + return (0, _filtering.filterSortedArray)(bindings, binding => { + if (positionCmp(binding.loc.end, mapped.start) < 0) { + return -1; + } + + // Currently we allow ranges to count if they start 1 character before, + // so we allow that when filtering here. + // See mapBindingReferenceToDescriptor for more info. + if (positionCmp(_extends({}, binding.loc.start, { + column: (0, _locColumn.locColumn)(binding.loc.start) - 1 + }), mapped.end) > 0) { + return 1; + } + + return 0; + }); +} + /** * Given a mapped range over the generated source, attempt to resolve a real * binding descriptor that can be used to access the value. */ async function findGeneratedReference(type, generatedAstBindings, mapped) { - return generatedAstBindings.reduce(async (acc, val) => { + const bindings = filterApplicableBindings(generatedAstBindings, mapped); + + return bindings.reduce(async (acc, val) => { const accVal = await acc; if (accVal) { return accVal; } - return type === "import" ? await mapImportReferenceToDescriptor(val, mapped) : await mapBindingReferenceToDescriptor(val, mapped); + return mapBindingReferenceToDescriptor(val, mapped); + }, null); +} + +async function findGeneratedImportReference(type, generatedAstBindings, mapped) { + let bindings = filterApplicableBindings(generatedAstBindings, mapped); + + // When wrapped, for instance as `Object(ns.default)`, the `Object` binding + // will be the first in the list. To avoid resolving `Object` as the + // value of the import itself, we potentially skip the first binding. + if (bindings.length > 1 && !bindings[0].loc.meta && bindings[1].loc.meta) { + bindings = bindings.slice(1); + } + + return bindings.reduce(async (acc, val) => { + const accVal = await acc; + if (accVal) { + return accVal; + } + + return mapImportReferenceToDescriptor(val, mapped); }, null); } /** * Given a mapped range over the generated source and the name of the imported * value that is referenced, attempt to resolve a binding descriptor for * the import's value. */ async function findGeneratedImportDeclaration(generatedAstBindings, mapped) { - return generatedAstBindings.reduce(async (acc, val) => { + const bindings = filterApplicableBindings(generatedAstBindings, mapped); + + return bindings.reduce(async (acc, val) => { const accVal = await acc; if (accVal) { return accVal; } return await mapImportDeclarationToDescriptor(val, mapped); }, null); } @@ -35147,18 +35352,29 @@ function positionCmp(p1, p2) { async function getGeneratedLocationRange(pos, source, sourceMaps) { const start = await getGeneratedLocation(sourceMaps, pos.start, source); const end = await getGeneratedLocation(sourceMaps, pos.end, source); // Since the map takes the closest location, sometimes mapping a // binding's location can point at the start of a binding listed after // it, so we need to make sure it maps to a location that actually has // a size in order to avoid picking up the wrong descriptor. - if ((0, _lodash.isEqual)(start, end)) { - return null; + if (positionCmp(start, end) === 0) { + return null; + } + if (positionCmp(start, end) > 0) { + // This will be fixed in future range work, but right now it is + // possible for the start to be after the end because of the way we + // map ranges. For now we create a placeholder single-character range. + return { + start, + end: _extends({}, start, { + column: start.column + 1 + }) + }; } return { start, end }; } async function getGeneratedLocation(sourceMaps, pos, source) { const all = await sourceMaps.getAllGeneratedLocations(pos, source); if (all.length > 0) { @@ -38211,23 +38427,16 @@ const { const dom = __webpack_require__(1758); const { connect } = __webpack_require__(3592); const { bindActionCreators } = __webpack_require__(3593); const Tree = createFactory(_devtoolsComponents2.default.Tree); __webpack_require__(1325); const classnames = __webpack_require__(175); - -const { - REPS: { - Rep, - Grip - } -} = __webpack_require__(1372); const { MODE } = __webpack_require__(1357); const Utils = __webpack_require__(1938); const { getChildren, @@ -38302,17 +38511,21 @@ class ObjectInspector extends Component if (roots !== nextProps.roots) { // Since the roots changed, we assume the properties did as well. Thus we can clear // the cachedNodes to avoid bugs and memory leaks. this.cachedNodes.clear(); return true; } - return expandedPaths.size !== nextProps.expandedPaths.size || loadedProperties.size !== nextProps.loadedProperties.size || [...expandedPaths].some(key => !nextProps.expandedPaths.has(key)); + // We should update if: + // - there are new loaded properties + // - OR the expanded paths number changed, and all of them have properties loaded + // - OR the expanded paths number did not changed, but old and new sets differ + return loadedProperties.size !== nextProps.loadedProperties.size || expandedPaths.size !== nextProps.expandedPaths.size && [...nextProps.expandedPaths].every(path => nextProps.loadedProperties.has(path)) || expandedPaths.size === nextProps.expandedPaths.size && [...nextProps.expandedPaths].some(key => !expandedPaths.has(key)); } componentWillUnmount() { const { releaseActor } = this.props; if (typeof releaseActor !== "function") { return; } @@ -38335,17 +38548,17 @@ class ObjectInspector extends Component }); } getRoots() { return this.props.roots; } getNodeKey(item) { - return item.path || JSON.stringify(item); + return item.path && typeof item.path.toString === "function" ? item.path.toString() : JSON.stringify(item); } setExpanded(item, expand) { if (nodeIsPrimitive(item)) { return; } const { @@ -38427,17 +38640,17 @@ class ObjectInspector extends Component return { label, value: dom.span({ className: "unavailable" }, "(unavailable)") }; } if (nodeIsFunction(item) && !nodeIsGetter(item) && !nodeIsSetter(item) && (this.props.mode === MODE.TINY || !this.props.mode)) { return { - label: this.renderGrip(item, { + label: Utils.renderRep(item, { ...this.props, functionName: label }) }; } if (nodeHasProperties(item) || nodeHasAccessors(item) || nodeIsMapEntry(item) || isPrimitive) { let repsProp = { ...this.props }; @@ -38445,17 +38658,17 @@ class ObjectInspector extends Component repsProp.mode = this.props.mode === MODE.LONG ? MODE.SHORT : MODE.TINY; } if (expanded) { repsProp.mode = MODE.TINY; } return { label, - value: this.renderGrip(item, repsProp) + value: Utils.renderRep(item, repsProp) }; } return { label }; } @@ -38529,57 +38742,38 @@ class ObjectInspector extends Component renderTreeItem(item, depth, focused, arrow, expanded) { const { label, value } = this.getTreeItemLabelAndValue(item, depth, expanded); const labelElement = this.renderTreeItemLabel(label, item, depth, focused, expanded); const delimiter = value && labelElement ? dom.span({ className: "object-delimiter" }, ": ") : null; return dom.div(this.getTreeTopElementProps(item, depth, focused, expanded), arrow, labelElement, delimiter, value); } - renderGrip(item, props) { - const object = getValue(item); - return Rep({ - ...props, - object, - mode: props.mode || MODE.TINY, - defaultRep: Grip - }); - } - render() { const { autoExpandAll = true, autoExpandDepth = 1, disabledFocus, disableWrap = false, expandedPaths, focusedItem, inline } = this.props; - let roots = this.getRoots(); - if (roots.length === 1) { - const root = roots[0]; - const name = root && root.name; - if (nodeIsPrimitive(root) && (name === null || typeof name === "undefined")) { - return this.renderGrip(root, this.props); - } - } - return Tree({ className: classnames({ inline, nowrap: disableWrap, "object-inspector": true }), autoExpandAll, autoExpandDepth, disabledFocus, - isExpanded: item => expandedPaths && expandedPaths.has(this.getNodeKey(item)), + isExpanded: item => expandedPaths && expandedPaths.has(item.path), isExpandable: item => nodeIsPrimitive(item) === false, focused: focusedItem, getRoots: this.getRoots, getParent, getChildren: this.getItemChildren, getKey: this.getNodeKey, @@ -38665,17 +38859,20 @@ const { * which also means that it will call the action responsible to fetch properties. */ function nodeExpand(node, actor, loadedProperties, createObjectClient) { return async ({ dispatch }) => { dispatch({ type: "NODE_EXPAND", data: { node } }); - dispatch(nodeLoadProperties(node, actor, loadedProperties, createObjectClient)); + + if (!loadedProperties.has(node.path)) { + dispatch(nodeLoadProperties(node, actor, loadedProperties, createObjectClient)); + } }; } function nodeCollapse(node) { return { type: "NODE_COLLAPSE", data: { node } }; @@ -38690,19 +38887,17 @@ function nodeFocus(node) { /* * This action checks if we need to fetch properties, entries, prototype and symbols * for a given node. If we do, it will call the appropriate ObjectClient functions. */ function nodeLoadProperties(item, actor, loadedProperties, createObjectClient) { return async ({ dispatch }) => { try { const properties = await loadItemProperties(item, createObjectClient, loadedProperties); - if (Object.keys(properties).length > 0) { - dispatch(nodePropertiesLoaded(item, actor, properties)); - } + dispatch(nodePropertiesLoaded(item, actor, properties)); } catch (e) { console.error(e); } }; } function nodePropertiesLoaded(node, actor, properties) { return { @@ -39006,17 +39201,17 @@ const { createNode, getChildren } = _dev const { loadItemProperties } = _devtoolsReps.ObjectInspectorUtils.loadProperties; class FrameworkComponent extends _react.PureComponent { async componentWillMount() { const expression = "this;"; const { selectedFrame, setPopupObjectProperties } = this.props; const value = selectedFrame.this; - const root = createNode(null, expression, expression, { value }); + const root = createNode({ name: expression, contents: { value } }); const properties = await loadItemProperties(root, _firefox.createObjectClient); if (properties) { setPopupObjectProperties(value, properties); } } renderReactComponent() { const { selectedFrame, popupObjectProperties } = this.props; @@ -39024,16 +39219,19 @@ class FrameworkComponent extends _react. const value = selectedFrame.this; const root = { name: expression, path: expression, contents: { value } }; const loadedRootProperties = popupObjectProperties[value.actor]; + if (!loadedRootProperties) { + return null; + } let roots = getChildren({ item: root, loadedProperties: new Map([[root.path, loadedRootProperties]]) }); roots = roots.filter(r => ["state", "props"].includes(r.name)); @@ -39420,16 +39618,66 @@ class Breakpoint extends _react.Componen ); } } exports.default = Breakpoint; /***/ }), +/***/ 3635: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.filterSortedArray = filterSortedArray; +function findInsertionLocation(array, callback) { + let left = 0; + let right = array.length; + while (left < right) { + const mid = Math.floor((left + right) / 2); + const item = array[mid]; + + const result = callback(item); + if (result === 0) { + left = mid; + break; + } + if (result >= 0) { + right = mid; + } else { + left = mid + 1; + } + } + + // Ensure the value is the start of any set of matches. + let i = left; + while (i > 0 && callback(array[i]) >= 0) { + i--; + } + return i + 1; +} + +function filterSortedArray(array, callback) { + const start = findInsertionLocation(array, callback); + + const results = []; + for (let i = start; i < array.length && callback(array[i]) === 0; i++) { + results.push(array[i]); + } + + return results; +} + +/***/ }), + /***/ 364: /***/ (function(module, exports) { module.exports = "<!-- 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/. --><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 33 12\"><path id=\"base-path\" d=\"M27.1,0H1C0.4,0,0,0.4,0,1v10c0,0.6,0.4,1,1,1h26.1 c0.6,0,1.2-0.3,1.5-0.7L33,6l-4.4-5.3C28.2,0.3,27.7,0,27.1,0z\"></path></svg>" /***/ }), /***/ 365:
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-asm.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-asm.js @@ -4,16 +4,20 @@ add_task(async function() { // After reload() we are getting getSources notifiction for old sources, // using the debugger statement to really stop are reloaded page. await waitForPaused(dbg); await resume(dbg); await waitForSources(dbg, "doc-asm.html", "asm.js"); + // Expand nodes and make sure more sources appear. + is(findAllElements(dbg, "sourceNodes").length, 2); + + await clickElement(dbg, "sourceDirectoryLabel", 2); is(findAllElements(dbg, "sourceNodes").length, 4); await selectSource(dbg, "asm.js"); await addBreakpoint(dbg, "asm.js", 7); invokeInTab("runAsm"); await waitForPaused(dbg);
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-sources.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sources.js @@ -19,33 +19,16 @@ async function assertSourceCount(dbg, co function getLabel(dbg, index) { return findElement(dbg, "sourceNode", index) .textContent.trim() .replace(/^[\s\u200b]*/g, ""); } add_task(async function() { const dbg = await initDebugger("doc-sources.html"); - const { selectors: { getSelectedSource, getExpandedState }, getState } = dbg; - - await waitForSources(dbg, "nested-source"); - await selectSource(dbg, "nested-source"); - - const expanded = getExpandedState(getState()); - - ok( - expanded.has( - `example.com/browser/devtools/client/debugger/new/test/mochitest/examples/nested/nested/` - ), - "Nodes in path are automatically expanded" - ); -}); - -add_task(async function() { - const dbg = await initDebugger("doc-sources.html"); const { selectors: { getSelectedSource }, getState } = dbg; await waitForSources(dbg, "simple1", "simple2", "nested-source", "long.js"); // Expand nodes and make sure more sources appear. await assertSourceCount(dbg, 2); await clickElement(dbg, "sourceDirectoryLabel", 2);
--- a/devtools/client/themes/images/debugger/typescript.svg +++ b/devtools/client/themes/images/debugger/typescript.svg @@ -1,6 +1,6 @@ <!-- 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/. --> -<svg viewBox="0 0 128 128"> -<path xmlns="http://www.w3.org/2000/svg" class="cls-2" id="original-2" d="M 1.5 63.91 v 62.5 h 125 V 1.41 H 1.5 Z m 100.73 -5 a 15.56 15.56 0 0 1 7.82 4.5 a 20.58 20.58 0 0 1 3 4 c 0 0.16 -5.4 3.81 -8.69 5.85 c -0.12 0.08 -0.6 -0.44 -1.13 -1.23 a 7.09 7.09 0 0 0 -5.87 -3.53 c -3.79 -0.26 -6.23 1.73 -6.21 5 a 4.58 4.58 0 0 0 0.54 2.34 c 0.83 1.73 2.38 2.76 7.24 4.86 c 8.95 3.85 12.78 6.39 15.16 10 c 2.66 4 3.25 10.46 1.45 15.24 c -2 5.2 -6.9 8.73 -13.83 9.9 a 38.32 38.32 0 0 1 -9.52 -0.1 a 23 23 0 0 1 -12.72 -6.63 c -1.15 -1.27 -3.39 -4.58 -3.25 -4.82 a 9.34 9.34 0 0 1 1.15 -0.73 L 82 101 l 3.59 -2.08 l 0.75 1.11 a 16.78 16.78 0 0 0 4.74 4.54 c 4 2.1 9.46 1.81 12.16 -0.62 a 5.43 5.43 0 0 0 0.69 -6.92 c -1 -1.39 -3 -2.56 -8.59 -5 c -6.45 -2.78 -9.23 -4.5 -11.77 -7.24 a 16.48 16.48 0 0 1 -3.43 -6.25 a 25 25 0 0 1 -0.22 -8 c 1.33 -6.23 6 -10.58 12.82 -11.87 A 31.66 31.66 0 0 1 102.23 58.93 Z M 72.89 64.15 l 0 5.12 H 56.66 V 115.5 H 45.15 V 69.26 H 28.88 v -5 A 49.19 49.19 0 0 1 29 59.09 C 29.08 59 39 59 51 59 L 72.83 59 Z" data-name="original" /> -</svg> \ No newline at end of file +<svg viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"> +<path d="M 1.5 63.91 v 62.5 h 125 V 1.41 H 1.5 Z m 100.73 -5 a 15.56 15.56 0 0 1 7.82 4.5 a 20.58 20.58 0 0 1 3 4 c 0 0.16 -5.4 3.81 -8.69 5.85 c -0.12 0.08 -0.6 -0.44 -1.13 -1.23 a 7.09 7.09 0 0 0 -5.87 -3.53 c -3.79 -0.26 -6.23 1.73 -6.21 5 a 4.58 4.58 0 0 0 0.54 2.34 c 0.83 1.73 2.38 2.76 7.24 4.86 c 8.95 3.85 12.78 6.39 15.16 10 c 2.66 4 3.25 10.46 1.45 15.24 c -2 5.2 -6.9 8.73 -13.83 9.9 a 38.32 38.32 0 0 1 -9.52 -0.1 a 23 23 0 0 1 -12.72 -6.63 c -1.15 -1.27 -3.39 -4.58 -3.25 -4.82 a 9.34 9.34 0 0 1 1.15 -0.73 L 82 101 l 3.59 -2.08 l 0.75 1.11 a 16.78 16.78 0 0 0 4.74 4.54 c 4 2.1 9.46 1.81 12.16 -0.62 a 5.43 5.43 0 0 0 0.69 -6.92 c -1 -1.39 -3 -2.56 -8.59 -5 c -6.45 -2.78 -9.23 -4.5 -11.77 -7.24 a 16.48 16.48 0 0 1 -3.43 -6.25 a 25 25 0 0 1 -0.22 -8 c 1.33 -6.23 6 -10.58 12.82 -11.87 A 31.66 31.66 0 0 1 102.23 58.93 Z M 72.89 64.15 l 0 5.12 H 56.66 V 115.5 H 45.15 V 69.26 H 28.88 v -5 A 49.19 49.19 0 0 1 29 59.09 C 29.08 59 39 59 51 59 L 72.83 59 Z" data-name="original" /> +</svg>