From 42bc3542cc2d45f22332d4bb0bf0d7a711f51a6c Mon Sep 17 00:00:00 2001 From: Jason Laster Date: Wed, 11 Apr 2018 18:13:30 -0400 Subject: [PATCH] Bug 1453070 - Update Debugger Frontend v35. r=jdescottes --- devtools/client/debugger/new/README.mozilla | 4 +- devtools/client/debugger/new/debugger.css | 54 ++- devtools/client/debugger/new/debugger.js | 336 ++++++++++++++---- devtools/client/debugger/new/parser-worker.js | 26 +- .../debugger/new/test/mochitest/browser.ini | 1 + .../browser_dbg-expressions-error.js | 2 +- .../test/mochitest/browser_dbg-expressions.js | 3 +- .../test/mochitest/browser_dbg-navigation.js | 28 +- .../browser_dbg-sourcemaps-reload.js | 5 +- .../examples/doc-scripts-debugger.html | 20 ++ .../debugger/new/test/mochitest/head.js | 8 + devtools/client/jar.mn | 1 + .../client/themes/images/debugger/tab.svg | 6 + 13 files changed, 387 insertions(+), 107 deletions(-) create mode 100644 devtools/client/debugger/new/test/mochitest/examples/doc-scripts-debugger.html create mode 100644 devtools/client/themes/images/debugger/tab.svg diff --git a/devtools/client/debugger/new/README.mozilla b/devtools/client/debugger/new/README.mozilla index 724d927b58f5..5001246f3b93 100644 --- a/devtools/client/debugger/new/README.mozilla +++ b/devtools/client/debugger/new/README.mozilla @@ -1,9 +1,9 @@ This is the debugger.html project output. See https://github.com/devtools-html/debugger.html -Version 34.0 +Version 35.0 -Comparison: https://github.com/devtools-html/debugger.html/compare/release-33...release-34 +Comparison: https://github.com/devtools-html/debugger.html/compare/release-34...release-35 Packages: - babel-plugin-transform-es2015-modules-commonjs @6.26.0 diff --git a/devtools/client/debugger/new/debugger.css b/devtools/client/debugger/new/debugger.css index be1ebd8d2a06..79179960e93d 100644 --- a/devtools/client/debugger/new/debugger.css +++ b/devtools/client/debugger/new/debugger.css @@ -612,6 +612,11 @@ img.source-icon { height: 15px; } +img.result-item-icon { + height: 18px; + width: 18px; +} + img.domain { mask: url("chrome://devtools/skin/images/debugger/domain.svg") no-repeat; } @@ -628,6 +633,10 @@ img.javascript { mask: url("chrome://devtools/skin/images/debugger/javascript.svg") no-repeat; } +img.tab { + mask: url("chrome://devtools/skin/images/debugger/tab.svg") no-repeat; +} + img.react { mask: url("chrome://devtools/skin/images/debugger/react.svg") no-repeat; } @@ -651,6 +660,13 @@ img.source-icon { display: inline-block; } +img.result-item-icon { + mask-size: 100%; + margin-inline-end: 15px; + margin-inline-start: 5px; + display: inline-block; +} + .refresh svg, .shortcut svg, .worker svg { @@ -756,6 +772,8 @@ html[dir="rtl"] .arrow svg, display: grid; grid-template-columns: 1fr; align-content: start; + + line-height: 1.4em; } .managed-tree .tree button { @@ -1603,6 +1621,10 @@ menuseparator { .function-signature .comma { color: var(--object-color); } +/* 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 . */ + .command-bar-button { appearance: none; background: transparent; @@ -2774,7 +2796,6 @@ debug-expression-error { .breakpoints-list .breakpoint { font-size: 12px; color: var(--theme-content-color1); - line-height: 1em; position: relative; transition: all 0.25s ease; padding: 0.5em 1em 0.5em 0.5em; @@ -3063,6 +3084,10 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line { .frames ul .frames-group.expanded .badge { color: var(--theme-highlight-blue); } +/* 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 . */ + .badge { --size: 17px; --radius: calc(var(--size) / 2); @@ -3617,6 +3642,10 @@ html[dir="rtl"] .dropdown { left: 0; top: 0; } +/* 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 . */ + .dropdown span.icon-spacer { margin-left: 8px; } @@ -4019,6 +4048,7 @@ html .welcomebox .toggle-button-end.collapsed { padding: 10px; flex-direction: row; border-bottom: 1px solid var(--theme-splitter-color); + line-height: 18px; } .result-list.small li { @@ -4050,8 +4080,24 @@ html .welcomebox .toggle-button-end.collapsed { background: var(--grey-70); } +.result-list li .result-item-icon { + background-color: var(--theme-comment); +} +.result-list li.selected .result-item-icon { + background-color: var(--theme-selection-color); +} + +.result-list li .result-item-icon.tab { + mask-size: 150%; + mask-position: 2px 4px; +} + +.result-list li img.result-item-icon { + width: 16px; + height: 16px; +} + .result-list li .title { - line-height: 1.5em; word-break: break-all; text-overflow: ellipsis; white-space: nowrap; @@ -4107,6 +4153,10 @@ html .welcomebox .toggle-button-end.collapsed { .theme-dark .result-list { background-color: var(--theme-body-background); } +/* 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 . */ + .result-item .title .highlight { font-weight: bold; background-color: transparent; diff --git a/devtools/client/debugger/new/debugger.js b/devtools/client/debugger/new/debugger.js index fa96b23e98d3..350ee93fd604 100644 --- a/devtools/client/debugger/new/debugger.js +++ b/devtools/client/debugger/new/debugger.js @@ -2283,7 +2283,7 @@ module.exports = feature; Object.defineProperty(exports, "__esModule", { value: true }); -exports.isMinified = undefined; +exports.sourceTypes = exports.isMinified = undefined; var _isMinified = __webpack_require__(1778); @@ -2310,6 +2310,7 @@ exports.getMode = getMode; exports.isLoaded = isLoaded; exports.isLoading = isLoading; exports.getTextAtPosition = getTextAtPosition; +exports.getSourceClassnames = getSourceClassnames; var _devtoolsSourceMap = __webpack_require__(1360); @@ -2319,6 +2320,16 @@ 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" +}; + /** * Trims the query part or reference identifier of a url string, if necessary. * @@ -2609,6 +2620,14 @@ function getTextAtPosition(source, location) { return lineText.slice(column, column + 100).trim(); } +function getSourceClassnames(source) { + if (source && source.isBlackBoxed) { + return "blackBox"; + } + + return sourceTypes[(0, _sourcesTree.getExtension)(source)] || "file"; +} + /***/ }), /***/ 1357: @@ -2704,6 +2723,9 @@ Object.keys(_createEditor).forEach(function (key) { } }); }); +exports.setEditor = setEditor; +exports.getEditor = getEditor; +exports.removeEditor = removeEditor; exports.shouldShowPrettyPrint = shouldShowPrettyPrint; exports.shouldShowFooter = shouldShowFooter; exports.traverseResults = traverseResults; @@ -2727,6 +2749,20 @@ var _wasm = __webpack_require__(1401); var _devtoolsSourceMap = __webpack_require__(1360); +let editor; + +function setEditor(_editor) { + editor = _editor; +} + +function getEditor() { + return editor; +} + +function removeEditor() { + editor = null; +} + function shouldShowPrettyPrint(selectedSource) { if (!selectedSource) { return false; @@ -2812,17 +2848,17 @@ function isVisible(codeMirror, top, left) { return inXView && inYView; } -function markText(editor, className, { start, end }) { - return editor.codeMirror.markText({ ch: start.column, line: start.line }, { ch: end.column, line: end.line }, { className }); +function markText(_editor, className, { start, end }) { + return _editor.codeMirror.markText({ ch: start.column, line: start.line }, { ch: end.column, line: end.line }, { className }); } -function lineAtHeight(editor, sourceId, event) { - const editorLine = editor.codeMirror.lineAtHeight(event.clientY); - return toSourceLine(sourceId, editorLine); +function lineAtHeight(_editor, sourceId, event) { + const _editorLine = _editor.codeMirror.lineAtHeight(event.clientY); + return toSourceLine(sourceId, _editorLine); } -function getSourceLocationFromMouseEvent(editor, selectedLocation, e) { - const { line, ch } = editor.codeMirror.coordsChar({ +function getSourceLocationFromMouseEvent(_editor, selectedLocation, e) { + const { line, ch } = _editor.codeMirror.coordsChar({ left: e.clientX, top: e.clientY }); @@ -3908,7 +3944,8 @@ function isDirectory(url) { } function getExtension(source) { - const parsedUrl = (0, _url.parse)(source.get("url")).pathname; + const url = source.get ? source.get("url") : source.url; + const parsedUrl = (0, _url.parse)(url).pathname; if (!parsedUrl) { return ""; } @@ -5290,6 +5327,7 @@ exports.copyToTheClipboard = copyToTheClipboard; * Clipboard function taken from * https://dxr.mozilla.org/mozilla-central/source/devtools/shared/platform/content/clipboard.js */ + function copyToTheClipboard(string) { const doCopy = function (e) { e.clipboardData.setData("text/plain", string); @@ -5502,7 +5540,6 @@ const createPauseState = exports.createPauseState = () => ({ }); const emptyPauseState = { - pause: null, frames: null, frameScopes: { generated: {}, @@ -5511,7 +5548,7 @@ const emptyPauseState = { }, selectedFrameId: null, loadedObjects: {}, - previousLocation: null + why: null }; function update(state = createPauseState(), action) { @@ -5635,9 +5672,7 @@ function update(state = createPauseState(), action) { } case "RESUME": - // We clear why on resume because we need it to decide if - // we shoul re-evaluate watch expressions. - return _extends({}, state, { why: null }); + return _extends({}, state, emptyPauseState); case "EVALUATE_EXPRESSION": return _extends({}, state, { @@ -6391,10 +6426,11 @@ function deleteExpression(expression) { */ function evaluateExpressions() { return async function ({ dispatch, getState, client }) { - const expressions = (0, _selectors.getExpressions)(getState()); - for (const expression of expressions) { - await dispatch(evaluateExpression(expression)); - } + const expressions = (0, _selectors.getExpressions)(getState()).toJS(); + const inputs = expressions.map(({ input }) => input); + const frameId = (0, _selectors.getSelectedFrameId)(getState()); + const results = await client.evaluateExpressions(inputs, frameId); + dispatch({ type: "EVALUATE_EXPRESSIONS", inputs, results }); }; } @@ -6425,7 +6461,7 @@ function evaluateExpression(expression) { return dispatch({ type: "EVALUATE_EXPRESSION", input: expression.input, - [_promise.PROMISE]: client.evaluate((0, _expressions.wrapExpression)(input), { frameId }) + [_promise.PROMISE]: client.evaluateInFrame((0, _expressions.wrapExpression)(input), frameId) }); }; } @@ -7912,6 +7948,7 @@ function update(state = createExpressionState(), action) { value: null, updating: true }); + case "UPDATE_EXPRESSION": const key = action.expression.input; return updateExpressionInList(state, key, { @@ -7919,14 +7956,26 @@ function update(state = createExpressionState(), action) { value: null, updating: true }).set("expressionError", !!action.expressionError); + case "EVALUATE_EXPRESSION": return updateExpressionInList(state, action.input, { input: action.input, value: action.value, updating: false }); + + case "EVALUATE_EXPRESSIONS": + const { inputs, results } = action; + + return (0, _lodash.zip)(inputs, results).reduce((newState, [input, result]) => updateExpressionInList(newState, input, { + input: input, + value: result, + updating: false + }), state); + case "DELETE_EXPRESSION": return deleteExpression(state, action.input); + case "CLEAR_EXPRESSION_ERROR": return state.set("expressionError", false); @@ -9576,6 +9625,14 @@ function wrapExpression(input) { `); } +function isUnavailable(value) { + if (!value.preview || !value.preview.name) { + return false; + } + + return ["ReferenceError", "TypeError"].includes(value.preview.name); +} + function getValue(expression) { const value = expression.value; if (!value) { @@ -9586,6 +9643,9 @@ function getValue(expression) { } if (value.exception) { + if (isUnavailable(value.exception)) { + return { value: { unavailable: true } }; + } return { path: value.from, value: value.exception @@ -9601,8 +9661,11 @@ function getValue(expression) { if (value.result && value.result.class == "Error") { const { name, message } = value.result.preview; - const newValue = name === "ReferenceError" ? { unavailable: true } : `${name}: ${message}`; + if (isUnavailable(value.result)) { + return { value: { unavailable: true } }; + } + const newValue = `${name}: ${message}`; return { path: value.input, value: newValue }; } @@ -10158,6 +10221,11 @@ var _initialiseProps = function () { return _react2.default.createElement( "li", props, + _react2.default.createElement( + "div", + null, + _react2.default.createElement("img", { className: item.icon }) + ), _react2.default.createElement( "div", { id: `${item.id}-title`, className: "title" }, @@ -12512,18 +12580,22 @@ function setBreakpointCondition(breakpointId, location, condition, noSliding) { }); } -function evaluateInFrame(frameId, script) { +async function evaluateInFrame(script, frameId) { return evaluate(script, { frameId }); } +async function evaluateExpressions(scripts, frameId) { + return Promise.all(scripts.map(script => evaluate(script, { frameId }))); +} + function evaluate(script, { frameId } = {}) { const params = frameId ? { frameActor: frameId } : {}; if (!tabTarget || !tabTarget.activeConsole || !script) { - return Promise.resolve(); + return Promise.resolve({}); } return new Promise(resolve => { - tabTarget.activeConsole.evaluateJS(script, result => resolve(result), params); + tabTarget.activeConsole.evaluateJSAsync(script, result => resolve(result), params); }); } @@ -12681,6 +12753,7 @@ const clientCommands = { setBreakpointCondition, evaluate, evaluateInFrame, + evaluateExpressions, debuggeeCommand, navigate, reload, @@ -13298,9 +13371,9 @@ class App extends _react.Component { this.onEscape = (_, e) => { const { activeSearch, - quickOpenEnabled, closeActiveSearch, - closeQuickOpen + closeQuickOpen, + quickOpenEnabled } = this.props; if (activeSearch) { @@ -13308,7 +13381,8 @@ class App extends _react.Component { closeActiveSearch(); } - if (quickOpenEnabled === true) { + if (quickOpenEnabled) { + e.preventDefault(); closeQuickOpen(); } }; @@ -13749,6 +13823,7 @@ Object.defineProperty(exports, "__esModule", { }); exports.buildQuery = undefined; exports.getMatchIndex = getMatchIndex; +exports.searchSourceForHighlight = searchSourceForHighlight; exports.removeOverlay = removeOverlay; exports.find = find; exports.findNext = findNext; @@ -13909,6 +13984,23 @@ function doSearch(ctx, rev, query, keepSelection, modifiers) { }); } +function searchSourceForHighlight(ctx, rev, query, keepSelection, modifiers, line, ch) { + const { cm } = ctx; + if (!cm) { + return; + } + + return cm.operation(function () { + const state = getSearchState(cm, query); + const isNewQuery = state.query !== query; + state.query = query; + + updateOverlay(cm, state, query, modifiers); + updateCursor(cm, state, keepSelection); + findNextOnLine(ctx, rev, query, isNewQuery, modifiers, line, ch); + }); +} + function getCursorPos(newQuery, rev, state) { if (newQuery) { return rev ? state.posFrom : state.posTo; @@ -13958,6 +14050,28 @@ function searchNext(ctx, rev, query, newQuery, modifiers) { return nextMatch; } +function findNextOnLine(ctx, rev, query, newQuery, modifiers, line, ch) { + const { cm, ed } = ctx; + cm.operation(function () { + const pos = { line: line - 1, ch }; + let cursor = getSearchCursor(cm, query, pos, modifiers); + + if (!cursor.find(rev) && query) { + cursor = getSearchCursor(cm, query, pos, modifiers); + if (!cursor.find(rev)) { + return; + } + } + + // We don't want to jump the editor + // when we're selecting text + if (!cm.state.selectingText) { + ed.alignLine(cursor.from().line, "center"); + cm.setSelection(cursor.from(), cursor.to()); + } + }); +} + /** * Remove overlay. * @@ -14256,6 +14370,7 @@ function willNavigate(event) { await sourceMaps.clearSourceMaps(); (0, _wasm.clearWasmStates)(); (0, _editor.clearDocuments)(); + (0, _editor.removeEditor)(); (0, _parser.clearSymbols)(); (0, _parser.clearASTs)(); (0, _parser.clearScopes)(); @@ -14306,10 +14421,12 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.doSearch = doSearch; +exports.doSearchForHighlight = doSearchForHighlight; exports.setFileSearchQuery = setFileSearchQuery; exports.toggleFileSearchModifier = toggleFileSearchModifier; exports.updateSearchResults = updateSearchResults; exports.searchContents = searchContents; +exports.searchContentsForHighlight = searchContentsForHighlight; exports.traverseResults = traverseResults; exports.closeFileSearch = closeFileSearch; @@ -14337,6 +14454,16 @@ function doSearch(query, editor) { }; } +function doSearchForHighlight(query, editor, line, ch) { + return async ({ getState, dispatch }) => { + const selectedSource = (0, _selectors.getSelectedSource)(getState()); + if (!selectedSource || !selectedSource.text) { + return; + } + dispatch(searchContentsForHighlight(query, editor, line, ch)); + }; +} + function setFileSearchQuery(query) { return { type: "UPDATE_FILE_SEARCH_QUERY", @@ -14386,6 +14513,22 @@ function searchContents(query, editor) { }; } +function searchContentsForHighlight(query, editor, line, ch) { + return async ({ getState, dispatch }) => { + const modifiers = (0, _selectors.getFileSearchModifiers)(getState()); + const selectedSource = (0, _selectors.getSelectedSource)(getState()); + + if (!query || !editor || !selectedSource || !selectedSource.text || !modifiers) { + return; + } + + const ctx = { ed: editor, cm: editor.codeMirror }; + const _modifiers = modifiers.toJS(); + + (0, _editor.searchSourceForHighlight)(ctx, false, query, true, _modifiers, line, ch); + }; +} + function traverseResults(rev, editor) { return async ({ getState, dispatch }) => { if (!editor) { @@ -15036,6 +15179,10 @@ var _svgInlineReact2 = _interopRequireDefault(_svgInlineReact); 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 . */ + const React = __webpack_require__(0); const { isDevelopment } = __webpack_require__(1355); @@ -15085,6 +15232,7 @@ const svg = { stepOut: __webpack_require__(366), stepOver: __webpack_require__(367), subSettings: __webpack_require__(368), + tab: __webpack_require__(3631), toggleBreakpoints: __webpack_require__(369), togglePanes: __webpack_require__(370), typescript: __webpack_require__(2252), @@ -16700,16 +16848,6 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de * file, You can obtain one at . */ // Dependencies -const sourceTypes = { - coffee: "coffeescript", - js: "javascript", - jsx: "react", - ts: "typescript" -}; - -// Actions - - class SourcesTree extends _react.Component { constructor(props) { @@ -16896,6 +17034,8 @@ class SourcesTree extends _react.Component { } } +// Actions + var _initialiseProps = function () { this.focusItem = item => { this.setState({ focusedItem: item }); @@ -16941,13 +17081,9 @@ var _initialiseProps = function () { if (!(0, _sourcesTree.nodeHasChildren)(item)) { const obj = item.contents.get("id"); const source = sources.get(obj); - if (source && source.get("isBlackBoxed")) { - return _react2.default.createElement("img", { className: "blackBox" }); - } - - const sourceType = sourceTypes[(0, _sourcesTree.getExtension)(source)]; - const classNames = (0, _classnames2.default)("source-icon", sourceType || "file"); - return _react2.default.createElement("img", { className: classNames }); + return _react2.default.createElement("img", { + className: (0, _classnames2.default)((0, _source.getSourceClassnames)(source.toJS()), "source-icon") + }); } return _react2.default.createElement("img", { className: "folder" }); @@ -17355,6 +17491,7 @@ class Editor extends _react.PureComponent { } this.setState({ editor }); + (0, _editor.setEditor)(editor); return editor; } @@ -26197,10 +26334,16 @@ exports.formatSymbols = formatSymbols; exports.formatShortcutResults = formatShortcutResults; exports.formatSources = formatSources; +var _classnames = __webpack_require__(175); + +var _classnames2 = _interopRequireDefault(_classnames); + var _utils = __webpack_require__(1366); var _source = __webpack_require__(1356); +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + const MODIFIERS = exports.MODIFIERS = { "@": "functions", "#": "variables", @@ -26237,14 +26380,14 @@ function parseLineColumn(query) { } } -function formatSourcesForList(source) { +function formatSourcesForList(source, tabs) { const title = (0, _source.getFilename)(source); const subtitle = (0, _utils.endTruncateStr)(source.relativeUrl, 100); - return { value: source.relativeUrl, title, subtitle, + icon: tabs.includes(source.url) ? "tab result-item-icon" : (0, _classnames2.default)((0, _source.getSourceClassnames)(source), "result-item-icon"), id: source.id, url: source.url }; @@ -26289,8 +26432,8 @@ function formatShortcutResults() { }]; } -function formatSources(sources) { - return sources.filter(source => !(0, _source.isPretty)(source)).map(source => formatSourcesForList(source)).filter(({ value }) => value != ""); +function formatSources(sources, tabs) { + return sources.filter(source => !(0, _source.isPretty)(source)).map(source => formatSourcesForList(source, tabs)).filter(({ value }) => value != ""); } /***/ }), @@ -26976,8 +27119,9 @@ function paused(pauseInfo) { // Run after fetching scoping data so that it may make use of the sourcemap // expression mappings for local variables. - if (!(0, _selectors.isEvaluatingExpression)(getState())) { - dispatch((0, _expressions.evaluateExpressions)()); + const atException = why.type == "exception"; + if (!atException || !(0, _selectors.isEvaluatingExpression)(getState())) { + await dispatch((0, _expressions.evaluateExpressions)()); } }; } @@ -27011,14 +27155,13 @@ function resumed() { return async ({ dispatch, client, getState }) => { const why = (0, _selectors.getPauseReason)(getState()); const wasPausedInEval = (0, _pause.inDebuggerEval)(why); + const wasStepping = (0, _selectors.isStepping)(getState()); - if (!(0, _selectors.isStepping)(getState()) && !wasPausedInEval) { + dispatch({ type: "RESUME" }); + + if (!wasStepping && !wasPausedInEval) { await dispatch((0, _expressions.evaluateExpressions)()); } - - dispatch({ - type: "RESUME" - }); }; } /* 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 @@ -27706,7 +27849,7 @@ function mapStateToProps(state) { return { enabled: (0, _selectors.getQuickOpenEnabled)(state), - sources: (0, _quickOpen.formatSources)((0, _selectors.getRelativeSources)(state)), + sources: (0, _quickOpen.formatSources)((0, _selectors.getRelativeSources)(state), (0, _selectors.getTabs)(state).toArray()), selectedSource, symbols: (0, _quickOpen.formatSymbols)((0, _selectors.getSymbols)(state, selectedSource)), symbolsLoading: (0, _selectors.isSymbolsLoading)(state, selectedSource), @@ -28505,6 +28648,10 @@ __webpack_require__(1705); 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 . */ + const Badge = ({ children }) => _react2.default.createElement( "div", { className: "badge text-white text-center" }, @@ -30357,6 +30504,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.createLocation = createLocation; +/* 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 . */ + function createLocation({ sourceId, line, @@ -30473,9 +30624,14 @@ function isInvalidTarget(target) { return invalidTarget || invalidToken || invalidType; } -function getExtra(expression, result, selectedFrame) { +function getExtra(expression, result) { return async ({ dispatch, getState, client, sourceMaps }) => { - const extra = await getExtraProps(getState, expression, result, expr => client.evaluateInFrame(selectedFrame.id, expr)); + const selectedFrame = (0, _selectors.getSelectedFrame)(getState()); + if (!selectedFrame) { + return; + } + + const extra = await getExtraProps(getState, expression, result, expr => client.evaluateInFrame(expr, selectedFrame.id)); return extra; }; @@ -30542,24 +30698,24 @@ function setPreview(expression, location, tokenPos, cursorPos) { type: "SET_PREVIEW", [_promise.PROMISE]: async function () { const source = (0, _selectors.getSelectedSource)(getState()); + const sourceId = source.id; + const selectedFrame = (0, _selectors.getSelectedFrame)(getState()); - const sourceId = source.get("id"); if (location && !(0, _devtoolsSourceMap.isGeneratedId)(sourceId)) { expression = await dispatch((0, _expressions.getMappedExpression)(expression)); } - const selectedFrame = (0, _selectors.getSelectedFrame)(getState()); if (!selectedFrame) { return; } - const { result } = await client.evaluateInFrame(selectedFrame.id, expression); + const { result } = await client.evaluateInFrame(expression, selectedFrame.id); if (result === undefined) { return; } - const extra = await dispatch(getExtra(expression, result, selectedFrame)); + const extra = await dispatch(getExtra(expression, result)); return { expression, @@ -30644,7 +30800,9 @@ function renderPause(isWaitingOnBreak) { L10N.getStr("pauseButtonItem") ) ); -} +} /* 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 . */ function renderPauseOnExceptions(shouldPauseOnExceptions, shouldIgnoreCaughtExceptions) { const active = (shouldPauseOnExceptions || shouldIgnoreCaughtExceptions) && (!shouldPauseOnExceptions || !shouldIgnoreCaughtExceptions); @@ -30916,7 +31074,10 @@ Object.defineProperty(exports, "__esModule", { var _lodash = __webpack_require__(2); -let newSources; +let newSources; /* 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 . */ + let createSource; let supportsWasm = false; let queuedSources; @@ -31909,7 +32070,9 @@ 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; }; +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; }; /* 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 . */ exports.updateFrameLocation = updateFrameLocation; exports.mapDisplayNames = mapDisplayNames; @@ -32171,7 +32334,9 @@ function showContextMenu(props) { }]; (0, _devtoolsContextmenu.showMenu)(contextMenuEvent, (0, _devtoolsContextmenu.buildMenu)(items)); -} +} /* 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 . */ /***/ }), @@ -33321,6 +33486,8 @@ var _actions = __webpack_require__(1354); var _actions2 = _interopRequireDefault(_actions); +var _editor = __webpack_require__(1358); + var _projectSearch = __webpack_require__(2010); var _projectTextSearch = __webpack_require__(1424); @@ -33375,6 +33542,7 @@ class ProjectSearch extends _react.Component { this.selectMatchItem = matchItem => { this.props.selectLocation(_extends({}, matchItem)); + this.props.doSearchForHighlight(this.state.inputValue, (0, _editor.getEditor)(), matchItem.line, matchItem.column); }; this.getResults = () => { @@ -34075,7 +34243,9 @@ 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; }; +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; }; /* 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 . */ exports.setupHelper = setupHelper; @@ -34625,7 +34795,9 @@ function locColumn(loc) { } return loc.column; -} +} /* 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 . */ /***/ }), @@ -34639,7 +34811,10 @@ 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; }; +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; }; /* 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 . */ + // eslint-disable-next-line max-len @@ -38661,7 +38836,9 @@ function insertStrtAt(string, index, newString) { const start = string.slice(0, index); const end = string.slice(index); return `${start}${newString}${end}`; -} +} /* 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 . */ function formatPausePoints(text, nodes) { nodes = (0, _lodash.reverse)((0, _lodash.sortBy)(nodes, ["location.line", "location.column"])); @@ -38794,7 +38971,9 @@ 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; }; +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; }; /* 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 . */ exports.getRelativeSources = getRelativeSources; @@ -38850,6 +39029,10 @@ var _selectors = __webpack_require__(3590); var _fetchExtra = __webpack_require__(3629); +/* 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 . */ + function setExtra() { return async function ({ dispatch, getState, sourceMaps }) { const frame = (0, _selectors.getSelectedFrame)(getState()); @@ -38925,11 +39108,7 @@ var _preview = __webpack_require__(1786); function fetchExtra() { return async function ({ dispatch, getState }) { const frame = (0, _selectors.getSelectedFrame)(getState()); - if (!frame) { - return; - } - - const extra = await dispatch((0, _preview.getExtra)("this;", frame.this, frame)); + const extra = await dispatch((0, _preview.getExtra)("this;", frame.this)); dispatch({ type: "ADD_EXTRA", extra: extra @@ -39098,6 +39277,13 @@ exports.default = BreakpointItem; /***/ }), +/***/ 3631: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + /***/ 364: /***/ (function(module, exports) { diff --git a/devtools/client/debugger/new/parser-worker.js b/devtools/client/debugger/new/parser-worker.js index d09d948861e7..50ed802f7f2e 100644 --- a/devtools/client/debugger/new/parser-worker.js +++ b/devtools/client/debugger/new/parser-worker.js @@ -1707,16 +1707,24 @@ function extractSymbol(path, symbols) { } if (t.isVariableDeclarator(path)) { - const node = path.node.id; - const { start, end } = path.node.loc; - if (t.isArrayPattern(node)) { + const nodeId = path.node.id; + + if (t.isArrayPattern(nodeId)) { return; } - symbols.identifiers.push({ - name: node.name, - expression: node.name, - location: { start, end } + const properties = nodeId.properties && t.objectPattern(nodeId.properties) ? nodeId.properties : [{ + value: { name: nodeId.name }, + loc: path.node.loc + }]; + + properties.forEach(function (property) { + const { start, end } = property.loc; + symbols.identifiers.push({ + name: property.value.name, + expression: property.value.name, + location: { start, end } + }); }); } } @@ -21339,7 +21347,9 @@ function replaceNode(ancestors, node) { } else { ancestor.node[ancestor.key] = node; } -} +} /* 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 . */ function getFirstExpression(ast) { const statements = ast.program.body; diff --git a/devtools/client/debugger/new/test/mochitest/browser.ini b/devtools/client/debugger/new/test/mochitest/browser.ini index 85062981c44a..fc192a0ff6a1 100644 --- a/devtools/client/debugger/new/test/mochitest/browser.ini +++ b/devtools/client/debugger/new/test/mochitest/browser.ini @@ -91,6 +91,7 @@ support-files = examples/doc-babel.html examples/doc-content-script-sources.html examples/doc-scripts.html + examples/doc-scripts-debugger.html examples/doc-script-mutate.html examples/doc-script-switching.html examples/doc-exceptions.html diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-expressions-error.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-expressions-error.js index b6ea01fceeb2..5d0ec4e52550 100644 --- a/devtools/client/debugger/new/test/mochitest/browser_dbg-expressions-error.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-expressions-error.js @@ -35,11 +35,11 @@ add_task(async function() { await togglePauseOnExceptions(dbg, true, false); // add a good expression, 2 bad expressions, and another good one + log(`Adding location`); await addExpression(dbg, "location"); await addExpression(dbg, "foo.bar"); await addExpression(dbg, "foo.batt"); await addExpression(dbg, "2"); - // check the value of is(getValue(dbg, 2), "(unavailable)"); is(getValue(dbg, 3), "(unavailable)"); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-expressions.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-expressions.js index 2e64672ba6c6..794d5a8909a8 100644 --- a/devtools/client/debugger/new/test/mochitest/browser_dbg-expressions.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-expressions.js @@ -46,8 +46,9 @@ async function editExpression(dbg, input) { // Position cursor reliably at the end of the text. pressKey(dbg, "End"); type(dbg, input); + const evaluated = waitForDispatch(dbg, "EVALUATE_EXPRESSIONS"); pressKey(dbg, "Enter"); - await waitForDispatch(dbg, "EVALUATE_EXPRESSION"); + await evaluated; } add_task(async function() { diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-navigation.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-navigation.js index 70ef38e763ed..46389a5ae2e2 100644 --- a/devtools/client/debugger/new/test/mochitest/browser_dbg-navigation.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-navigation.js @@ -6,6 +6,14 @@ function countSources(dbg) { return sources.size; } +const sources = [ + "simple1.js", + "simple2.js", + "simple3.js", + "long.js", + "scripts.html" +]; + /** * Test navigating * navigating while paused will reset the pause state and sources @@ -27,21 +35,11 @@ add_task(async function() { assertPausedLocation(dbg); is(countSources(dbg), 5, "5 sources are loaded."); - await navigate(dbg, "about:blank"); - await waitForDispatch(dbg, "NAVIGATE"); - is(countSources(dbg), 0, "0 sources are loaded."); + await navigate(dbg, "doc-scripts.html", ...sources); + is(countSources(dbg), 5, "5 sources are loaded."); ok(!isPaused(getState()), "Is not paused"); - await navigate( - dbg, - "doc-scripts.html", - "simple1.js", - "simple2.js", - "simple3.js", - "long.js", - "scripts.html" - ); - + await navigate(dbg, "doc-scripts.html", ...sources); is(countSources(dbg), 5, "5 sources are loaded."); // Test that the current select source persists across reloads @@ -50,9 +48,7 @@ add_task(async function() { await waitForSelectedSource(dbg, "long.js"); ok( - getSelectedSource(getState()) - .get("url") - .includes("long.js"), + getSelectedSource(getState()).url.includes("long.js"), "Selected source is long.js" ); }); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps-reload.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps-reload.js index c879192c05d2..7166436a6cd8 100644 --- a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps-reload.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps-reload.js @@ -25,11 +25,12 @@ function getBreakpoints(dbg) { add_task(async function() { const dbg = await initDebugger("doc-minified.html"); + dump(`>> meh`) + await navigate(dbg, "sourcemaps-reload/doc-sourcemaps-reload.html", "v1"); - await waitForSource(dbg, "v1"); + dump(`>> select v1`) await selectSource(dbg, "v1"); - await addBreakpoint(dbg, "v1", 6); let breakpoint = getBreakpoints(dbg)[0]; is(breakpoint.location.line, 6); diff --git a/devtools/client/debugger/new/test/mochitest/examples/doc-scripts-debugger.html b/devtools/client/debugger/new/test/mochitest/examples/doc-scripts-debugger.html new file mode 100644 index 000000000000..c38cb932d50c --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/doc-scripts-debugger.html @@ -0,0 +1,20 @@ + + + + + + Debugger test page + + + + + + diff --git a/devtools/client/debugger/new/test/mochitest/head.js b/devtools/client/debugger/new/test/mochitest/head.js index a0f67d9ce12c..9a5272868f2b 100644 --- a/devtools/client/debugger/new/test/mochitest/head.js +++ b/devtools/client/debugger/new/test/mochitest/head.js @@ -252,6 +252,7 @@ function waitForSelectedSource(dbg, url) { return waitForState( dbg, state => { + const source = dbg.selectors.getSelectedSource(state); const isLoaded = source && sourceUtils.isLoaded(source); if (!isLoaded) { @@ -713,7 +714,10 @@ async function reload(dbg, ...sources) { * @static */ async function navigate(dbg, url, ...sources) { + info(`Navigating to ${url}`) + const navigated = waitForDispatch(dbg, "NAVIGATE"); await dbg.client.navigate(url); + await navigated; return waitForSources(dbg, ...sources); } @@ -941,6 +945,7 @@ const selectors = { `.expressions-list .expression-container:nth-child(${i}) .object-delimiter + *`, expressionClose: i => `.expressions-list .expression-container:nth-child(${i}) .close`, + expressionInput: '.expressions-list input.input-expression', expressionNodes: ".expressions-list .tree-node", scopesHeader: ".scopes-pane ._header", breakpointItem: i => `.breakpoints-list .breakpoint:nth-of-type(${i})`, @@ -1103,8 +1108,11 @@ function getScopeValue(dbg, index) { } function toggleObjectInspectorNode(node) { + const objectInspector = node.closest(".object-inspector"); const properties = objectInspector.querySelectorAll(".node").length; + + log(`Toggling node ${node.innerText}`) node.click(); return waitUntil( () => objectInspector.querySelectorAll(".node").length !== properties diff --git a/devtools/client/jar.mn b/devtools/client/jar.mn index 3cc142d2d268..bdf6491ce900 100644 --- a/devtools/client/jar.mn +++ b/devtools/client/jar.mn @@ -284,6 +284,7 @@ devtools.jar: skin/images/debugger/stepIn.svg (themes/images/debugger/stepIn.svg) skin/images/debugger/stepOut.svg (themes/images/debugger/stepOut.svg) skin/images/debugger/stepOver.svg (themes/images/debugger/stepOver.svg) + skin/images/debugger/tab.svg (themes/images/debugger/tab.svg) skin/images/debugger/typescript.svg (themes/images/debugger/typescript.svg) # Netmonitor diff --git a/devtools/client/themes/images/debugger/tab.svg b/devtools/client/themes/images/debugger/tab.svg new file mode 100644 index 000000000000..b4c44e431efb --- /dev/null +++ b/devtools/client/themes/images/debugger/tab.svg @@ -0,0 +1,6 @@ + + + +