Bug 1464486 - Update Debugger Frontend v59. r=dwalsh

This commit is contained in:
Jason Laster 2018-05-25 13:52:20 -04:00
Родитель 7d46f4bb8c
Коммит 15e1d86b8e
38 изменённых файлов: 1130 добавлений и 161 удалений

Просмотреть файл

@ -1,13 +1,13 @@
This is the debugger.html project output.
See https://github.com/devtools-html/debugger.html
Version 58
Version 59
Comparison: https://github.com/devtools-html/debugger.html/compare/release-57...release-58
Comparison: https://github.com/devtools-html/debugger.html/compare/release-58...release-59
Packages:
- babel-plugin-transform-es2015-modules-commonjs @6.26.2
- babel-preset-react @6.24.1
- react @16.2.0
- react-dom @16.2.0
- webpack @3.12.0
- webpack @3.11.0

Просмотреть файл

@ -1108,7 +1108,10 @@ html .toggle-button.end.vertical svg {
.search-field i.magnifying-glass,
.search-field i.sad-face {
padding: 6px;
padding-top: 5px;
padding-bottom: 5px;
padding-inline-end: 10px;
padding-inline-start: 5px;
width: 24px;
}
@ -1118,6 +1121,11 @@ html .toggle-button.end.vertical svg {
width: 40px;
}
.search-field.big i.sad-face {
padding-top: 4px;
padding-inline-start: 4px;
}
.search-field .magnifying-glass path,
.search-field .magnifying-glass ellipse {
stroke: var(--theme-comment);
@ -1134,18 +1142,13 @@ html .toggle-button.end.vertical svg {
.search-field .summary {
line-height: 27px;
text-align: center;
padding-right: 10px;
padding-inline-end: 10px;
color: var(--theme-body-color-inactive);
align-self: center;
padding-top: 1px;
white-space: nowrap;
}
.search-field.big .summary {
padding: 5px 0 5px 0;
line-height: 2rem;
}
.search-field .search-nav-buttons {
display: flex;
user-select: none;
@ -1261,7 +1264,7 @@ html .toggle-button.end.vertical svg {
}
.project-text-search .search-field .close-btn.big {
margin-top: 6px;
margin-top: 2px;
}
.project-text-search .managed-tree {
@ -3077,7 +3080,7 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
max-width: calc(100% - var(--breakpoint-expression-right-clear-space));
display: inline-block;
padding-inline-end: 8px;
cursor: default;
cursor: pointer;
flex-grow: 1;
text-overflow: ellipsis;
overflow: hidden;
@ -3261,7 +3264,7 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
.expression-container__close-btn {
position: absolute;
offset-inline-end: 0px;
top: 0px;
top: 1px;
}
.expression-content {
@ -4049,6 +4052,7 @@ html .welcomebox .toggle-button-end.collapsed {
position: relative;
transition: all 0.15s ease;
min-width: 40px;
max-width: 100%;
overflow: hidden;
padding: 5px;
margin-inline-start: 3px;

Просмотреть файл

@ -22811,7 +22811,7 @@ function toParsedScopes(children, sourceId) {
return {
start: scope.loc.start,
end: scope.loc.end,
type: scope.type === "module" ? "block" : scope.type,
type: scope.type === "module" || scope.type === "function-body" ? "block" : scope.type,
displayName: scope.displayName,
bindings: scope.bindings,
children: toParsedScopes(scope.children, sourceId)
@ -22906,9 +22906,18 @@ function isLetOrConst(node) {
}
function hasLexicalDeclaration(node, parent) {
const nodes = [];
if (t.isSwitchStatement(node)) {
for (const caseNode of node.cases) {
nodes.push(...caseNode.consequent);
}
} else {
nodes.push(...node.body);
}
const isFunctionBody = t.isFunction(parent, { body: node });
return node.body.some(child => isLexicalVariable(child) || !isFunctionBody && child.type === "FunctionDeclaration" || child.type === "ClassDeclaration");
return nodes.some(child => isLexicalVariable(child) || t.isClassDeclaration(child) || !isFunctionBody && t.isFunctionDeclaration(child));
}
function isLexicalVariable(node) {
return isNode(node, "VariableDeclaration") && isLetOrConst(node);
@ -22973,19 +22982,27 @@ const scopeCollectionVisitor = {
// This ignores Annex B function declaration hoisting, which
// is probably a fine assumption.
state.declarationBindingIds.add(node.id);
const fnScope = getVarScope(scope);
scope.bindings[node.id.name] = {
type: fnScope === scope ? "var" : "let",
refs: [{
type: "fn-decl",
start: fromBabelLocation(node.id.loc.start, state.sourceId),
end: fromBabelLocation(node.id.loc.end, state.sourceId),
declaration: {
start: fromBabelLocation(node.loc.start, state.sourceId),
end: fromBabelLocation(node.loc.end, state.sourceId)
}
}]
};
const refs = [{
type: "fn-decl",
start: fromBabelLocation(node.id.loc.start, state.sourceId),
end: fromBabelLocation(node.id.loc.end, state.sourceId),
declaration: {
start: fromBabelLocation(node.loc.start, state.sourceId),
end: fromBabelLocation(node.loc.end, state.sourceId)
}
}];
if (scope.type === "block") {
scope.bindings[node.id.name] = {
type: "let",
refs
};
} else {
getVarScope(scope).bindings[node.id.name] = {
type: "var",
refs
};
}
}
scope = pushTempScope(state, "function", (0, _getFunctionName2.default)(node, parentNode), {
@ -23007,6 +23024,13 @@ const scopeCollectionVisitor = {
refs: []
};
}
if (t.isBlockStatement(node.body) && hasLexicalDeclaration(node.body, node)) {
scope = pushTempScope(state, "function-body", "Function Body", {
start: fromBabelLocation(node.body.loc.start, state.sourceId),
end: fromBabelLocation(node.body.loc.end, state.sourceId)
});
}
} else if (t.isClass(node)) {
if (t.isIdentifier(node.id)) {
// For decorated classes, the AST considers the first the decorator
@ -23075,7 +23099,9 @@ const scopeCollectionVisitor = {
end: fromBabelLocation(node.loc.end, state.sourceId)
});
parseDeclarator(node.param, scope, "var", "catch", node, state);
} else if (t.isBlockStatement(node) && hasLexicalDeclaration(node, parentNode)) {
} else if (t.isBlockStatement(node) &&
// Function body's are handled in the function logic above.
!t.isFunction(parentNode) && hasLexicalDeclaration(node, parentNode)) {
// Debugger will create new lexical environment for the block.
pushTempScope(state, "block", "Block", {
start: fromBabelLocation(node.loc.start, state.sourceId),
@ -23199,7 +23225,7 @@ const scopeCollectionVisitor = {
type: "implicit",
refs: []
};
} else if (t.isSwitchStatement(node) && node.cases.some(caseNode => caseNode.consequent.some(child => isLexicalVariable(child)))) {
} else if (t.isSwitchStatement(node) && hasLexicalDeclaration(node, parentNode)) {
pushTempScope(state, "block", "Switch", {
start: fromBabelLocation(node.loc.start, state.sourceId),
end: fromBabelLocation(node.loc.end, state.sourceId)
@ -25012,6 +25038,7 @@ const {
const dispatcher = new WorkerDispatcher();
const getOriginalURLs = dispatcher.task("getOriginalURLs");
const getOriginalRanges = dispatcher.task("getOriginalRanges");
const getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
queue: true
});
@ -25035,6 +25062,7 @@ module.exports = {
isOriginalId,
hasMappedSource,
getOriginalURLs,
getOriginalRanges,
getGeneratedRanges,
getGeneratedLocation,
getAllGeneratedLocations,

Просмотреть файл

@ -417,7 +417,7 @@ function toggleBreakpoint(line, column) {
line,
column
});
const isEmptyLine = (0, _ast.isEmptyLineInSource)(state, line, selectedSource);
const isEmptyLine = (0, _ast.isEmptyLineInSource)(state, line, selectedSource.id);
if (!bp && isEmptyLine || bp && bp.loading) {
return;
@ -434,8 +434,8 @@ function toggleBreakpoint(line, column) {
}
return dispatch(addBreakpoint({
sourceId: selectedSource.get("id"),
sourceUrl: selectedSource.get("url"),
sourceId: selectedSource.id,
sourceUrl: selectedSource.url,
line: line,
column: column
}));

Просмотреть файл

@ -211,9 +211,9 @@ const mapStateToProps = state => {
return {
selectedLocation: (0, _selectors.getSelectedLocation)(state),
selectedSource,
hasPrettyPrint: !!(0, _selectors.getPrettySource)(state, selectedSource.get("id")),
hasPrettyPrint: !!(0, _selectors.getPrettySource)(state, selectedSource.id),
contextMenu: (0, _selectors.getContextMenu)(state),
getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource.toJS(), symbols),
getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource, symbols),
getFunctionLocation: line => (0, _ast.findClosestFunction)(symbols, {
line,
column: Infinity

Просмотреть файл

@ -70,7 +70,7 @@ class EmptyLines extends _react.Component {
const mapStateToProps = state => {
const selectedSource = (0, _selectors.getSelectedSource)(state);
const foundEmptyLines = (0, _selectors.getEmptyLines)(state, selectedSource.toJS());
const foundEmptyLines = (0, _selectors.getEmptyLines)(state, selectedSource.id);
return {
selectedSource,
emptyLines: selectedSource ? foundEmptyLines : []

Просмотреть файл

@ -169,7 +169,7 @@ const mapStateToProps = state => {
breakpoints: (0, _selectors.getVisibleBreakpoints)(state),
isPaused: (0, _selectors.isPaused)(state),
contextMenu: (0, _selectors.getContextMenu)(state),
emptyLines: (0, _selectors.getEmptyLines)(state, selectedSource.toJS())
emptyLines: (0, _selectors.getEmptyLines)(state, selectedSource.id)
};
};

Просмотреть файл

@ -18,6 +18,8 @@ var _SourceIcon2 = _interopRequireDefault(_SourceIcon);
var _Button = require("../shared/Button/index");
var _text = require("../../utils/text");
var _actions = require("../../actions/index");
var _actions2 = _interopRequireDefault(_actions);
@ -175,7 +177,7 @@ class Tab extends _react.PureComponent {
shouldHide: icon => ["file", "javascript"].includes(icon)
}), _react2.default.createElement("div", {
className: "filename"
}, (0, _devtoolsModules.getUnicodeUrlPath)(filename)), _react2.default.createElement(_Button.CloseButton, {
}, (0, _text.truncateMiddleText)((0, _devtoolsModules.getUnicodeUrlPath)(filename), 30)), _react2.default.createElement(_Button.CloseButton, {
handleClick: onClickClose,
tooltip: L10N.getStr("sourceTabs.closeTabButtonTooltip")
}));

Просмотреть файл

@ -16,14 +16,14 @@ var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored[
var _classnames2 = _interopRequireDefault(_classnames);
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
var _Button = require("../shared/Button/index");
var _breakpoint = require("../../utils/breakpoint/index");
var _prefs = require("../../utils/prefs");
var _pause = require("../../utils/pause/index");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* This Source Code Form is subject to the terms of the Mozilla Public
@ -39,19 +39,19 @@ function getBreakpointLocation(source, line, column) {
function getBreakpointText(selectedSource, breakpoint) {
const {
condition,
text,
originalText
text
} = breakpoint;
return condition || text;
}
if (condition) {
return condition;
function isCurrentlyPausedAtBreakpoint(breakpoint, frame, why) {
if (!frame || (0, _pause.isInterrupted)(why)) {
return false;
}
if (!selectedSource || (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id) || originalText.length == 0) {
return text;
}
return originalText;
const bpId = (0, _breakpoint.getLocationWithoutColumn)(breakpoint.location);
const pausedId = (0, _breakpoint.getLocationWithoutColumn)(frame.location);
return bpId === pausedId;
}
class Breakpoint extends _react.Component {
@ -74,7 +74,9 @@ class Breakpoint extends _react.Component {
shouldComponentUpdate(nextProps) {
const prevBreakpoint = this.props.breakpoint;
const nextBreakpoint = nextProps.breakpoint;
return !prevBreakpoint || this.props.selectedSource != nextProps.selectedSource || prevBreakpoint.text != nextBreakpoint.text || prevBreakpoint.disabled != nextBreakpoint.disabled || prevBreakpoint.condition != nextBreakpoint.condition || prevBreakpoint.hidden != nextBreakpoint.hidden || prevBreakpoint.isCurrentlyPaused != nextBreakpoint.isCurrentlyPaused;
const wasPaused = isCurrentlyPausedAtBreakpoint(prevBreakpoint, this.props.frame, this.props.why);
const isPaused = isCurrentlyPausedAtBreakpoint(nextBreakpoint, nextProps.frame, nextProps.why);
return !prevBreakpoint || this.props.selectedSource != nextProps.selectedSource || prevBreakpoint.text != nextBreakpoint.text || prevBreakpoint.disabled != nextBreakpoint.disabled || prevBreakpoint.condition != nextBreakpoint.condition || prevBreakpoint.hidden != nextBreakpoint.hidden || prevBreakpoint.frame != nextBreakpoint.frame || wasPaused != isPaused;
}
destroyEditor() {
@ -144,22 +146,15 @@ class Breakpoint extends _react.Component {
renderLineClose() {
const {
breakpoint,
onCloseClick,
selectedSource
onCloseClick
} = this.props;
const {
location
} = breakpoint;
let {
const {
line,
column
} = location;
if (selectedSource && (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id) && breakpoint.generatedLocation) {
line = breakpoint.generatedLocation.line;
column = breakpoint.generatedLocation.column;
}
return _react2.default.createElement("div", {
className: "breakpoint-line-close"
}, _react2.default.createElement("div", {
@ -174,10 +169,12 @@ class Breakpoint extends _react.Component {
const {
breakpoint,
onClick,
onContextMenu
onContextMenu,
frame,
why
} = this.props;
const locationId = breakpoint.locationId;
const isCurrentlyPaused = breakpoint.isCurrentlyPaused;
const isCurrentlyPaused = isCurrentlyPausedAtBreakpoint(breakpoint, frame, why);
const isDisabled = breakpoint.disabled;
const isConditional = !!breakpoint.condition;
return _react2.default.createElement("div", {

Просмотреть файл

@ -18,8 +18,6 @@ var _immutable = require("devtools/client/shared/vendor/immutable");
var I = _interopRequireWildcard(_immutable);
var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"];
var _lodash = require("devtools/client/shared/vendor/lodash");
var _Breakpoint = require("./Breakpoint");
@ -38,10 +36,6 @@ var _source = require("../../utils/source");
var _selectors = require("../../selectors/index");
var _pause = require("../../utils/pause/index");
var _breakpoint = require("../../utils/breakpoint/index");
var _BreakpointsContextMenu = require("./BreakpointsContextMenu");
var _BreakpointsContextMenu2 = _interopRequireDefault(_BreakpointsContextMenu);
@ -54,16 +48,6 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function isCurrentlyPausedAtBreakpoint(frame, why, breakpoint) {
if (!frame || !(0, _pause.isInterrupted)(why)) {
return false;
}
const bpId = (0, _breakpoint.makeLocationId)(breakpoint.location);
const pausedId = (0, _breakpoint.makeLocationId)(frame.location);
return bpId === pausedId;
}
function createExceptionOption(label, value, onChange, className) {
return _react2.default.createElement("div", {
className: className,
@ -106,7 +90,7 @@ class Breakpoints extends _react.Component {
}
selectBreakpoint(breakpoint) {
this.props.selectLocation(breakpoint.location);
this.props.selectSpecificLocation(breakpoint.location);
}
removeBreakpoint(event, breakpoint) {
@ -116,12 +100,16 @@ class Breakpoints extends _react.Component {
renderBreakpoint(breakpoint) {
const {
selectedSource
selectedSource,
why,
frame
} = this.props;
return _react2.default.createElement(_Breakpoint2.default, {
key: breakpoint.locationId,
breakpoint: breakpoint,
selectedSource: selectedSource,
why: why,
frame: frame,
onClick: () => this.selectBreakpoint(breakpoint),
onContextMenu: e => (0, _BreakpointsContextMenu2.default)(_objectSpread({}, this.props, {
breakpoint,
@ -188,24 +176,10 @@ class Breakpoints extends _react.Component {
}
function updateLocation(sources, frame, why, bp) {
const source = (0, _selectors.getSourceInSources)(sources, bp.location.sourceId);
const isCurrentlyPaused = isCurrentlyPausedAtBreakpoint(frame, why, bp);
const locationId = (0, _breakpoint.makeLocationId)(bp.location);
const localBP = _objectSpread({}, bp, {
locationId,
isCurrentlyPaused,
source
});
return localBP;
}
const _getBreakpoints = (0, _reselect.createSelector)(_selectors.getBreakpoints, _selectors.getSources, _selectors.getTopFrame, _selectors.getPauseReason, (breakpoints, sources, frame, why) => breakpoints.map(bp => updateLocation(sources, frame, why, bp)).filter(bp => bp.source && !bp.source.isBlackBoxed));
const mapStateToProps = state => ({
breakpoints: _getBreakpoints(state),
breakpoints: (0, _selectors.getMappedBreakpoints)(state),
frame: (0, _selectors.getTopFrame)(state),
why: (0, _selectors.getPauseReason)(state),
selectedSource: (0, _selectors.getSelectedSource)(state)
});

Просмотреть файл

@ -0,0 +1,196 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _react = require("devtools/client/shared/vendor/react");
var _react2 = _interopRequireDefault(_react);
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
var _classnames2 = _interopRequireDefault(_classnames);
var _actions = require("../../../actions/index");
var _actions2 = _interopRequireDefault(_actions);
var _BreakpointsContextMenu = require("./BreakpointsContextMenu");
var _BreakpointsContextMenu2 = _interopRequireDefault(_BreakpointsContextMenu);
var _Button = require("../../shared/Button/index");
var _breakpoint = require("../../../utils/breakpoint/index");
var _prefs = require("../../../utils/prefs");
var _editor = require("../../../utils/editor/index");
var _selectors = require("../../../selectors/index");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function getMappedLocation(mappedLocation, selectedSource) {
return selectedSource && (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id) ? mappedLocation.generatedLocation : mappedLocation.location;
}
class Breakpoint extends _react.PureComponent {
constructor(...args) {
var _temp;
return _temp = super(...args), this.onContextMenu = e => {
(0, _BreakpointsContextMenu2.default)(_objectSpread({}, this.props, {
contextMenuEvent: e
}));
}, this.selectBreakpoint = () => {
const {
breakpoint,
selectSpecificLocation
} = this.props;
selectSpecificLocation(breakpoint.location);
}, this.removeBreakpoint = event => {
const {
breakpoint,
removeBreakpoint
} = this.props;
event.stopPropagation();
removeBreakpoint(breakpoint.location);
}, this.handleBreakpointCheckbox = () => {
const {
breakpoint,
enableBreakpoint,
disableBreakpoint
} = this.props;
if (breakpoint.loading) {
return;
}
if (breakpoint.disabled) {
enableBreakpoint(breakpoint.location);
} else {
disableBreakpoint(breakpoint.location);
}
}, _temp;
}
isCurrentlyPausedAtBreakpoint() {
const {
frame,
breakpoint,
selectedSource
} = this.props;
if (!frame) {
return false;
}
const bpId = (0, _breakpoint.getLocationWithoutColumn)(getMappedLocation(breakpoint, selectedSource));
const frameId = (0, _breakpoint.getLocationWithoutColumn)(getMappedLocation(frame, selectedSource));
return bpId == frameId;
}
getBreakpointLocation() {
const {
breakpoint,
source,
selectedSource
} = this.props;
const {
column,
line
} = getMappedLocation(breakpoint, selectedSource);
const isWasm = source && source.isWasm;
const columnVal = _prefs.features.columnBreakpoints && column ? `:${column}` : "";
const bpLocation = isWasm ? `0x${line.toString(16).toUpperCase()}` : `${line}${columnVal}`;
return bpLocation;
}
getBreakpointText() {
const {
selectedSource,
breakpoint
} = this.props;
const {
condition
} = breakpoint;
if (condition) {
return condition;
}
if (selectedSource && (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id)) {
return breakpoint.text;
}
return breakpoint.originalText;
}
highlightText() {
const text = this.getBreakpointText();
const sourceEditor = (0, _editor.getEditor)();
if (!text || !sourceEditor || !sourceEditor.editor) {
return {
__html: ""
};
}
const node = document.createElement("div");
sourceEditor.editor.constructor.runMode(text, "application/javascript", node);
return {
__html: node.innerHTML
};
}
render() {
const {
breakpoint
} = this.props;
return _react2.default.createElement("div", {
className: (0, _classnames2.default)({
breakpoint,
paused: this.isCurrentlyPausedAtBreakpoint(),
disabled: breakpoint.disabled,
"is-conditional": !!breakpoint.condition
}),
onClick: this.selectBreakpoint,
onContextMenu: this.onContextMenu
}, _react2.default.createElement("input", {
type: "checkbox",
className: "breakpoint-checkbox",
checked: !breakpoint.disabled,
onChange: this.handleBreakpointCheckbox,
onClick: ev => ev.stopPropagation()
}), _react2.default.createElement("label", {
className: "breakpoint-label cm-s-mozilla",
title: this.getBreakpointText(),
dangerouslySetInnerHTML: this.highlightText()
}), _react2.default.createElement("div", {
className: "breakpoint-line-close"
}, _react2.default.createElement("div", {
className: "breakpoint-line"
}, this.getBreakpointLocation()), _react2.default.createElement(_Button.CloseButton, {
handleClick: e => this.removeBreakpoint(e),
tooltip: L10N.getStr("breakpoints.removeBreakpointTooltip")
})));
}
}
const mapStateToProps = state => ({
frame: (0, _selectors.getTopFrame)(state),
selectedSource: (0, _selectors.getSelectedSource)(state)
});
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Breakpoint);

Просмотреть файл

@ -0,0 +1,201 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = showContextMenu;
var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"];
/* 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 showContextMenu(props) {
const {
removeBreakpoint,
removeBreakpoints,
removeAllBreakpoints,
toggleBreakpoints,
toggleAllBreakpoints,
toggleDisabledBreakpoint,
selectLocation,
setBreakpointCondition,
openConditionalPanel,
breakpoints,
breakpoint,
contextMenuEvent
} = props;
contextMenuEvent.preventDefault();
const deleteSelfLabel = L10N.getStr("breakpointMenuItem.deleteSelf2.label");
const deleteAllLabel = L10N.getStr("breakpointMenuItem.deleteAll2.label");
const deleteOthersLabel = L10N.getStr("breakpointMenuItem.deleteOthers2.label");
const enableSelfLabel = L10N.getStr("breakpointMenuItem.enableSelf2.label");
const enableAllLabel = L10N.getStr("breakpointMenuItem.enableAll2.label");
const enableOthersLabel = L10N.getStr("breakpointMenuItem.enableOthers2.label");
const disableSelfLabel = L10N.getStr("breakpointMenuItem.disableSelf2.label");
const disableAllLabel = L10N.getStr("breakpointMenuItem.disableAll2.label");
const disableOthersLabel = L10N.getStr("breakpointMenuItem.disableOthers2.label");
const removeConditionLabel = L10N.getStr("breakpointMenuItem.removeCondition2.label");
const addConditionLabel = L10N.getStr("breakpointMenuItem.addCondition2.label");
const editConditionLabel = L10N.getStr("breakpointMenuItem.editCondition2.label");
const deleteSelfKey = L10N.getStr("breakpointMenuItem.deleteSelf2.accesskey");
const deleteAllKey = L10N.getStr("breakpointMenuItem.deleteAll2.accesskey");
const deleteOthersKey = L10N.getStr("breakpointMenuItem.deleteOthers2.accesskey");
const enableSelfKey = L10N.getStr("breakpointMenuItem.enableSelf2.accesskey");
const enableAllKey = L10N.getStr("breakpointMenuItem.enableAll2.accesskey");
const enableOthersKey = L10N.getStr("breakpointMenuItem.enableOthers2.accesskey");
const disableSelfKey = L10N.getStr("breakpointMenuItem.disableSelf2.accesskey");
const disableAllKey = L10N.getStr("breakpointMenuItem.disableAll2.accesskey");
const disableOthersKey = L10N.getStr("breakpointMenuItem.disableOthers2.accesskey");
const removeConditionKey = L10N.getStr("breakpointMenuItem.removeCondition2.accesskey");
const editConditionKey = L10N.getStr("breakpointMenuItem.editCondition2.accesskey");
const addConditionKey = L10N.getStr("breakpointMenuItem.addCondition2.accesskey");
const otherBreakpoints = breakpoints.filter(b => b !== breakpoint);
const enabledBreakpoints = breakpoints.filter(b => !b.disabled);
const disabledBreakpoints = breakpoints.filter(b => b.disabled);
const otherEnabledBreakpoints = breakpoints.filter(b => !b.disabled && b !== breakpoint);
const otherDisabledBreakpoints = breakpoints.filter(b => b.disabled && b !== breakpoint);
const deleteSelfItem = {
id: "node-menu-delete-self",
label: deleteSelfLabel,
accesskey: deleteSelfKey,
disabled: false,
click: () => removeBreakpoint(breakpoint.location)
};
const deleteAllItem = {
id: "node-menu-delete-all",
label: deleteAllLabel,
accesskey: deleteAllKey,
disabled: false,
click: () => removeAllBreakpoints()
};
const deleteOthersItem = {
id: "node-menu-delete-other",
label: deleteOthersLabel,
accesskey: deleteOthersKey,
disabled: false,
click: () => removeBreakpoints(otherBreakpoints)
};
const enableSelfItem = {
id: "node-menu-enable-self",
label: enableSelfLabel,
accesskey: enableSelfKey,
disabled: false,
click: () => toggleDisabledBreakpoint(breakpoint.location.line)
};
const enableAllItem = {
id: "node-menu-enable-all",
label: enableAllLabel,
accesskey: enableAllKey,
disabled: false,
click: () => toggleAllBreakpoints(false)
};
const enableOthersItem = {
id: "node-menu-enable-others",
label: enableOthersLabel,
accesskey: enableOthersKey,
disabled: false,
click: () => toggleBreakpoints(false, otherDisabledBreakpoints)
};
const disableSelfItem = {
id: "node-menu-disable-self",
label: disableSelfLabel,
accesskey: disableSelfKey,
disabled: false,
click: () => toggleDisabledBreakpoint(breakpoint.location.line)
};
const disableAllItem = {
id: "node-menu-disable-all",
label: disableAllLabel,
accesskey: disableAllKey,
disabled: false,
click: () => toggleAllBreakpoints(true)
};
const disableOthersItem = {
id: "node-menu-disable-others",
label: disableOthersLabel,
accesskey: disableOthersKey,
click: () => toggleBreakpoints(true, otherEnabledBreakpoints)
};
const removeConditionItem = {
id: "node-menu-remove-condition",
label: removeConditionLabel,
accesskey: removeConditionKey,
disabled: false,
click: () => setBreakpointCondition(breakpoint.location)
};
const addConditionItem = {
id: "node-menu-add-condition",
label: addConditionLabel,
accesskey: addConditionKey,
click: () => {
selectLocation(breakpoint.location);
openConditionalPanel(breakpoint.location.line);
}
};
const editConditionItem = {
id: "node-menu-edit-condition",
label: editConditionLabel,
accesskey: editConditionKey,
click: () => {
selectLocation(breakpoint.location);
openConditionalPanel(breakpoint.location.line);
}
};
const hideEnableSelfItem = !breakpoint.disabled;
const hideEnableAllItem = disabledBreakpoints.size === 0;
const hideEnableOthersItem = otherDisabledBreakpoints.size === 0;
const hideDisableAllItem = enabledBreakpoints.size === 0;
const hideDisableOthersItem = otherEnabledBreakpoints.size === 0;
const hideDisableSelfItem = breakpoint.disabled;
const items = [{
item: enableSelfItem,
hidden: () => hideEnableSelfItem
}, {
item: enableAllItem,
hidden: () => hideEnableAllItem
}, {
item: enableOthersItem,
hidden: () => hideEnableOthersItem
}, {
item: {
type: "separator"
},
hidden: () => hideEnableSelfItem && hideEnableAllItem && hideEnableOthersItem
}, {
item: deleteSelfItem
}, {
item: deleteAllItem
}, {
item: deleteOthersItem,
hidden: () => breakpoints.size === 1
}, {
item: {
type: "separator"
},
hidden: () => hideDisableSelfItem && hideDisableAllItem && hideDisableOthersItem
}, {
item: disableSelfItem,
hidden: () => hideDisableSelfItem
}, {
item: disableAllItem,
hidden: () => hideDisableAllItem
}, {
item: disableOthersItem,
hidden: () => hideDisableOthersItem
}, {
item: {
type: "separator"
}
}, {
item: addConditionItem,
hidden: () => breakpoint.condition
}, {
item: editConditionItem,
hidden: () => !breakpoint.condition
}, {
item: removeConditionItem,
hidden: () => !breakpoint.condition
}];
(0, _devtoolsContextmenu.showMenu)(contextMenuEvent, (0, _devtoolsContextmenu.buildMenu)(items));
}

Просмотреть файл

@ -0,0 +1,105 @@
"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);
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
var _Breakpoint = require("./Breakpoint");
var _Breakpoint2 = _interopRequireDefault(_Breakpoint);
var _SourceIcon = require("../../shared/SourceIcon");
var _SourceIcon2 = _interopRequireDefault(_SourceIcon);
var _actions = require("../../../actions/index");
var _actions2 = _interopRequireDefault(_actions);
var _source = require("../../../utils/source");
var _breakpoint = require("../../../utils/breakpoint/index");
var _selectors = require("../../../selectors/index");
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/>. */
function createExceptionOption(label, value, onChange, className) {
return _react2.default.createElement("div", {
className: className,
onClick: onChange
}, _react2.default.createElement("input", {
type: "checkbox",
checked: value ? "checked" : "",
onChange: e => e.stopPropagation() && onChange()
}), _react2.default.createElement("div", {
className: "breakpoint-exceptions-label"
}, label));
}
class Breakpoints extends _react.Component {
renderExceptionsOptions() {
const {
breakpointSources,
shouldPauseOnExceptions,
shouldPauseOnCaughtExceptions,
pauseOnExceptions
} = this.props;
const isEmpty = breakpointSources.length == 0;
const exceptionsBox = createExceptionOption(L10N.getStr("pauseOnExceptionsItem2"), shouldPauseOnExceptions, () => pauseOnExceptions(!shouldPauseOnExceptions, false), "breakpoints-exceptions");
const ignoreCaughtBox = createExceptionOption(L10N.getStr("pauseOnCaughtExceptionsItem"), shouldPauseOnCaughtExceptions, () => pauseOnExceptions(true, !shouldPauseOnCaughtExceptions), "breakpoints-exceptions-caught");
return _react2.default.createElement("div", {
className: (0, _classnames2.default)("breakpoints-exceptions-options", {
empty: isEmpty
})
}, exceptionsBox, shouldPauseOnExceptions ? ignoreCaughtBox : null);
}
renderBreakpoints() {
const {
breakpointSources
} = this.props;
return [...breakpointSources.map(({
source,
breakpoints
}) => [_react2.default.createElement("div", {
className: "breakpoint-heading",
title: source.url,
key: source.url,
onClick: () => this.props.selectSource(source.id)
}, _react2.default.createElement(_SourceIcon2.default, {
source: source
}), (0, _source.getFilename)(source)), ...breakpoints.map(breakpoint => _react2.default.createElement(_Breakpoint2.default, {
breakpoint: breakpoint,
source: source,
key: (0, _breakpoint.makeLocationId)(breakpoint.location)
}))])];
}
render() {
return _react2.default.createElement("div", {
className: "pane breakpoints-list"
}, this.renderExceptionsOptions(), this.renderBreakpoints());
}
}
const mapStateToProps = state => ({
breakpointSources: (0, _selectors.getBreakpointSources)(state),
selectedSource: (0, _selectors.getSelectedSource)(state)
});
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Breakpoints);

Просмотреть файл

@ -0,0 +1,14 @@
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DIRS += [
]
DevToolsModules(
'Breakpoint.js',
'BreakpointsContextMenu.js',
'index.js',
)

Просмотреть файл

@ -162,17 +162,17 @@ function isSymbolsLoading(state, source) {
return symbols.hasOwnProperty("loading");
}
function isEmptyLineInSource(state, line, selectedSource) {
const emptyLines = getEmptyLines(state, selectedSource);
function isEmptyLineInSource(state, line, selectedSourceId) {
const emptyLines = getEmptyLines(state, selectedSourceId);
return emptyLines && emptyLines.includes(line);
}
function getEmptyLines(state, source) {
if (!source) {
function getEmptyLines(state, sourceId) {
if (!sourceId) {
return null;
}
return state.ast.emptyLines.get(source.id);
return state.ast.emptyLines.get(sourceId);
}
function getPausePoints(state, sourceId) {

Просмотреть файл

@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getBreakpointSources = undefined;
var _lodash = require("devtools/client/shared/vendor/lodash");
var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"];
var _selectors = require("../selectors/index");
var _source = require("../utils/source");
/* 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 getBreakpointsForSource(source, breakpoints) {
return breakpoints.valueSeq().filter(bp => bp.location.sourceId == source.id && !bp.hidden && (bp.text || bp.condition)).sortBy(bp => bp.location.line).toJS();
}
function findBreakpointSources(sources, breakpoints) {
const sourceIds = (0, _lodash.uniq)(breakpoints.valueSeq().filter(bp => !bp.hidden).map(bp => bp.location.sourceId).toJS());
const breakpointSources = sourceIds.map(id => (0, _selectors.getSourceInSources)(sources, id)).filter(source => source && !source.isBlackBoxed);
return (0, _lodash.sortBy)(breakpointSources, source => (0, _source.getFilenameFromURL)(source.url));
}
function _getBreakpointSources(breakpoints, sources, selectedSource) {
const breakpointSources = findBreakpointSources(sources, breakpoints);
return breakpointSources.map(source => ({
source,
breakpoints: getBreakpointsForSource(source, breakpoints)
}));
}
const getBreakpointSources = exports.getBreakpointSources = (0, _reselect.createSelector)(_selectors.getBreakpoints, _selectors.getSources, _getBreakpointSources);

Просмотреть файл

@ -251,4 +251,13 @@ Object.defineProperty(exports, "getRelativeSources", {
get: function () {
return _getRelativeSources.getRelativeSources;
}
});
var _mappedBreakpoints = require("./mappedBreakpoints");
Object.defineProperty(exports, "getMappedBreakpoints", {
enumerable: true,
get: function () {
return _mappedBreakpoints.getMappedBreakpoints;
}
});

Просмотреть файл

@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getMappedBreakpoints = undefined;
var _breakpoint = require("../utils/breakpoint/index");
var _immutable = require("devtools/client/shared/vendor/immutable");
var _immutable2 = _interopRequireDefault(_immutable);
var _selectors = require("../selectors/index");
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"];
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/>. */
function formatBreakpoint(sources, selectedSource, breakpoint) {
let location = breakpoint.location;
let text = breakpoint.originalText;
const condition = breakpoint.condition;
const disabled = breakpoint.disabled;
const locationId = (0, _breakpoint.makeLocationId)(location);
const source = (0, _selectors.getSourceInSources)(sources, location.sourceId);
if ((0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id)) {
location = breakpoint.generatedLocation || breakpoint.location;
text = breakpoint.text;
}
const localBP = {
locationId,
location,
text,
source,
condition,
disabled
};
return localBP;
}
function _getMappedBreakpoints(breakpoints, sources, selectedSource) {
if (!selectedSource) {
return _immutable2.default.Map();
}
return breakpoints.map(bp => formatBreakpoint(sources, selectedSource, bp)).filter(bp => bp.source && !bp.source.isBlackBoxed);
}
const getMappedBreakpoints = exports.getMappedBreakpoints = (0, _reselect.createSelector)(_selectors.getBreakpoints, _selectors.getSources, _selectors.getSelectedSource, _selectors.getTopFrame, _selectors.getPauseReason, _getMappedBreakpoints);

Просмотреть файл

@ -14,6 +14,7 @@ DevToolsModules(
'inComponent.js',
'index.js',
'isSelectedFrameVisible.js',
'mappedBreakpoints.js',
'visibleBreakpoints.js',
'visibleSelectedFrame.js',
)

Просмотреть файл

@ -31,6 +31,7 @@ Object.defineProperty(exports, "findScopeByName", {
exports.firstString = firstString;
exports.locationMoved = locationMoved;
exports.makeLocationId = makeLocationId;
exports.getLocationWithoutColumn = getLocationWithoutColumn;
exports.makePendingLocationId = makePendingLocationId;
exports.assertBreakpoint = assertBreakpoint;
exports.assertPendingBreakpoint = assertPendingBreakpoint;
@ -77,6 +78,14 @@ function makeLocationId(location) {
return `${sourceId}:${line}:${columnString}`;
}
function getLocationWithoutColumn(location) {
const {
sourceId,
line
} = location;
return `${sourceId}:${line}`;
}
function makePendingLocationId(location) {
assertPendingLocation(location);
const {

Просмотреть файл

@ -9,6 +9,8 @@ var _parser = require("../../../workers/parser/index");
var _locColumn = require("./locColumn");
var _rangeMetadata = require("./rangeMetadata");
var _findGeneratedBindingFromPosition = require("./findGeneratedBindingFromPosition");
var _buildGeneratedBindingList = require("./buildGeneratedBindingList");
@ -30,10 +32,11 @@ async function buildMappedScopes(source, frame, scopes, sourceMaps, client) {
}
const generatedAstBindings = (0, _buildGeneratedBindingList.buildGeneratedBindingList)(scopes, generatedAstScopes, frame.this);
const originalRanges = await (0, _rangeMetadata.loadRangeMetadata)(source, frame, originalAstScopes, sourceMaps);
const {
mappedOriginalScopes,
expressionLookup
} = await mapOriginalBindingsToGenerated(source, originalAstScopes, generatedAstBindings, client, sourceMaps);
} = await mapOriginalBindingsToGenerated(source, originalRanges, originalAstScopes, generatedAstBindings, client, sourceMaps);
const mappedGeneratedScopes = generateClientScope(scopes, mappedOriginalScopes);
return isReliableScope(mappedGeneratedScopes) ? {
mappings: expressionLookup,
@ -41,7 +44,7 @@ async function buildMappedScopes(source, frame, scopes, sourceMaps, client) {
} : null;
}
async function mapOriginalBindingsToGenerated(source, originalAstScopes, generatedAstBindings, client, sourceMaps) {
async function mapOriginalBindingsToGenerated(source, originalRanges, originalAstScopes, generatedAstBindings, client, sourceMaps) {
const expressionLookup = {};
const mappedOriginalScopes = [];
const cachedSourceMaps = batchScopeMappings(originalAstScopes, source, sourceMaps);
@ -51,7 +54,7 @@ async function mapOriginalBindingsToGenerated(source, originalAstScopes, generat
for (const name of Object.keys(item.bindings)) {
const binding = item.bindings[name];
const result = await findGeneratedBinding(cachedSourceMaps, client, source, name, binding, generatedAstBindings);
const result = await findGeneratedBinding(cachedSourceMaps, client, source, name, binding, originalRanges, generatedAstBindings);
if (result) {
generatedBindings[name] = result.grip;
@ -213,7 +216,14 @@ function generateClientScope(scopes, originalScopes) {
return result;
}
async function findGeneratedBinding(sourceMaps, client, source, name, originalBinding, generatedAstBindings) {
function hasValidIdent(range, pos) {
return range.type === "match" || // For declarations, we allow the range on the identifier to be a
// more general "contains" to increase the chances of a match.
pos.type !== "ref" && range.type === "contains";
} // eslint-disable-next-line complexity
async function findGeneratedBinding(sourceMaps, client, source, name, originalBinding, originalRanges, generatedAstBindings) {
// If there are no references to the implicits, then we have no way to
// even attempt to map it back to the original since there is no location
// data to use. Bail out instead of just showing it as unmapped.
@ -227,27 +237,43 @@ async function findGeneratedBinding(sourceMaps, client, source, name, originalBi
let genContent = null;
for (const pos of refs) {
if (originalBinding.type === "import") {
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
} else {
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForStandardBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
const range = (0, _rangeMetadata.findMatchingRange)(originalRanges, pos);
if (range && hasValidIdent(range, pos)) {
if (originalBinding.type === "import") {
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
} else {
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForStandardBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
}
}
if ((pos.type === "class-decl" || pos.type === "class-inner") && source.contentType && source.contentType.match(/\/typescript/)) {
// Resolve to first binding in the range
const declContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForNormalDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
const declRange = (0, _rangeMetadata.findMatchingRange)(originalRanges, pos.declaration);
if (declContent) {
// Prefer the declaration mapping in this case because TS sometimes
// maps class declaration names to "export.Foo = Foo;" or to
// the decorator logic itself
genContent = declContent;
if (declRange && declRange.type !== "multiple") {
// Resolve to first binding in the range
const declContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForNormalDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
if (declContent) {
// Prefer the declaration mapping in this case because TS sometimes
// maps class declaration names to "export.Foo = Foo;" or to
// the decorator logic itself
genContent = declContent;
}
}
}
if (!genContent && (pos.type === "import-decl" || pos.type === "import-ns-decl")) {
// match the import declaration location
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
const declRange = (0, _rangeMetadata.findMatchingRange)(originalRanges, pos.declaration); // The import declaration should have an original position mapping,
// but otherwise we don't really have preferences on the range type
// because it can have multiple bindings, but we do want to make sure
// that all of the bindings that match the range are part of the same
// import declaration.
if (declRange && declRange.singleDeclaration) {
// match the import declaration location
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
}
}
if (genContent) {

Просмотреть файл

@ -16,4 +16,5 @@ DevToolsModules(
'locColumn.js',
'mappingContains.js',
'positionCmp.js',
'rangeMetadata.js',
)

Просмотреть файл

@ -0,0 +1,92 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.loadRangeMetadata = loadRangeMetadata;
exports.findMatchingRange = findMatchingRange;
var _locColumn = require("./locColumn");
var _positionCmp = require("./positionCmp");
var _filtering = require("./filtering");
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
async function loadRangeMetadata(source, frame, originalAstScopes, sourceMaps) {
const originalRanges = await sourceMaps.getOriginalRanges(frame.location.sourceId, source.url);
const sortedOriginalAstBindings = [];
for (const item of originalAstScopes) {
for (const name of Object.keys(item.bindings)) {
for (const ref of item.bindings[name].refs) {
sortedOriginalAstBindings.push(ref);
}
}
}
sortedOriginalAstBindings.sort((a, b) => (0, _positionCmp.positionCmp)(a.start, b.start));
let i = 0;
return originalRanges.map(range => {
const bindings = [];
while (i < sortedOriginalAstBindings.length && (sortedOriginalAstBindings[i].start.line < range.line || sortedOriginalAstBindings[i].start.line === range.line && (0, _locColumn.locColumn)(sortedOriginalAstBindings[i].start) < range.columnStart)) {
i++;
}
while (i < sortedOriginalAstBindings.length && sortedOriginalAstBindings[i].start.line === range.line && (0, _locColumn.locColumn)(sortedOriginalAstBindings[i].start) >= range.columnStart && (0, _locColumn.locColumn)(sortedOriginalAstBindings[i].start) < range.columnEnd) {
bindings.push(sortedOriginalAstBindings[i]);
i++;
}
let type = "empty";
let singleDeclaration = true;
if (bindings.length === 1) {
const binding = bindings[0];
if (binding.start.line === range.line && binding.start.column === range.columnStart) {
type = "match";
} else {
type = "contains";
}
} else if (bindings.length > 1) {
type = "multiple";
const binding = bindings[0];
const declStart = binding.type !== "ref" ? binding.declaration.start : null;
singleDeclaration = bindings.every(b => {
return declStart && b.type !== "ref" && (0, _positionCmp.positionCmp)(declStart, b.declaration.start) === 0;
});
}
return _objectSpread({
type,
singleDeclaration
}, range);
});
}
function findMatchingRange(sortedOriginalRanges, bindingRange) {
return (0, _filtering.filterSortedArray)(sortedOriginalRanges, range => {
if (range.line < bindingRange.start.line) {
return -1;
}
if (range.line > bindingRange.start.line) {
return 1;
}
if (range.columnEnd <= (0, _locColumn.locColumn)(bindingRange.start)) {
return -1;
}
if (range.columnStart > (0, _locColumn.locColumn)(bindingRange.start)) {
return 1;
}
return 0;
}).pop();
}

Просмотреть файл

@ -466,5 +466,5 @@ function getSourceClassnames(source, sourceMetaData) {
return "blackBox";
}
return sourceTypes[(0, _sourcesTree.getExtension)(source)] || defaultClassName;
return sourceTypes[(0, _sourcesTree.getExtension)(source.url)] || defaultClassName;
}

Просмотреть файл

@ -47,8 +47,7 @@ function isDirectory(url) {
return (parts.length === 0 || url.path.slice(-1) === "/" || nodeHasChildren(url)) && url.name != "(index)";
}
function getExtension(source) {
const url = source.get ? source.get("url") : source.url;
function getExtension(url = "") {
const parsedUrl = (0, _url.parse)(url).pathname;
if (!parsedUrl) {
@ -59,7 +58,7 @@ function getExtension(source) {
}
function isNotJavaScript(source) {
return ["css", "svg", "png"].includes(getExtension(source));
return ["css", "svg", "png"].includes(getExtension(source.url));
}
function isInvalidUrl(url, source) {

Просмотреть файл

@ -3,7 +3,7 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.formatKeyShortcut = undefined;
exports.truncateMiddleText = exports.formatKeyShortcut = undefined;
var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"];
@ -40,5 +40,26 @@ function formatKeyShortcut(shortcut) {
return shortcut.replace(/CommandOrControl\+|CmdOrCtrl\+/g, `${L10N.getStr("ctrl")} `).replace(/Shift\+/g, "Shift ");
}
/**
* Truncates the received text to the maxLength in the format:
* Original: 'this is a very long text and ends here'
* Truncated: 'this is a ver...and ends here'
* @param {String} sourceText - Source text
* @param {Number} maxLength - Max allowed length
* @memberof utils/text
* @static
*/
exports.formatKeyShortcut = formatKeyShortcut;
function truncateMiddleText(sourceText, maxLength) {
let truncatedText = sourceText;
if (sourceText.length > maxLength) {
truncatedText = `${sourceText.substring(0, Math.round(maxLength / 2) - 2)}...${sourceText.substring(sourceText.length - Math.round(maxLength / 2 - 1))}`;
}
return truncatedText;
}
exports.formatKeyShortcut = formatKeyShortcut;
exports.truncateMiddleText = truncateMiddleText;

Просмотреть файл

@ -89,7 +89,7 @@ function toParsedScopes(children, sourceId) {
return {
start: scope.loc.start,
end: scope.loc.end,
type: scope.type === "module" ? "block" : scope.type,
type: scope.type === "module" || scope.type === "function-body" ? "block" : scope.type,
displayName: scope.displayName,
bindings: scope.bindings,
children: toParsedScopes(scope.children, sourceId)
@ -190,10 +190,20 @@ function isLetOrConst(node) {
}
function hasLexicalDeclaration(node, parent) {
const nodes = [];
if (t.isSwitchStatement(node)) {
for (const caseNode of node.cases) {
nodes.push(...caseNode.consequent);
}
} else {
nodes.push(...node.body);
}
const isFunctionBody = t.isFunction(parent, {
body: node
});
return node.body.some(child => isLexicalVariable(child) || !isFunctionBody && child.type === "FunctionDeclaration" || child.type === "ClassDeclaration");
return nodes.some(child => isLexicalVariable(child) || t.isClassDeclaration(child) || !isFunctionBody && t.isFunctionDeclaration(child));
}
function isLexicalVariable(node) {
@ -257,19 +267,27 @@ const scopeCollectionVisitor = {
// This ignores Annex B function declaration hoisting, which
// is probably a fine assumption.
state.declarationBindingIds.add(node.id);
const fnScope = getVarScope(scope);
scope.bindings[node.id.name] = {
type: fnScope === scope ? "var" : "let",
refs: [{
type: "fn-decl",
start: fromBabelLocation(node.id.loc.start, state.sourceId),
end: fromBabelLocation(node.id.loc.end, state.sourceId),
declaration: {
start: fromBabelLocation(node.loc.start, state.sourceId),
end: fromBabelLocation(node.loc.end, state.sourceId)
}
}]
};
const refs = [{
type: "fn-decl",
start: fromBabelLocation(node.id.loc.start, state.sourceId),
end: fromBabelLocation(node.id.loc.end, state.sourceId),
declaration: {
start: fromBabelLocation(node.loc.start, state.sourceId),
end: fromBabelLocation(node.loc.end, state.sourceId)
}
}];
if (scope.type === "block") {
scope.bindings[node.id.name] = {
type: "let",
refs
};
} else {
getVarScope(scope).bindings[node.id.name] = {
type: "var",
refs
};
}
}
scope = pushTempScope(state, "function", (0, _getFunctionName2.default)(node, parentNode), {
@ -290,6 +308,13 @@ const scopeCollectionVisitor = {
refs: []
};
}
if (t.isBlockStatement(node.body) && hasLexicalDeclaration(node.body, node)) {
scope = pushTempScope(state, "function-body", "Function Body", {
start: fromBabelLocation(node.body.loc.start, state.sourceId),
end: fromBabelLocation(node.body.loc.end, state.sourceId)
});
}
} else if (t.isClass(node)) {
if (t.isIdentifier(node.id)) {
// For decorated classes, the AST considers the first the decorator
@ -359,7 +384,8 @@ const scopeCollectionVisitor = {
end: fromBabelLocation(node.loc.end, state.sourceId)
});
parseDeclarator(node.param, scope, "var", "catch", node, state);
} else if (t.isBlockStatement(node) && hasLexicalDeclaration(node, parentNode)) {
} else if (t.isBlockStatement(node) && // Function body's are handled in the function logic above.
!t.isFunction(parentNode) && hasLexicalDeclaration(node, parentNode)) {
// Debugger will create new lexical environment for the block.
pushTempScope(state, "block", "Block", {
start: fromBabelLocation(node.loc.start, state.sourceId),
@ -489,7 +515,7 @@ const scopeCollectionVisitor = {
type: "implicit",
refs: []
};
} else if (t.isSwitchStatement(node) && node.cases.some(caseNode => caseNode.consequent.some(child => isLexicalVariable(child)))) {
} else if (t.isSwitchStatement(node) && hasLexicalDeclaration(node, parentNode)) {
pushTempScope(state, "block", "Switch", {
start: fromBabelLocation(node.loc.start, state.sourceId),
end: fromBabelLocation(node.loc.end, state.sourceId)

Просмотреть файл

@ -31,6 +31,8 @@ support-files =
examples/sourcemapped/fixtures/babel-for-loops/output.js.map
examples/sourcemapped/fixtures/babel-functions/output.js
examples/sourcemapped/fixtures/babel-functions/output.js.map
examples/sourcemapped/fixtures/babel-lex-and-nonlex/output.js
examples/sourcemapped/fixtures/babel-lex-and-nonlex/output.js.map
examples/sourcemapped/fixtures/babel-type-module/output.js
examples/sourcemapped/fixtures/babel-type-module/output.js.map
examples/sourcemapped/fixtures/babel-type-script/output.js

Просмотреть файл

@ -25,7 +25,7 @@ add_task(async function() {
let onPaused = waitForPaused(dbg);
invokeInTab("mutate");
await onPaused;
await waitForLoadedSource(dbg, "script-mutate");
await waitForSelectedSource(dbg, "script-mutate");
is(
getScopeNodeLabel(dbg, 2),

Просмотреть файл

@ -46,7 +46,7 @@ add_task(async function() {
"Block",
["three", "5"],
["two", "4"],
"Block",
"Function Body",
["three", "3"],
["two", "2"],
"root",
@ -73,7 +73,7 @@ add_task(async function() {
["aConst", '"const2"'],
["aLet", '"let2"'],
"Outer:_Outer()",
"Block",
"Function Body",
["aConst", '"const1"'],
["aLet", '"let1"'],
"Outer()",
@ -86,7 +86,7 @@ add_task(async function() {
"babel-line-start-bindings-es6",
{ line: 19, column: 4 },
[
"Block",
"Function Body",
["<this>", "{\u2026}"],
["one", "1"],
["two", "2"],
@ -102,7 +102,7 @@ add_task(async function() {
"babel-this-arguments-bindings",
{ line: 4, column: 4 },
[
"Block",
"Function Body",
["<this>", '"this-value"'],
["arrow", "undefined"],
"fn",
@ -123,7 +123,7 @@ add_task(async function() {
"arrow",
["<this>", '"this-value"'],
["argArrow", '"arrow-arg"'],
"Block",
"Function Body",
"arrow()",
"fn",
["arg", '"arg-value"'],
@ -158,12 +158,12 @@ add_task(async function() {
]);
await breakpointScopes(dbg, "babel-classes", { line: 12, column: 6 }, [
"Block",
"Function Body",
["three", "3"],
["two", "2"],
"Class",
"Another()",
"Block",
"Function Body",
"Another()",
["one", "1"],
"Thing()",
@ -174,7 +174,7 @@ add_task(async function() {
await breakpointScopes(dbg, "babel-for-loops", { line: 5, column: 4 }, [
"For",
["i", "1"],
"Block",
"Function Body",
["i", "0"],
"Module",
"root()"
@ -183,7 +183,7 @@ add_task(async function() {
await breakpointScopes(dbg, "babel-for-loops", { line: 9, column: 4 }, [
"For",
["i", '"2"'],
"Block",
"Function Body",
["i", "0"],
"Module",
"root()"
@ -192,7 +192,7 @@ add_task(async function() {
await breakpointScopes(dbg, "babel-for-loops", { line: 13, column: 4 }, [
"For",
["i", "3"],
"Block",
"Function Body",
["i", "0"],
"Module",
"root()"
@ -201,13 +201,13 @@ add_task(async function() {
await breakpointScopes(dbg, "babel-functions", { line: 6, column: 8 }, [
"arrow",
["p3", "undefined"],
"Block",
"Function Body",
"arrow()",
"inner",
["p2", "undefined"],
"Function Expression",
"inner()",
"Block",
"Function Body",
"inner()",
"decl",
["p1", "undefined"],
@ -268,7 +268,7 @@ add_task(async function() {
await breakpointScopes(dbg, "babel-switches", { line: 7, column: 6 }, [
"Switch",
["val", "2"],
"Block",
"Function Body",
["val", "1"],
"Module",
"root()"
@ -279,7 +279,7 @@ add_task(async function() {
["val", "3"],
"Switch",
["val", "2"],
"Block",
"Function Body",
["val", "1"],
"Module",
"root()"
@ -290,12 +290,21 @@ add_task(async function() {
["two", "2"],
"Catch",
["err", '"AnError"'],
"Block",
"Function Body",
["one", "1"],
"Module",
"root()"
]);
await breakpointScopes(dbg, "babel-lex-and-nonlex", { line: 3, column: 4 }, [
"Function Body",
"Thing()",
"root",
"someHelper()",
"Module",
"root()"
]);
await breakpointScopes(
dbg,
"babel-modules-webpack",

Просмотреть файл

@ -40,7 +40,7 @@ add_task(async function() {
is(getScopeLabel(dbg, 2), "na");
is(getScopeLabel(dbg, 3), "nb");
is(getScopeLabel(dbg, 4), "Block");
is(getScopeLabel(dbg, 4), "Function Body");
await toggleScopeNode(dbg, 4);

Просмотреть файл

@ -27,6 +27,8 @@
<button onclick="babelForOf()">Run babel-for-of</button>
<script src="sourcemapped/fixtures/babel-functions/output.js"></script>
<button onclick="babelFunctions()">Run babel-functions</button>
<script src="sourcemapped/fixtures/babel-lex-and-nonlex/output.js"></script>
<button onclick="babelLexAndNonlex()">Run babel-lex-and-nonlex</button>
<script src="sourcemapped/fixtures/babel-line-start-bindings-es6/output.js"></script>
<button onclick="babelLineStartBindingsEs6()">Run babel-line-start-bindings-es6</button>
<script src="sourcemapped/fixtures/babel-modules-cjs/output.js"></script>

Просмотреть файл

@ -0,0 +1,9 @@
export default function root() {
function someHelper(){
console.log("pause here", root, Thing);
}
class Thing {}
someHelper();
}

Просмотреть файл

@ -0,0 +1,90 @@
var babelLexAndNonlex =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony export (immutable) */ __webpack_exports__["default"] = root;
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function root() {
function someHelper() {
console.log("pause here", root, Thing);
}
var Thing = function Thing() {
_classCallCheck(this, Thing);
};
someHelper();
}
/***/ })
/******/ ])["default"];
//# sourceMappingURL=output.js.map

Просмотреть файл

@ -0,0 +1 @@
{"version":3,"sources":["webpack:///webpack/bootstrap 683415abc3361bb5ff85","webpack:///./fixtures/babel-lex-and-nonlex/input.js"],"names":["root","someHelper","console","log","Thing"],"mappings":";;AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;;;;;AC7De,SAASA,IAAT,GAAgB;AAC7B,WAASC,UAAT,GAAqB;AACnBC,YAAQC,GAAR,CAAY,YAAZ,EAA0BH,IAA1B,EAAgCI,KAAhC;AACD;;AAH4B,MAKvBA,KALuB;AAAA;AAAA;;AAO7BH;AACD,C","file":"fixtures/babel-lex-and-nonlex/output.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 683415abc3361bb5ff85","export default function root() {\n function someHelper(){\n console.log(\"pause here\", root, Thing);\n }\n\n class Thing {}\n\n someHelper();\n}\n\n\n\n// WEBPACK FOOTER //\n// ./fixtures/babel-lex-and-nonlex/input.js"],"sourceRoot":""}

Просмотреть файл

@ -437,6 +437,7 @@ const {
const dispatcher = new WorkerDispatcher();
const getOriginalURLs = dispatcher.task("getOriginalURLs");
const getOriginalRanges = dispatcher.task("getOriginalRanges");
const getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
queue: true
});
@ -460,6 +461,7 @@ module.exports = {
isOriginalId,
hasMappedSource,
getOriginalURLs,
getOriginalRanges,
getGeneratedRanges,
getGeneratedLocation,
getAllGeneratedLocations,

Просмотреть файл

@ -1973,6 +1973,7 @@ exports.ArraySet = ArraySet;
const {
getOriginalURLs,
getOriginalRanges,
getGeneratedRanges,
getGeneratedLocation,
getAllGeneratedLocations,
@ -1993,6 +1994,7 @@ const {
// easier to unit test.
self.onmessage = workerHandler({
getOriginalURLs,
getOriginalRanges,
getGeneratedRanges,
getGeneratedLocation,
getAllGeneratedLocations,
@ -2046,6 +2048,57 @@ async function getOriginalURLs(generatedSource) {
const COMPUTED_SPANS = new WeakSet();
const SOURCE_MAPPINGS = new WeakMap();
async function getOriginalRanges(sourceId, url) {
if (!isOriginalId(sourceId)) {
return [];
}
const generatedSourceId = originalToGeneratedId(sourceId);
const map = await getSourceMap(generatedSourceId);
if (!map) {
return [];
}
let mappings = SOURCE_MAPPINGS.get(map);
if (!mappings) {
mappings = new Map();
SOURCE_MAPPINGS.set(map, mappings);
}
let fileMappings = mappings.get(url);
if (!fileMappings) {
fileMappings = [];
mappings.set(url, fileMappings);
const originalMappings = fileMappings;
map.eachMapping(mapping => {
if (mapping.source !== url) {
return;
}
const last = originalMappings[originalMappings.length - 1];
if (last && last.line === mapping.originalLine) {
if (last.columnStart < mapping.originalColumn) {
last.columnEnd = mapping.originalColumn;
} else {
// Skip this duplicate original location,
return;
}
}
originalMappings.push({
line: mapping.originalLine,
columnStart: mapping.originalColumn,
columnEnd: Infinity
});
}, null, SourceMapConsumer.ORIGINAL_ORDER);
}
return fileMappings;
}
/**
* Given an original location, find the ranges on the generated file that
* are mapped from the original range containing the location.
@ -2234,6 +2287,7 @@ function applySourceMap(generatedId, url, code, mappings) {
module.exports = {
getOriginalURLs,
getOriginalRanges,
getGeneratedRanges,
getGeneratedLocation,
getAllGeneratedLocations,

7
devtools/client/shared/vendor/WasmDis.js поставляемый
Просмотреть файл

@ -956,7 +956,9 @@ var WasmDisassembler = /** @class */ (function () {
case 30 /* CODE_OPERATOR */:
var operator = reader.result;
if (operator.code == 11 /* end */ && this._indentLevel == 0) {
// reached of the function, skipping the operator
// reached of the function, closing function body
this.appendBuffer(" )");
this.newLine();
break;
}
switch (operator.code) {
@ -980,8 +982,7 @@ var WasmDisassembler = /** @class */ (function () {
case 31 /* END_FUNCTION_BODY */:
this._funcIndex++;
this._backrefLabels = null;
this.appendBuffer(" )");
this.newLine();
// See case BinaryReaderState.CODE_OPERATOR for closing of body
break;
default:
throw new Error("Expectected state: " + reader.state);