зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1500998 - Update debugger frontend v94 r=jdescottes
This commit is contained in:
Родитель
44a3847f77
Коммит
b9e4308d69
|
@ -1,9 +1,9 @@
|
|||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Version 92
|
||||
Version 94
|
||||
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-91...release-92
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-93...release-94
|
||||
|
||||
Packages:
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.2
|
||||
|
|
|
@ -1364,7 +1364,8 @@ html .toggle-button.end.vertical svg {
|
|||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
.search-shadow {
|
||||
border: 1px solid transparent;
|
||||
border: 1px solid var(--theme-toolbar-background);
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
}
|
||||
|
||||
.search-shadow.focused {
|
||||
|
@ -1595,6 +1596,8 @@ html .toggle-button.end.vertical svg {
|
|||
display: flex;
|
||||
align-self: stretch;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.project-text-search .search-field .close-btn.big {
|
||||
|
@ -2000,6 +2003,30 @@ menuseparator {
|
|||
height: 100%;
|
||||
z-index: 999;
|
||||
}
|
||||
.outline-filter {
|
||||
margin: 5px 0 0 0;
|
||||
padding: 0px 10px;
|
||||
}
|
||||
|
||||
.outline-filter-input {
|
||||
padding: 0.5em 1.6em;
|
||||
width: 100%;
|
||||
border: 1px solid var(--theme-splitter-color);
|
||||
background-color: var(--theme-sidebar-background);
|
||||
color: var(--theme-body-color);
|
||||
font-size: 12px;
|
||||
-moz-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.outline-filter-input.focused {
|
||||
border: 1px solid var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.outline-filter-input::placeholder {
|
||||
font-style: italic;
|
||||
color: var(--theme-comment);
|
||||
}
|
||||
/* 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/>. */
|
||||
|
@ -2014,32 +2041,32 @@ menuseparator {
|
|||
}
|
||||
|
||||
.outline-pane-info {
|
||||
padding: 0.5em;
|
||||
width: 100%;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
padding: 0.5em;
|
||||
user-select: none;
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.outline-list {
|
||||
list-style-type: none;
|
||||
padding: 4px 0;
|
||||
margin: 0;
|
||||
padding: 0 0 4px 0;
|
||||
position: absolute;
|
||||
top: 38px;
|
||||
bottom: 25px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
list-style-type: none;
|
||||
font-family: var(--monospace-font-family);
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 25px;
|
||||
}
|
||||
|
||||
.outline-list__class-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.outline-list__class-list .function-signature .function-name {
|
||||
|
@ -2051,9 +2078,9 @@ menuseparator {
|
|||
}
|
||||
|
||||
.outline-list h2 {
|
||||
margin: 10px 0 10px 10px;
|
||||
font-weight: normal;
|
||||
font-size: 1em;
|
||||
margin: 10px 0 10px 10px;
|
||||
color: var(--blue-55);
|
||||
}
|
||||
|
||||
|
@ -2085,19 +2112,19 @@ menuseparator {
|
|||
}
|
||||
|
||||
.outline-footer {
|
||||
background: var(--theme-body-background);
|
||||
border-top: 1px solid var(--theme-splitter-color);
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 25px;
|
||||
background: var(--theme-body-background);
|
||||
border-top: 1px solid var(--theme-splitter-color);
|
||||
opacity: 1;
|
||||
z-index: 1;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
height: 25px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.theme-dark .outline-footer button {
|
||||
|
@ -2298,6 +2325,7 @@ menuseparator {
|
|||
|
||||
.search-bar .search-shadow {
|
||||
flex-grow: 1;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.search-bar .search-shadow.focused {
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -27,26 +27,30 @@ var _selectors = require("../selectors/index");
|
|||
*/
|
||||
function updateTab(source, framework) {
|
||||
const {
|
||||
url
|
||||
url,
|
||||
id: sourceId
|
||||
} = source;
|
||||
const isOriginal = (0, _devtoolsSourceMap.isOriginalId)(source.id);
|
||||
return {
|
||||
type: "UPDATE_TAB",
|
||||
url,
|
||||
framework,
|
||||
isOriginal
|
||||
isOriginal,
|
||||
sourceId
|
||||
};
|
||||
}
|
||||
|
||||
function addTab(source) {
|
||||
const {
|
||||
url
|
||||
url,
|
||||
id: sourceId
|
||||
} = source;
|
||||
const isOriginal = (0, _devtoolsSourceMap.isOriginalId)(source.id);
|
||||
return {
|
||||
type: "ADD_TAB",
|
||||
url,
|
||||
isOriginal
|
||||
isOriginal,
|
||||
sourceId
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ function getMenuItems(event, {
|
|||
id: "node-menu-copy-source-url",
|
||||
label: copySourceUri2Label,
|
||||
accesskey: copySourceUri2Key,
|
||||
disabled: false,
|
||||
disabled: !selectedSource.url,
|
||||
click: () => (0, _clipboard.copyToTheClipboard)((0, _source.getRawSourceURL)(selectedSource.url))
|
||||
};
|
||||
const sourceId = selectedSource.id;
|
||||
|
@ -139,14 +139,14 @@ function getMenuItems(event, {
|
|||
id: "node-menu-show-source",
|
||||
label: revealInTreeLabel,
|
||||
accesskey: revealInTreeKey,
|
||||
disabled: false,
|
||||
disabled: !selectedSource.url,
|
||||
click: () => showSource(sourceId)
|
||||
};
|
||||
const blackBoxMenuItem = {
|
||||
id: "node-menu-blackbox",
|
||||
label: toggleBlackBoxLabel,
|
||||
accesskey: blackboxKey,
|
||||
disabled: isOriginal || isPrettyPrinted || hasSourceMap,
|
||||
disabled: isOriginal || isPrettyPrinted || hasSourceMap || !selectedSource.url,
|
||||
click: () => toggleBlackBox(selectedSource)
|
||||
};
|
||||
const watchExpressionItem = {
|
||||
|
|
|
@ -101,14 +101,15 @@ class Tab extends _react.PureComponent {
|
|||
}
|
||||
}, {
|
||||
item: { ...tabMenuItems.copySourceUri2,
|
||||
disabled: !selectedSource.url,
|
||||
click: () => (0, _clipboard.copyToTheClipboard)((0, _source.getRawSourceURL)(sourceTab.url))
|
||||
}
|
||||
}];
|
||||
items.push({
|
||||
}, {
|
||||
item: { ...tabMenuItems.showSource,
|
||||
disabled: !selectedSource.url,
|
||||
click: () => showSource(tab)
|
||||
}
|
||||
});
|
||||
}];
|
||||
|
||||
if (!isPrettySource) {
|
||||
items.push({
|
||||
|
|
|
@ -13,6 +13,8 @@ var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").
|
|||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _fuzzaldrinPlus = require("devtools/client/debugger/new/dist/vendors").vendored["fuzzaldrin-plus"];
|
||||
|
||||
var _clipboard = require("../../utils/clipboard");
|
||||
|
||||
var _function = require("../../utils/function");
|
||||
|
@ -23,6 +25,10 @@ var _actions2 = _interopRequireDefault(_actions);
|
|||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _OutlineFilter = require("./OutlineFilter");
|
||||
|
||||
var _OutlineFilter2 = _interopRequireDefault(_OutlineFilter);
|
||||
|
||||
var _PreviewFunction = require("../shared/PreviewFunction");
|
||||
|
||||
var _PreviewFunction2 = _interopRequireDefault(_PreviewFunction);
|
||||
|
@ -34,7 +40,35 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|||
/* 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/>. */
|
||||
|
||||
/**
|
||||
* Check whether the name argument matches the fuzzy filter argument
|
||||
*/
|
||||
const filterOutlineItem = (name, filter) => {
|
||||
// Set higher to make the fuzzaldrin filter more specific
|
||||
const FUZZALDRIN_FILTER_THRESHOLD = 15000;
|
||||
|
||||
if (!filter) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (filter.length === 1) {
|
||||
// when filter is a single char just check if it starts with the char
|
||||
return filter.toLowerCase() === name.toLowerCase()[0];
|
||||
}
|
||||
|
||||
return (0, _fuzzaldrinPlus.score)(name, filter) > FUZZALDRIN_FILTER_THRESHOLD;
|
||||
};
|
||||
|
||||
class Outline extends _react.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.updateFilter = this.updateFilter.bind(this);
|
||||
this.state = {
|
||||
filter: ""
|
||||
};
|
||||
}
|
||||
|
||||
selectItem(location) {
|
||||
const {
|
||||
selectedSource,
|
||||
|
@ -89,6 +123,12 @@ class Outline extends _react.Component {
|
|||
(0, _devtoolsContextmenu.showMenu)(event, menuOptions);
|
||||
}
|
||||
|
||||
updateFilter(filter) {
|
||||
this.setState({
|
||||
filter: filter.trim()
|
||||
});
|
||||
}
|
||||
|
||||
renderPlaceholder() {
|
||||
const placeholderMessage = this.props.selectedSource ? L10N.getStr("outline.noFunctions") : L10N.getStr("outline.noFileSelected");
|
||||
return _react2.default.createElement("div", {
|
||||
|
@ -145,9 +185,12 @@ class Outline extends _react.Component {
|
|||
}
|
||||
|
||||
renderFunctions(functions) {
|
||||
const {
|
||||
filter
|
||||
} = this.state;
|
||||
let classes = (0, _lodash.uniq)(functions.map(func => func.klass));
|
||||
let namedFunctions = functions.filter(func => func.name != "anonymous" && !func.klass && !classes.includes(func.name));
|
||||
let classFunctions = functions.filter(func => func.name != "anonymous" && !!func.klass);
|
||||
let namedFunctions = functions.filter(func => filterOutlineItem(func.name, filter) && !func.klass && !classes.includes(func.name));
|
||||
let classFunctions = functions.filter(func => filterOutlineItem(func.name, filter) && !!func.klass);
|
||||
|
||||
if (this.props.alphabetizeOutline) {
|
||||
namedFunctions = (0, _lodash.sortBy)(namedFunctions, "name");
|
||||
|
@ -155,16 +198,18 @@ class Outline extends _react.Component {
|
|||
classFunctions = (0, _lodash.sortBy)(classFunctions, "name");
|
||||
}
|
||||
|
||||
return _react2.default.createElement("div", null, _react2.default.createElement("ul", {
|
||||
return _react2.default.createElement("ul", {
|
||||
className: "outline-list"
|
||||
}, namedFunctions.map(func => this.renderFunction(func)), classes.map(klass => this.renderClassFunctions(klass, classFunctions))), _react2.default.createElement("div", {
|
||||
}, namedFunctions.map(func => this.renderFunction(func)), classes.map(klass => this.renderClassFunctions(klass, classFunctions)));
|
||||
}
|
||||
|
||||
renderFooter() {
|
||||
return _react2.default.createElement("div", {
|
||||
className: "outline-footer bottom"
|
||||
}, _react2.default.createElement("button", {
|
||||
onClick: () => {
|
||||
this.props.onAlphabetizeClick();
|
||||
},
|
||||
onClick: this.props.onAlphabetizeClick,
|
||||
className: this.props.alphabetizeOutline ? "active" : ""
|
||||
}, L10N.getStr("outline.sortLabel"))));
|
||||
}, L10N.getStr("outline.sortLabel")));
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -172,6 +217,9 @@ class Outline extends _react.Component {
|
|||
symbols,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
const {
|
||||
filter
|
||||
} = this.state;
|
||||
|
||||
if (!selectedSource) {
|
||||
return this.renderPlaceholder();
|
||||
|
@ -182,9 +230,17 @@ class Outline extends _react.Component {
|
|||
}
|
||||
|
||||
const symbolsToDisplay = symbols.functions.filter(func => func.name != "anonymous");
|
||||
|
||||
if (symbolsToDisplay.length === 0) {
|
||||
return this.renderPlaceholder();
|
||||
}
|
||||
|
||||
return _react2.default.createElement("div", {
|
||||
className: "outline"
|
||||
}, symbolsToDisplay.length > 0 ? this.renderFunctions(symbols.functions) : this.renderPlaceholder());
|
||||
}, _react2.default.createElement("div", null, _react2.default.createElement(_OutlineFilter2.default, {
|
||||
filter: filter,
|
||||
updateFilter: this.updateFilter
|
||||
}), this.renderFunctions(symbolsToDisplay), this.renderFooter()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
|
||||
|
||||
var _classnames2 = _interopRequireDefault(_classnames);
|
||||
|
||||
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 OutlineFilter extends _react.Component {
|
||||
constructor(...args) {
|
||||
var _temp;
|
||||
|
||||
return _temp = super(...args), this.state = {
|
||||
focused: false
|
||||
}, this.setFocus = shouldFocus => {
|
||||
this.setState({
|
||||
focused: shouldFocus
|
||||
});
|
||||
}, this.onChange = e => {
|
||||
this.props.updateFilter(e.target.value);
|
||||
}, this.onKeyDown = e => {
|
||||
if (e.key === "Escape" && this.props.filter !== "") {
|
||||
// use preventDefault to override toggling the split-console which is
|
||||
// also bound to the ESC key
|
||||
e.preventDefault();
|
||||
this.props.updateFilter("");
|
||||
}
|
||||
}, _temp;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
focused
|
||||
} = this.state;
|
||||
return _react2.default.createElement("div", {
|
||||
className: "outline-filter"
|
||||
}, _react2.default.createElement("form", null, _react2.default.createElement("input", {
|
||||
className: (0, _classnames2.default)("outline-filter-input", {
|
||||
focused
|
||||
}),
|
||||
onFocus: () => this.setFocus(true),
|
||||
onBlur: () => this.setFocus(false),
|
||||
placeholder: L10N.getStr("outline.placeholder"),
|
||||
value: this.props.filter,
|
||||
type: "text",
|
||||
onChange: this.onChange,
|
||||
onKeyDown: this.onKeyDown
|
||||
})));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.default = OutlineFilter;
|
|
@ -116,7 +116,8 @@ class SourcesTree extends _react.Component {
|
|||
debuggeeUrl,
|
||||
projectRoot,
|
||||
uncollapsedTree,
|
||||
sourceTree
|
||||
sourceTree,
|
||||
focusedItem: this.state.focusedItem
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ DIRS += [
|
|||
DevToolsModules(
|
||||
'index.js',
|
||||
'Outline.js',
|
||||
'OutlineFilter.js',
|
||||
'SourcesTree.js',
|
||||
'SourcesTreeItem.js',
|
||||
)
|
||||
|
|
|
@ -1,24 +1,35 @@
|
|||
"use strict";
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _reactDom = require("devtools/client/shared/vendor/react-dom");
|
||||
|
||||
var _reactDom2 = _interopRequireDefault(_reactDom);
|
||||
|
||||
var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"];
|
||||
|
||||
var _client = require("./client/index");
|
||||
|
||||
var _bootstrap = require("./utils/bootstrap");
|
||||
|
||||
var _sourceQueue = require("./utils/source-queue");
|
||||
|
||||
var _sourceQueue2 = _interopRequireDefault(_sourceQueue);
|
||||
|
||||
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/>. */
|
||||
|
||||
// @flow
|
||||
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
import { isFirefoxPanel } from "devtools-environment";
|
||||
|
||||
import { onConnect } from "./client";
|
||||
import { teardownWorkers } from "./utils/bootstrap";
|
||||
import sourceQueue from "./utils/source-queue";
|
||||
|
||||
function unmountRoot() {
|
||||
const mount = document.querySelector("#mount .launchpad-root");
|
||||
ReactDOM.unmountComponentAtNode(mount);
|
||||
|
||||
_reactDom2.default.unmountComponentAtNode(mount);
|
||||
}
|
||||
|
||||
if (isFirefoxPanel()) {
|
||||
if ((0, _devtoolsEnvironment.isFirefoxPanel)()) {
|
||||
module.exports = {
|
||||
bootstrap: ({
|
||||
threadClient,
|
||||
|
@ -26,38 +37,45 @@ if (isFirefoxPanel()) {
|
|||
debuggerClient,
|
||||
sourceMaps,
|
||||
toolboxActions
|
||||
}: any) => {
|
||||
return onConnect(
|
||||
{
|
||||
tab: { clientType: "firefox" },
|
||||
}) => {
|
||||
return (0, _client.onConnect)({
|
||||
tab: {
|
||||
clientType: "firefox"
|
||||
},
|
||||
tabConnection: {
|
||||
tabTarget,
|
||||
threadClient,
|
||||
debuggerClient
|
||||
}
|
||||
}, {
|
||||
services: {
|
||||
sourceMaps
|
||||
},
|
||||
{
|
||||
services: { sourceMaps },
|
||||
toolboxActions
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
destroy: () => {
|
||||
unmountRoot();
|
||||
sourceQueue.clear();
|
||||
teardownWorkers();
|
||||
|
||||
_sourceQueue2.default.clear();
|
||||
|
||||
(0, _bootstrap.teardownWorkers)();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
const { bootstrap, L10N } = require("devtools-launchpad");
|
||||
const {
|
||||
bootstrap,
|
||||
L10N
|
||||
} = require("devtools/shared/flags");
|
||||
|
||||
window.L10N = L10N;
|
||||
// $FlowIgnore:
|
||||
window.L10N.setBundle(require("../assets/panel/debugger.properties"));
|
||||
window.L10N = L10N; // $FlowIgnore:
|
||||
|
||||
bootstrap(React, ReactDOM).then(connection => {
|
||||
onConnect(connection, {
|
||||
services: { sourceMaps: require("devtools-source-map") },
|
||||
window.L10N.setBundle(require("devtools/shared/flags"));
|
||||
bootstrap(_react2.default, _reactDom2.default).then(connection => {
|
||||
(0, _client.onConnect)(connection, {
|
||||
services: {
|
||||
sourceMaps: require("devtools/client/shared/source-map/index.js")
|
||||
},
|
||||
toolboxActions: {}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -98,7 +98,11 @@ function update(state = initialSourcesState(), action) {
|
|||
location = { ...action.location,
|
||||
url: action.source.url
|
||||
};
|
||||
|
||||
if (action.source.url) {
|
||||
_prefs.prefs.pendingSelectedLocation = location;
|
||||
}
|
||||
|
||||
return { ...state,
|
||||
selectedLocation: {
|
||||
sourceId: action.source.id,
|
||||
|
|
|
@ -70,24 +70,37 @@ function removeSourcesFromTabList(tabs, sources) {
|
|||
function updateTabList(tabs, {
|
||||
url,
|
||||
framework = null,
|
||||
sourceId,
|
||||
isOriginal = false
|
||||
}) {
|
||||
const currentIndex = tabs.findIndex(tab => isSimilarTab(tab, url, isOriginal));
|
||||
// Set currentIndex to -1 for URL-less tabs so that they aren't
|
||||
// filtered by isSimilarTab
|
||||
const currentIndex = url ? tabs.findIndex(tab => isSimilarTab(tab, url, isOriginal)) : -1;
|
||||
|
||||
if (currentIndex === -1) {
|
||||
tabs = [{
|
||||
url,
|
||||
framework,
|
||||
sourceId,
|
||||
isOriginal
|
||||
}, ...tabs];
|
||||
} else if (framework) {
|
||||
tabs[currentIndex].framework = framework;
|
||||
}
|
||||
|
||||
_prefs.asyncStore.tabs = tabs;
|
||||
_prefs.asyncStore.tabs = persistTabs(tabs);
|
||||
return tabs;
|
||||
}
|
||||
|
||||
function persistTabs(tabs) {
|
||||
return tabs.filter(tab => tab.url).map(tab => {
|
||||
const newTab = { ...tab
|
||||
};
|
||||
delete newTab.sourceId;
|
||||
return newTab;
|
||||
});
|
||||
}
|
||||
|
||||
function moveTabInList(tabs, {
|
||||
url,
|
||||
tabIndex: newIndex
|
||||
|
@ -166,8 +179,15 @@ function getNewSelectedSourceId(state, availableTabs) {
|
|||
|
||||
const getTabs = exports.getTabs = state => state.tabs;
|
||||
|
||||
const getSourceTabs = exports.getSourceTabs = (0, _reselect.createSelector)(getTabs, _sources.getSources, _sources.getUrls, (tabs, sources, urls) => tabs.filter(tab => (0, _sources.getSpecificSourceByUrlInSources)(sources, urls, tab.url, tab.isOriginal)));
|
||||
const getSourcesForTabs = exports.getSourcesForTabs = (0, _reselect.createSelector)(getSourceTabs, _sources.getSources, _sources.getUrls, (tabs, sources, urls) => {
|
||||
return tabs.map(tab => (0, _sources.getSpecificSourceByUrlInSources)(sources, urls, tab.url, tab.isOriginal)).filter(Boolean);
|
||||
});
|
||||
const getSourceTabs = exports.getSourceTabs = (0, _reselect.createSelector)(getTabs, _sources.getSources, _sources.getUrls, (tabs, sources, urls) => tabs.filter(tab => getTabWithOrWithoutUrl(tab, sources, urls)));
|
||||
const getSourcesForTabs = exports.getSourcesForTabs = (0, _reselect.createSelector)(getSourceTabs, _sources.getSources, _sources.getUrls, (tabs, sources, urls) => tabs.map(tab => getTabWithOrWithoutUrl(tab, sources, urls)).filter(Boolean));
|
||||
|
||||
function getTabWithOrWithoutUrl(tab, sources, urls) {
|
||||
if (tab.url) {
|
||||
return (0, _sources.getSpecificSourceByUrlInSources)(sources, urls, tab.url, tab.isOriginal);
|
||||
}
|
||||
|
||||
return tab.sourceId ? sources[tab.sourceId] : null;
|
||||
}
|
||||
|
||||
exports.default = update;
|
|
@ -21,7 +21,7 @@ const libraryMap = [{
|
|||
pattern: /preact/i
|
||||
}, {
|
||||
label: "React",
|
||||
pattern: /react/i
|
||||
pattern: /(node_modules\/react)|(react(\.[a-z]+)*\.js$)/i
|
||||
}, {
|
||||
label: "Immutable",
|
||||
pattern: /immutable/i
|
||||
|
|
|
@ -170,7 +170,7 @@ function getFilename(source) {
|
|||
id
|
||||
} = source;
|
||||
|
||||
if (!url) {
|
||||
if (!getRawSourceURL(url)) {
|
||||
return getFormattedSourceId(id);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,13 +24,32 @@ function newSourcesSet(newSources, prevSources) {
|
|||
return uniqSources;
|
||||
}
|
||||
|
||||
function findFocusedItemInTree(newSourceTree, focusedItem, debuggeeHost) {
|
||||
const parts = focusedItem.path.split("/").filter(p => p !== "");
|
||||
let path = "";
|
||||
return parts.reduce((subTree, part, index) => {
|
||||
if (subTree === undefined || subTree === null) {
|
||||
return null;
|
||||
} else if ((0, _utils.isSource)(subTree)) {
|
||||
return subTree;
|
||||
}
|
||||
|
||||
path = path ? `${path}/${part}` : part;
|
||||
const {
|
||||
index: childIndex
|
||||
} = (0, _treeOrder.findNodeInContents)(subTree, (0, _treeOrder.createTreeNodeMatcher)(part, !(0, _utils.partIsFile)(index, parts, focusedItem), debuggeeHost));
|
||||
return subTree.contents[childIndex];
|
||||
}, newSourceTree);
|
||||
}
|
||||
|
||||
function updateTree({
|
||||
newSources,
|
||||
prevSources,
|
||||
debuggeeUrl,
|
||||
projectRoot,
|
||||
uncollapsedTree,
|
||||
sourceTree
|
||||
sourceTree,
|
||||
focusedItem
|
||||
}) {
|
||||
const newSet = newSourcesSet(newSources, prevSources);
|
||||
const debuggeeHost = (0, _treeOrder.getDomain)(debuggeeUrl);
|
||||
|
@ -40,10 +59,15 @@ function updateTree({
|
|||
}
|
||||
|
||||
const newSourceTree = (0, _collapseTree.collapseTree)(uncollapsedTree);
|
||||
|
||||
if (focusedItem) {
|
||||
focusedItem = findFocusedItemInTree(newSourceTree, focusedItem, debuggeeHost);
|
||||
}
|
||||
|
||||
return {
|
||||
uncollapsedTree,
|
||||
sourceTree: newSourceTree,
|
||||
parentMap: (0, _utils.createParentMap)(newSourceTree),
|
||||
focusedItem: null
|
||||
focusedItem
|
||||
};
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that the editor highlights the correct location when the
|
||||
// debugger pauses
|
||||
|
||||
function getItems(dbg) {
|
||||
return findAllElements(dbg, "outlineItems");
|
||||
}
|
||||
|
@ -12,6 +9,8 @@ function getNthItem(dbg, index) {
|
|||
return findElement(dbg, "outlineItem", index);
|
||||
}
|
||||
|
||||
// Tests that the editor highlights the correct location when the
|
||||
// debugger pauses
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-scripts.html");
|
||||
const {
|
||||
|
@ -59,3 +58,71 @@ add_task(async function() {
|
|||
"Alphabetized first function is correct"
|
||||
);
|
||||
});
|
||||
|
||||
// Tests the outline pane fuzzy filtering of outline items
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-scripts.html");
|
||||
await selectSource(dbg, "long", 1);
|
||||
findElementWithSelector(dbg, ".outline-tab").click();
|
||||
|
||||
// turn off alphetical sort if active
|
||||
const alphabetizeButton = findElementWithSelector(
|
||||
dbg,
|
||||
".outline-footer button"
|
||||
);
|
||||
if (alphabetizeButton.className === "active") {
|
||||
alphabetizeButton.click();
|
||||
}
|
||||
|
||||
const outlineFilter = findElementWithSelector(dbg, ".outline-filter-input");
|
||||
ok(outlineFilter, "Outline filter is present");
|
||||
|
||||
outlineFilter.blur();
|
||||
ok(
|
||||
!findElementWithSelector(dbg, ".outline-filter-input.focused"),
|
||||
"does not have class focused when not focused"
|
||||
);
|
||||
|
||||
outlineFilter.focus();
|
||||
ok(
|
||||
findElementWithSelector(dbg, ".outline-filter-input.focused"),
|
||||
"has class focused when focused"
|
||||
);
|
||||
|
||||
is(getItems(dbg).length, 9, "9 items in the unfiltered list");
|
||||
|
||||
// filter all items starting with t
|
||||
type(dbg, "t");
|
||||
is(getItems(dbg).length, 4, "4 items in the list after 't' filter");
|
||||
ok(getItems(dbg)[0].textContent.includes("TodoModel(key)"), "item TodoModel");
|
||||
ok(
|
||||
getItems(dbg)[1].textContent.includes("toggleAll(checked)"),
|
||||
"item toggleAll"
|
||||
);
|
||||
ok(
|
||||
getItems(dbg)[2].textContent.includes("toggle(todoToToggle)"),
|
||||
"item toggle"
|
||||
);
|
||||
ok(getItems(dbg)[3].textContent.includes("testModel()"), "item testModel");
|
||||
|
||||
// filter using term 'tog'
|
||||
type(dbg, "og");
|
||||
is(getItems(dbg).length, 2, "2 items in the list after 'tog' filter");
|
||||
ok(
|
||||
getItems(dbg)[0].textContent.includes("toggleAll(checked)"),
|
||||
"item toggleAll"
|
||||
);
|
||||
ok(
|
||||
getItems(dbg)[1].textContent.includes("toggle(todoToToggle)"),
|
||||
"item toggle"
|
||||
);
|
||||
|
||||
pressKey(dbg, "Escape");
|
||||
is(getItems(dbg).length, 9, "9 items in the list after escape pressed");
|
||||
|
||||
// check that the term 'todo' includes items with todo
|
||||
type(dbg, "todo");
|
||||
is(getItems(dbg).length, 2, "2 items in the list after 'todo' filter");
|
||||
ok(getItems(dbg)[0].textContent.includes("TodoModel(key)"), "item TodoModel");
|
||||
ok(getItems(dbg)[1].textContent.includes("addTodo(title)"), "item addTodo");
|
||||
});
|
||||
|
|
|
@ -2,25 +2,6 @@
|
|||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test keyboard arrow behaviour
|
||||
|
||||
async function waitForNodeToGainFocus(dbg, index) {
|
||||
await waitUntil(() => {
|
||||
const element = findElement(dbg, "sourceNode", index);
|
||||
|
||||
if (element) {
|
||||
return element.classList.contains("focused");
|
||||
}
|
||||
|
||||
return false;
|
||||
}, `waiting for source node ${index} to be focused`);
|
||||
}
|
||||
|
||||
async function assertNodeIsFocused(dbg, index) {
|
||||
await waitForNodeToGainFocus(dbg, index);
|
||||
const node = findElement(dbg, "sourceNode", index);
|
||||
ok(node.classList.contains("focused"), `node ${index} is focused`);
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-sources.html");
|
||||
await waitForSources(dbg, "simple1", "simple2", "nested-source", "long.js");
|
||||
|
|
|
@ -40,7 +40,7 @@ add_task(async function() {
|
|||
|
||||
ok(fourthNode.classList.contains("focused"), "4th node is focused");
|
||||
ok(selectedSource.includes("nested-source.js"), "nested-source is selected");
|
||||
|
||||
await assertNodeIsFocused(dbg, 4);
|
||||
await waitForSelectedSource(dbg, "nested-source");
|
||||
|
||||
// Make sure new sources appear in the list.
|
||||
|
@ -51,6 +51,7 @@ add_task(async function() {
|
|||
});
|
||||
|
||||
await waitForSourceCount(dbg, 9);
|
||||
await assertNodeIsFocused(dbg, 4);
|
||||
is(
|
||||
getLabel(dbg, 7),
|
||||
"math.min.js",
|
||||
|
|
|
@ -37,3 +37,28 @@ add_task(async function() {
|
|||
await reload(dbg, "simple1", "simple2");
|
||||
is(countTabs(dbg), 0);
|
||||
});
|
||||
|
||||
// Test that URL-less sources have tabs added to the UI but
|
||||
// do not persist upon reload
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-scripts.html", "simple1", "simple2");
|
||||
|
||||
await selectSource(dbg, "simple1");
|
||||
await selectSource(dbg, "simple2");
|
||||
|
||||
is(countTabs(dbg), 2);
|
||||
|
||||
invokeInTab("doEval");
|
||||
await waitForPaused(dbg);
|
||||
await resume(dbg);
|
||||
is(countTabs(dbg), 3);
|
||||
|
||||
invokeInTab("doEval");
|
||||
await waitForPaused(dbg);
|
||||
await resume(dbg);
|
||||
is(countTabs(dbg), 4);
|
||||
|
||||
// Test reloading the debugger
|
||||
await reload(dbg, "simple1", "simple2");
|
||||
is(countTabs(dbg), 2);
|
||||
});
|
||||
|
|
|
@ -1340,3 +1340,21 @@ async function assertSourceCount(dbg, count) {
|
|||
await waitForSourceCount(dbg, count);
|
||||
is(findAllElements(dbg, "sourceNodes").length, count, `${count} sources`);
|
||||
}
|
||||
|
||||
async function waitForNodeToGainFocus(dbg, index) {
|
||||
await waitUntil(() => {
|
||||
const element = findElement(dbg, "sourceNode", index);
|
||||
|
||||
if (element) {
|
||||
return element.classList.contains("focused");
|
||||
}
|
||||
|
||||
return false;
|
||||
}, `waiting for source node ${index} to be focused`);
|
||||
}
|
||||
|
||||
async function assertNodeIsFocused(dbg, index) {
|
||||
await waitForNodeToGainFocus(dbg, index);
|
||||
const node = findElement(dbg, "sourceNode", index);
|
||||
ok(node.classList.contains("focused"), `node ${index} is focused`);
|
||||
}
|
||||
|
|
|
@ -606,6 +606,10 @@ sources.header=Sources
|
|||
# LOCALIZATION NOTE (outline.header): Outline left sidebar header
|
||||
outline.header=Outline
|
||||
|
||||
# LOCALIZATION NOTE (outline.placeholder): Placeholder text for the filter input
|
||||
# element
|
||||
outline.placeholder=Filter functions
|
||||
|
||||
# LOCALIZATION NOTE (outline.sortLabel): Label for the sort button
|
||||
outline.sortLabel=Sort by name
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче