зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1302872 - update debugger bundle r=me UPDATE_BUNDLE
--HG-- rename : devtools/client/debugger/new/test/mochitest/examples/doc-script-switching-01.html => devtools/client/debugger/new/test/mochitest/examples/doc-script-switching.html
This commit is contained in:
Родитель
474601f18a
Коммит
9232f9818d
|
@ -1,4 +1,4 @@
|
|||
// Generated from: 02b44328ac19e43705f51209237b20fb264f93f4 Merge pull request #711 from devtools-html/cleanup
|
||||
// Generated from: 30002d3cfc4341840af847af9eb2c31cab18abb5 Move some of editor-select.js test into editor-highlight.js to make tests more focused (and avoid timeouts on linux debug) (#746)
|
||||
|
||||
var Debugger =
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
|
@ -21282,8 +21282,8 @@ var Debugger =
|
|||
|
||||
var State = makeRecord({
|
||||
sources: I.Map(),
|
||||
selectedSource: undefined,
|
||||
pendingSelectedSourceURL: undefined,
|
||||
selectedLocation: undefined,
|
||||
pendingSelectedLocation: undefined,
|
||||
sourcesText: I.Map(),
|
||||
sourceMaps: I.Map(),
|
||||
tabs: I.List([])
|
||||
|
@ -21312,19 +21312,22 @@ var Debugger =
|
|||
break;
|
||||
|
||||
case "SELECT_SOURCE":
|
||||
return state.merge({
|
||||
selectedSource: action.source,
|
||||
pendingSelectedSourceURL: null,
|
||||
tabs: updateTabList(state, fromJS(action.source), action.options)
|
||||
return state.set("selectedLocation", {
|
||||
sourceId: action.source.id,
|
||||
line: action.line
|
||||
}).set("pendingSelectedLocation", null).merge({
|
||||
tabs: updateTabList(state, fromJS(action.source), action.tabIndex)
|
||||
});
|
||||
|
||||
case "SELECT_SOURCE_URL":
|
||||
return state.merge({ pendingSelectedSourceURL: action.url });
|
||||
return state.set("pendingSelectedLocation", {
|
||||
url: action.url,
|
||||
line: action.line
|
||||
});
|
||||
|
||||
case "CLOSE_TAB":
|
||||
return state.merge({
|
||||
selectedSource: getNewSelectedSource(state, action.id),
|
||||
tabs: removeSourceFromTabList(state, action.id)
|
||||
return state.merge({ tabs: removeSourceFromTabList(state, action.id) }).set("selectedLocation", {
|
||||
sourceId: getNewSelectedSourceId(state, action.id)
|
||||
});
|
||||
|
||||
case "LOAD_SOURCE_TEXT":
|
||||
|
@ -21359,9 +21362,9 @@ var Debugger =
|
|||
return _updateText(state, action, [action.originalSource]);
|
||||
|
||||
case "NAVIGATE":
|
||||
var source = state.selectedSource;
|
||||
var sourceUrl = source && source.get("url");
|
||||
return State().set("pendingSelectedSourceURL", sourceUrl);
|
||||
var source = getSelectedSource({ sources: state });
|
||||
var _url = source && source.get("url");
|
||||
return State().set("pendingSelectedLocation", { url: _url });
|
||||
}
|
||||
|
||||
return state;
|
||||
|
@ -21402,16 +21405,16 @@ var Debugger =
|
|||
/*
|
||||
* Adds the new source to the tab list if it is not already there
|
||||
*/
|
||||
function updateTabList(state, source, options) {
|
||||
function updateTabList(state, source, tabIndex) {
|
||||
var tabs = state.get("tabs");
|
||||
var selectedSource = state.get("selectedSource");
|
||||
var selectedSource = getSelectedSource({ sources: state });
|
||||
var selectedSourceIndex = tabs.indexOf(selectedSource);
|
||||
var sourceIndex = tabs.indexOf(source);
|
||||
var includesSource = !!tabs.find(t => t.get("id") == source.get("id"));
|
||||
|
||||
if (includesSource) {
|
||||
if (options.position != undefined) {
|
||||
return tabs.delete(sourceIndex).insert(options.position, source);
|
||||
if (tabIndex != undefined) {
|
||||
return tabs.delete(sourceIndex).insert(tabIndex, source);
|
||||
}
|
||||
|
||||
return tabs;
|
||||
|
@ -21423,13 +21426,13 @@ var Debugger =
|
|||
/**
|
||||
* Gets the next tab to select when a tab closes.
|
||||
*/
|
||||
function getNewSelectedSource(state, id) {
|
||||
function getNewSelectedSourceId(state, id) {
|
||||
var tabs = state.get("tabs");
|
||||
var selectedSource = state.get("selectedSource");
|
||||
var selectedSource = getSelectedSource({ sources: state });
|
||||
|
||||
// if we're not closing the selected tab return the selected tab
|
||||
if (selectedSource.get("id") != id) {
|
||||
return selectedSource;
|
||||
return selectedSource.get("id");
|
||||
}
|
||||
|
||||
var tabIndex = tabs.findIndex(tab => tab.get("id") == id);
|
||||
|
@ -21441,11 +21444,11 @@ var Debugger =
|
|||
|
||||
// if we're closing the last tab, select the penultimate tab
|
||||
if (tabIndex + 1 == numTabs) {
|
||||
return tabs.get(tabIndex - 1);
|
||||
return tabs.get(tabIndex - 1).get("id");
|
||||
}
|
||||
|
||||
// return the next tab
|
||||
return tabs.get(tabIndex + 1);
|
||||
return tabs.get(tabIndex + 1).get("id");
|
||||
}
|
||||
|
||||
// Selectors
|
||||
|
@ -21484,11 +21487,15 @@ var Debugger =
|
|||
}
|
||||
|
||||
function getSelectedSource(state) {
|
||||
return state.sources.selectedSource;
|
||||
return state.sources.selectedLocation && getSource(state, state.sources.selectedLocation.sourceId);
|
||||
}
|
||||
|
||||
function getPendingSelectedSourceURL(state) {
|
||||
return state.sources.pendingSelectedSourceURL;
|
||||
function getSelectedLocation(state) {
|
||||
return state.sources.selectedLocation;
|
||||
}
|
||||
|
||||
function getPendingSelectedLocation(state) {
|
||||
return state.sources.pendingSelectedLocation;
|
||||
}
|
||||
|
||||
function getSourceMap(state, sourceId) {
|
||||
|
@ -21514,7 +21521,8 @@ var Debugger =
|
|||
getSourceText,
|
||||
getSourceTabs,
|
||||
getSelectedSource,
|
||||
getPendingSelectedSourceURL,
|
||||
getSelectedLocation,
|
||||
getPendingSelectedLocation,
|
||||
getSourceMap,
|
||||
getPrettySource
|
||||
};
|
||||
|
@ -26884,11 +26892,10 @@ var Debugger =
|
|||
|
||||
switch (action.type) {
|
||||
case constants.PAUSED:
|
||||
if (action.status == "done") {
|
||||
var _action$value = action.value;
|
||||
var selectedFrameId = _action$value.selectedFrameId;
|
||||
var frames = _action$value.frames;
|
||||
var pauseInfo = _action$value.pauseInfo;
|
||||
{
|
||||
var selectedFrameId = action.selectedFrameId;
|
||||
var frames = action.frames;
|
||||
var pauseInfo = action.pauseInfo;
|
||||
|
||||
pauseInfo.isInterrupted = pauseInfo.why.type === "interrupted";
|
||||
|
||||
|
@ -26900,7 +26907,6 @@ var Debugger =
|
|||
});
|
||||
}
|
||||
|
||||
break;
|
||||
case constants.RESUME:
|
||||
return state.merge({
|
||||
pause: null,
|
||||
|
@ -27071,7 +27077,8 @@ var Debugger =
|
|||
getSourceText: sources.getSourceText,
|
||||
getSourceTabs: sources.getSourceTabs,
|
||||
getSelectedSource: sources.getSelectedSource,
|
||||
getPendingSelectedSourceURL: sources.getPendingSelectedSourceURL,
|
||||
getSelectedLocation: sources.getSelectedLocation,
|
||||
getPendingSelectedLocation: sources.getPendingSelectedLocation,
|
||||
getSourceMap: sources.getSourceMap,
|
||||
getPrettySource: sources.getPrettySource,
|
||||
|
||||
|
@ -28766,7 +28773,7 @@ var Debugger =
|
|||
},
|
||||
|
||||
onKeyDown(e) {
|
||||
if (e.key === "Escape") {
|
||||
if (this.state.searchOn && e.key === "Escape") {
|
||||
this.setState({ searchOn: false });
|
||||
e.preventDefault();
|
||||
}
|
||||
|
@ -30166,7 +30173,7 @@ var Debugger =
|
|||
var getSource = _require9.getSource;
|
||||
var getSourceByURL = _require9.getSourceByURL;
|
||||
var getSourceText = _require9.getSourceText;
|
||||
var getPendingSelectedSourceURL = _require9.getPendingSelectedSourceURL;
|
||||
var getPendingSelectedLocation = _require9.getPendingSelectedLocation;
|
||||
var getSourceMap = _require9.getSourceMap;
|
||||
var getSourceMapURL = _require9.getSourceMapURL;
|
||||
var getFrames = _require9.getFrames;
|
||||
|
@ -30196,9 +30203,9 @@ var Debugger =
|
|||
|
||||
// If a request has been made to show this source, go ahead and
|
||||
// select it.
|
||||
var pendingURL = getPendingSelectedSourceURL(getState());
|
||||
if (pendingURL === source.url) {
|
||||
dispatch(selectSource(source.id));
|
||||
var pendingLocation = getPendingSelectedLocation(getState());
|
||||
if (pendingLocation && pendingLocation.url === source.url) {
|
||||
dispatch(selectSource(source.id, { line: pendingLocation.line }));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -30246,17 +30253,21 @@ var Debugger =
|
|||
* @static
|
||||
*/
|
||||
function selectSourceURL(url) {
|
||||
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
|
||||
|
||||
return _ref7 => {
|
||||
var dispatch = _ref7.dispatch;
|
||||
var getState = _ref7.getState;
|
||||
|
||||
var source = getSourceByURL(getState(), url);
|
||||
if (source) {
|
||||
dispatch(selectSource(source.get("id")));
|
||||
dispatch(selectSource(source.get("id"), options));
|
||||
} else {
|
||||
dispatch({
|
||||
type: constants.SELECT_SOURCE_URL,
|
||||
url: url
|
||||
url: url,
|
||||
tabIndex: options.tabIndex,
|
||||
line: options.line
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -30288,7 +30299,8 @@ var Debugger =
|
|||
dispatch({
|
||||
type: constants.SELECT_SOURCE,
|
||||
source: source,
|
||||
options
|
||||
tabIndex: options.tabIndex,
|
||||
line: options.line
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -30767,31 +30779,31 @@ var Debugger =
|
|||
* @static
|
||||
*/
|
||||
function paused(pauseInfo) {
|
||||
return _ref2 => {
|
||||
var dispatch = _ref2.dispatch;
|
||||
var getState = _ref2.getState;
|
||||
var client = _ref2.client;
|
||||
var frame = pauseInfo.frame;
|
||||
var frames = pauseInfo.frames;
|
||||
var why = pauseInfo.why;
|
||||
return (() => {
|
||||
var _ref2 = _asyncToGenerator(function* (_ref3) {
|
||||
var dispatch = _ref3.dispatch;
|
||||
var getState = _ref3.getState;
|
||||
var client = _ref3.client;
|
||||
var frame = pauseInfo.frame;
|
||||
var frames = pauseInfo.frames;
|
||||
var why = pauseInfo.why;
|
||||
|
||||
frames = yield updateFrameLocations(getState(), frames);
|
||||
|
||||
dispatch(evaluateExpressions());
|
||||
|
||||
return dispatch({
|
||||
type: constants.PAUSED,
|
||||
[PROMISE]: _asyncToGenerator(function* () {
|
||||
frames = yield updateFrameLocations(getState(), frames);
|
||||
|
||||
dispatch(selectSource(frame.location.sourceId));
|
||||
return {
|
||||
pauseInfo: { why, frame },
|
||||
frames: frames,
|
||||
selectedFrameId: frame.id
|
||||
};
|
||||
})()
|
||||
dispatch(evaluateExpressions());
|
||||
dispatch({
|
||||
type: constants.PAUSED,
|
||||
pauseInfo: { why, frame },
|
||||
frames: frames,
|
||||
selectedFrameId: frame.id
|
||||
});
|
||||
dispatch(selectSource(frame.location.sourceId, { line: frame.location.line }));
|
||||
});
|
||||
};
|
||||
|
||||
return function (_x) {
|
||||
return _ref2.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32783,7 +32795,7 @@ var Debugger =
|
|||
|
||||
var getSourceText = _require4.getSourceText;
|
||||
var getBreakpointsForSource = _require4.getBreakpointsForSource;
|
||||
var getSelectedSource = _require4.getSelectedSource;
|
||||
var getSelectedLocation = _require4.getSelectedLocation;
|
||||
var getSelectedFrame = _require4.getSelectedFrame;
|
||||
|
||||
var _require5 = __webpack_require__(194);
|
||||
|
@ -32798,8 +32810,8 @@ var Debugger =
|
|||
|
||||
__webpack_require__(264);
|
||||
|
||||
function isSourceForFrame(source, frame) {
|
||||
return source && frame && frame.location.sourceId === source.get("id");
|
||||
function isTextForSource(sourceText) {
|
||||
return !sourceText.get("loading") && !sourceText.get("error");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32818,7 +32830,7 @@ var Debugger =
|
|||
var Editor = React.createClass({
|
||||
propTypes: {
|
||||
breakpoints: ImPropTypes.map.isRequired,
|
||||
selectedSource: ImPropTypes.map,
|
||||
selectedLocation: PropTypes.object,
|
||||
sourceText: PropTypes.object,
|
||||
addBreakpoint: PropTypes.func,
|
||||
removeBreakpoint: PropTypes.func,
|
||||
|
@ -32838,11 +32850,11 @@ var Debugger =
|
|||
|
||||
if (bp) {
|
||||
this.props.removeBreakpoint({
|
||||
sourceId: this.props.selectedSource.get("id"),
|
||||
sourceId: this.props.selectedLocation.sourceId,
|
||||
line: line + 1
|
||||
});
|
||||
} else {
|
||||
this.props.addBreakpoint({ sourceId: this.props.selectedSource.get("id"),
|
||||
this.props.addBreakpoint({ sourceId: this.props.selectedLocation.sourceId,
|
||||
line: line + 1 },
|
||||
// Pass in a function to get line text because the breakpoint
|
||||
// may slide and it needs to compute the value at the new
|
||||
|
@ -32851,45 +32863,52 @@ var Debugger =
|
|||
}
|
||||
},
|
||||
|
||||
clearDebugLine(line) {
|
||||
this.editor.codeMirror.removeLineClass(line - 1, "line", "debug-line");
|
||||
updateDebugLine(prevProps, nextProps) {
|
||||
if (prevProps.selectedFrame) {
|
||||
var line = prevProps.selectedFrame.location.line;
|
||||
this.editor.codeMirror.removeLineClass(line - 1, "line", "debug-line");
|
||||
}
|
||||
if (nextProps.selectedFrame) {
|
||||
var _line = nextProps.selectedFrame.location.line;
|
||||
this.editor.codeMirror.addLineClass(_line - 1, "line", "debug-line");
|
||||
}
|
||||
},
|
||||
|
||||
setDebugLine(line) {
|
||||
this.editor.codeMirror.addLineClass(line - 1, "line", "debug-line");
|
||||
highlightLine() {
|
||||
if (!this.pendingJumpLine) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the location has changed and a specific line is requested,
|
||||
// move to that line and flash it.
|
||||
var codeMirror = this.editor.codeMirror;
|
||||
|
||||
// Make sure to clean up after ourselves. Not only does this
|
||||
// cancel any existing animation, but it avoids it from
|
||||
// happening ever again (in case CodeMirror re-applies the
|
||||
// class, etc).
|
||||
if (this.lastJumpLine) {
|
||||
codeMirror.removeLineClass(this.lastJumpLine - 1, "line", "highlight-line");
|
||||
}
|
||||
|
||||
var line = this.pendingJumpLine;
|
||||
this.editor.alignLine(line);
|
||||
},
|
||||
|
||||
setSourceText(newSourceText, oldSourceText) {
|
||||
if (newSourceText.get("loading")) {
|
||||
this.setText("Loading...");
|
||||
return;
|
||||
// We only want to do the flashing animation if it's not a debug
|
||||
// line, which has it's own styling.
|
||||
if (!this.props.selectedFrame || this.props.selectedFrame.location.line !== line) {
|
||||
this.editor.codeMirror.addLineClass(line - 1, "line", "highlight-line");
|
||||
}
|
||||
|
||||
if (newSourceText.get("error")) {
|
||||
this.setText("Error");
|
||||
console.error(newSourceText.get("error"));
|
||||
return;
|
||||
}
|
||||
|
||||
this.setText(newSourceText.get("text"));
|
||||
this.setMode(newSourceText);
|
||||
|
||||
resizeBreakpointGutter(this.editor.codeMirror);
|
||||
this.lastJumpLine = line;
|
||||
this.pendingJumpLine = null;
|
||||
},
|
||||
|
||||
// Only reset the editor text if the source has changed.
|
||||
// * Resetting the text will remove the breakpoints.
|
||||
// * Comparing the source text is probably inneficient.
|
||||
setText(text) {
|
||||
if (!text || !this.editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (text == this.editor.getText()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.editor.setText(text);
|
||||
},
|
||||
|
||||
|
@ -32940,24 +32959,52 @@ var Debugger =
|
|||
},
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// Clear the currently highlighted line
|
||||
if (isSourceForFrame(this.props.selectedSource, this.props.selectedFrame)) {
|
||||
this.clearDebugLine(this.props.selectedFrame.location.line);
|
||||
// This lifecycle method is responsible for updating the editor
|
||||
// text.
|
||||
var sourceText = nextProps.sourceText;
|
||||
|
||||
if (!sourceText) {
|
||||
this.setText("");
|
||||
this.editor.setMode({ name: "text" });
|
||||
} else if (!isTextForSource(sourceText)) {
|
||||
// There are only 2 possible states: errored or loading. Do
|
||||
// nothing except put a message in the editor.
|
||||
this.setText(sourceText.get("error") || "Loading...");
|
||||
this.editor.setMode({ name: "text" });
|
||||
} else if (this.props.sourceText !== sourceText) {
|
||||
// Only update it if the `sourceText` object has actually changed.
|
||||
// It is immutable so it will always change when updated.
|
||||
this.setText(sourceText.get("text"));
|
||||
this.setMode(sourceText);
|
||||
resizeBreakpointGutter(this.editor.codeMirror);
|
||||
}
|
||||
},
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
// This is in `componentDidUpdate` so helper functions can expect
|
||||
// `this.props` to be the current props. This lifecycle method is
|
||||
// responsible for updating the editor annotations.
|
||||
var selectedLocation = this.props.selectedLocation;
|
||||
|
||||
// If the location is different and a new line is requested,
|
||||
// update the pending jump line. Note that if jumping to a line in
|
||||
// a source where the text hasn't been loaded yet, we will set the
|
||||
// line here but not jump until rendering the actual source.
|
||||
|
||||
if (prevProps.selectedLocation !== selectedLocation) {
|
||||
if (selectedLocation && selectedLocation.line != undefined) {
|
||||
this.pendingJumpLine = selectedLocation.line;
|
||||
} else {
|
||||
this.pendingJumpLine = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the source text. The source text may not have been loaded
|
||||
// yet. On startup, the source text may not exist yet.
|
||||
if (nextProps.sourceText) {
|
||||
this.setSourceText(nextProps.sourceText, this.props.sourceText);
|
||||
}
|
||||
|
||||
if (this.props.selectedSource && !nextProps.selectedSource) {
|
||||
this.editor.setText("");
|
||||
}
|
||||
|
||||
// Highlight the paused line if necessary
|
||||
if (isSourceForFrame(nextProps.selectedSource, nextProps.selectedFrame)) {
|
||||
this.setDebugLine(nextProps.selectedFrame.location.line);
|
||||
// Only update and jump around in real source texts. This will
|
||||
// keep the jump state around until the real source text is
|
||||
// loaded.
|
||||
if (this.props.sourceText && isTextForSource(this.props.sourceText)) {
|
||||
this.updateDebugLine(prevProps, this.props);
|
||||
this.highlightLine();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -32979,13 +33026,13 @@ var Debugger =
|
|||
});
|
||||
|
||||
module.exports = connect((state, props) => {
|
||||
var selectedSource = getSelectedSource(state);
|
||||
var selectedId = selectedSource && selectedSource.get("id");
|
||||
var selectedLocation = getSelectedLocation(state);
|
||||
var sourceId = selectedLocation && selectedLocation.sourceId;
|
||||
|
||||
return {
|
||||
selectedSource,
|
||||
sourceText: getSourceText(state, selectedId),
|
||||
breakpoints: getBreakpointsForSource(state, selectedId),
|
||||
selectedLocation,
|
||||
sourceText: getSourceText(state, sourceId),
|
||||
breakpoints: getBreakpointsForSource(state, sourceId),
|
||||
selectedFrame: getSelectedFrame(state)
|
||||
};
|
||||
}, dispatch => bindActionCreators(actions, dispatch))(Editor);
|
||||
|
@ -33231,6 +33278,13 @@ var Debugger =
|
|||
var Svg = __webpack_require__(234);
|
||||
var ImPropTypes = __webpack_require__(227);
|
||||
|
||||
var _require5 = __webpack_require__(212);
|
||||
|
||||
var Services = _require5.Services;
|
||||
|
||||
var shiftKey = Services.appinfo.OS === "Darwin" ? "\u21E7" : "Shift+";
|
||||
var ctrlKey = Services.appinfo.OS === "Linux" ? "Ctrl+" : "";
|
||||
|
||||
var actions = __webpack_require__(213);
|
||||
var Breakpoints = React.createFactory(__webpack_require__(271));
|
||||
var Expressions = React.createFactory(__webpack_require__(274));
|
||||
|
@ -33306,8 +33360,8 @@ var Debugger =
|
|||
this.keyShortcutsEnabled = true;
|
||||
keyShortcuts.on("F8", this.resume);
|
||||
keyShortcuts.on("F10", this.stepOver);
|
||||
keyShortcuts.on("F11", this.stepIn);
|
||||
keyShortcuts.on("F12", this.stepOut);
|
||||
keyShortcuts.on(`${ ctrlKey }F11`, this.stepIn);
|
||||
keyShortcuts.on(`${ ctrlKey }Shift+F11`, this.stepOut);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
|
@ -33315,8 +33369,8 @@ var Debugger =
|
|||
|
||||
keyShortcuts.off("F8", this.resume);
|
||||
keyShortcuts.off("F10", this.stepOver);
|
||||
keyShortcuts.off("F11", this.stepIn);
|
||||
keyShortcuts.off("F12", this.stepOut);
|
||||
keyShortcuts.off(`${ ctrlKey }F11`, this.stepIn);
|
||||
keyShortcuts.off(`${ ctrlKey }Shift+F11`, this.stepOut);
|
||||
},
|
||||
|
||||
componentDidUpdate() {
|
||||
|
@ -33325,7 +33379,7 @@ var Debugger =
|
|||
|
||||
renderStepButtons() {
|
||||
var className = this.props.pause ? "active" : "disabled";
|
||||
return [debugBtn(this.stepOver, "stepOver", className, "Step Over (F10)"), debugBtn(this.stepIn, "stepIn", className, "Step In (F11)"), debugBtn(this.stepOut, "stepOut", className, "Step Out \u21E7 (F12)")];
|
||||
return [debugBtn(this.stepOver, "stepOver", className, "Step Over (F10)"), debugBtn(this.stepIn, "stepIn", className, `Step In (${ ctrlKey }F11)`), debugBtn(this.stepOut, "stepOut", className, `Step Out (${ ctrlKey }${ shiftKey }F11)`)];
|
||||
},
|
||||
|
||||
renderPauseButton() {
|
||||
|
@ -37722,7 +37776,7 @@ var Debugger =
|
|||
key: source.get("id"),
|
||||
onClick: () => {
|
||||
var tabIndex = getLastVisibleTabIndex(sourceTabs, sourceTabEls);
|
||||
selectSource(source.get("id"), { position: tabIndex });
|
||||
selectSource(source.get("id"), { tabIndex });
|
||||
this.toggleSourcesDropdown();
|
||||
}
|
||||
}, filename);
|
||||
|
@ -37905,7 +37959,7 @@ var Debugger =
|
|||
},
|
||||
|
||||
render() {
|
||||
if (!this.props.selectedSource) {
|
||||
if (!this.props.selectedSource || !isEnabled("prettyPrint") && !isEnabled("blackBox")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -37946,6 +38000,8 @@ var Debugger =
|
|||
__webpack_require__(362);
|
||||
var Svg = __webpack_require__(234);
|
||||
|
||||
var INITIAL_SELECTED_INDEX = 0;
|
||||
|
||||
var Autocomplete = React.createClass({
|
||||
propTypes: {
|
||||
selectItem: PropTypes.func,
|
||||
|
@ -37957,7 +38013,7 @@ var Debugger =
|
|||
getInitialState() {
|
||||
return {
|
||||
inputValue: "",
|
||||
selectedIndex: -1
|
||||
selectedIndex: INITIAL_SELECTED_INDEX
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -38000,7 +38056,7 @@ var Debugger =
|
|||
ref: "searchInput",
|
||||
onChange: e => this.setState({
|
||||
inputValue: e.target.value,
|
||||
selectedIndex: -1
|
||||
selectedIndex: INITIAL_SELECTED_INDEX
|
||||
}),
|
||||
onFocus: e => this.setState({ focused: true }),
|
||||
onBlur: e => this.setState({ focused: false }),
|
||||
|
|
|
@ -151,7 +151,7 @@ var Debugger =
|
|||
|
||||
var consumer = _getConsumer(generatedSource.id);
|
||||
|
||||
// if there is not a consumer, then its a generated source without a map
|
||||
// if there is not a consumer, then it's a generated source without a map
|
||||
if (!consumer) {
|
||||
return {
|
||||
url: generatedSource.url,
|
||||
|
|
|
@ -381,6 +381,15 @@ ul.sources-list {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.highlight-line .CodeMirror-line {
|
||||
animation: fade-highlight-out 1.5s normal forwards;
|
||||
}
|
||||
|
||||
@keyframes fade-highlight-out {
|
||||
0% { background-color: var(--theme-highlight-gray); }
|
||||
100% { background-color: transparent; }
|
||||
}
|
||||
|
||||
.welcomebox {
|
||||
width: 100%;
|
||||
|
||||
|
|
|
@ -43,22 +43,29 @@
|
|||
"waitForThreadEvents": false,
|
||||
"waitForState": false,
|
||||
"waitForPaused": false,
|
||||
"waitForSources": false,
|
||||
"isPaused": false,
|
||||
"assertPausedLocation": false,
|
||||
"assertHighlightLocation": false,
|
||||
"initDebugger": false,
|
||||
"invokeInTab": false,
|
||||
"findSource": false,
|
||||
"findElement": false,
|
||||
"findAllElements": false,
|
||||
"selectSource": false,
|
||||
"stepOver": false,
|
||||
"stepIn": false,
|
||||
"stepOut": false,
|
||||
"resume": false,
|
||||
"reload": false,
|
||||
"navigate": false,
|
||||
"removeBreakpoint": false,
|
||||
"addBreakpoint": false,
|
||||
"toggleCallStack": false,
|
||||
"isVisibleWithin": false,
|
||||
"clickElement": false,
|
||||
"togglePauseOnExceptions": false
|
||||
"togglePauseOnExceptions": false,
|
||||
"pressKey": false,
|
||||
"EXAMPLE_URL": false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ support-files =
|
|||
!/devtools/client/commandline/test/helpers.js
|
||||
!/devtools/client/framework/test/shared-head.js
|
||||
examples/doc-scripts.html
|
||||
examples/doc-script-switching-01.html
|
||||
examples/doc-script-switching.html
|
||||
examples/doc-exceptions.html
|
||||
examples/doc-iframes.html
|
||||
examples/doc-debugger-statements.html
|
||||
|
@ -20,9 +20,13 @@ support-files =
|
|||
[browser_dbg-editor-gutter.js]
|
||||
[browser_dbg-editor-mode.js]
|
||||
[browser_dbg-editor-select.js]
|
||||
[browser_dbg-editor-highlight.js]
|
||||
[browser_dbg-call-stack.js]
|
||||
[browser_dbg-pause-exceptions.js]
|
||||
[browser_dbg-chrome-create.js]
|
||||
[browser_dbg-chrome-debugging.js]
|
||||
[browser_dbg-iframes.js]
|
||||
[browser_dbg-debugger-buttons.js]
|
||||
[browser_dbg_keyboard-shortcuts.js]
|
||||
[browser_dbg-navigation.js]
|
||||
[browser_dbg-console.js]
|
||||
|
|
|
@ -17,7 +17,7 @@ function isFrameSelected(dbg, index, title) {
|
|||
|
||||
add_task(function* () {
|
||||
const dbg = yield initDebugger(
|
||||
"doc-script-switching-01.html",
|
||||
"doc-script-switching.html",
|
||||
"script-switching-01.js"
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// Return a promise with a reference to jsterm, opening the split
|
||||
// console if necessary. This cleans up the split console pref so
|
||||
// it won't pollute other tests.
|
||||
function getSplitConsole(dbg) {
|
||||
const { toolbox, win } = dbg;
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled");
|
||||
});
|
||||
|
||||
if (!win) {
|
||||
win = toolbox.win;
|
||||
}
|
||||
|
||||
if (!toolbox.splitConsole) {
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {}, win);
|
||||
}
|
||||
|
||||
return new Promise(resolve => {
|
||||
toolbox.getPanelWhenReady("webconsole").then(() => {
|
||||
ok(toolbox.splitConsole, "Split console is shown.");
|
||||
let jsterm = toolbox.getPanel("webconsole").hud.jsterm;
|
||||
resolve(jsterm);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
Services.prefs.setBoolPref("devtools.toolbox.splitconsoleEnabled", true);
|
||||
const dbg = yield initDebugger("doc-script-switching.html");
|
||||
|
||||
yield getSplitConsole(dbg);
|
||||
ok(dbg.toolbox.splitConsole, "Split console is shown.");
|
||||
});
|
|
@ -0,0 +1,47 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that the editor will always highight the right line, no
|
||||
// matter if the source text doesn't exist yet or even if the source
|
||||
// doesn't exist.
|
||||
|
||||
add_task(function* () {
|
||||
const dbg = yield initDebugger("doc-scripts.html");
|
||||
const { selectors: { getSourceText }, getState } = dbg;
|
||||
const sourceUrl = EXAMPLE_URL + "code-long.js";
|
||||
|
||||
// The source itself doesn't even exist yet, and using
|
||||
// `selectSourceURL` will set a pending request to load this source
|
||||
// and highlight a specific line.
|
||||
dbg.actions.selectSourceURL(sourceUrl, { line: 66 });
|
||||
|
||||
// Wait for the source text to load and make sure we're in the right
|
||||
// place.
|
||||
yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
|
||||
assertHighlightLocation(dbg, "long.js", 66);
|
||||
|
||||
// Jump to line 16 and make sure the editor scrolled.
|
||||
yield selectSource(dbg, "long.js", 16);
|
||||
assertHighlightLocation(dbg, "long.js", 16);
|
||||
|
||||
// Make sure only one line is ever highlighted and the flash
|
||||
// animation is cancelled on old lines.
|
||||
yield selectSource(dbg, "long.js", 17);
|
||||
yield selectSource(dbg, "long.js", 18);
|
||||
assertHighlightLocation(dbg, "long.js", 18);
|
||||
is(findAllElements(dbg, "highlightLine").length, 1,
|
||||
"Only 1 line is highlighted");
|
||||
|
||||
// Test jumping to a line in a source that exists but hasn't been
|
||||
// loaded yet.
|
||||
yield waitForSources(dbg, "simple1.js");
|
||||
selectSource(dbg, "simple1.js", 6);
|
||||
|
||||
// Make sure the source is in the loading state, wait for it to be
|
||||
// fully loaded, and check the highlighted line.
|
||||
const simple1 = findSource(dbg, "simple1.js");
|
||||
ok(getSourceText(getState(), simple1.id).get("loading"));
|
||||
yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
|
||||
ok(getSourceText(getState(), simple1.id).get("text"));
|
||||
assertHighlightLocation(dbg, "simple1.js", 6);
|
||||
});
|
|
@ -5,10 +5,10 @@
|
|||
// debugger pauses
|
||||
|
||||
// checks to see if the first breakpoint is visible
|
||||
function isBreakpointVisible(dbg) {
|
||||
const bpLine = findElement(dbg, "breakpoint");
|
||||
function isElementVisible(dbg, elementName) {
|
||||
const bpLine = findElement(dbg, elementName);
|
||||
const cm = findElement(dbg, "codeMirror");
|
||||
ok(isVisibleWithin(cm, bpLine), "CodeMirror is scrolled to line");
|
||||
return bpLine && isVisibleWithin(cm, bpLine);
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
|
@ -21,7 +21,7 @@ add_task(function* () {
|
|||
const simple2 = findSource(dbg, "simple2.js");
|
||||
|
||||
// Set the initial breakpoint.
|
||||
yield addBreakpoint(dbg, simple1.id, 4);
|
||||
yield addBreakpoint(dbg, simple1, 4);
|
||||
ok(!getSelectedSource(getState()), "No selected source");
|
||||
|
||||
// Call the function that we set a breakpoint in.
|
||||
|
@ -42,11 +42,11 @@ add_task(function* () {
|
|||
|
||||
// Make sure that we can set a breakpoint on a line out of the
|
||||
// viewport, and that pausing there scrolls the editor to it.
|
||||
const longSrc = findSource(dbg, "long.js");
|
||||
yield addBreakpoint(dbg, longSrc.id, 66);
|
||||
let longSrc = findSource(dbg, "long.js");
|
||||
yield addBreakpoint(dbg, longSrc, 66);
|
||||
|
||||
invokeInTab("testModel");
|
||||
yield waitForPaused(dbg);
|
||||
assertPausedLocation(dbg, longSrc, 66);
|
||||
isBreakpointVisible(dbg);
|
||||
ok(isElementVisible(dbg, "breakpoint"), "Breakpoint is visible");
|
||||
});
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function countSources(dbg) {
|
||||
const sources = dbg.selectors.getSources(dbg.getState());
|
||||
return sources.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test navigating
|
||||
* navigating while paused will reset the pause state and sources
|
||||
*/
|
||||
add_task(function* () {
|
||||
const dbg = yield initDebugger(
|
||||
"doc-script-switching.html",
|
||||
"script-switching-01.js"
|
||||
);
|
||||
|
||||
invokeInTab("firstCall");
|
||||
yield waitForPaused(dbg);
|
||||
|
||||
yield navigate(dbg, "doc-scripts.html", "simple1.js", "long.js");
|
||||
yield addBreakpoint(dbg, "simple1.js", 4);
|
||||
invokeInTab("main");
|
||||
yield waitForPaused(dbg);
|
||||
assertPausedLocation(dbg, "simple1.js", 4);
|
||||
is(countSources(dbg), 4, "4 sources are loaded.");
|
||||
|
||||
yield navigate(dbg, "about:blank");
|
||||
yield waitForDispatch(dbg, "NAVIGATE");
|
||||
is(countSources(dbg), 0, "0 sources are loaded.");
|
||||
|
||||
yield navigate(dbg,
|
||||
"doc-scripts.html",
|
||||
"simple1.js",
|
||||
"simple2.js",
|
||||
"long.js",
|
||||
"scripts.html"
|
||||
);
|
||||
|
||||
is(countSources(dbg), 4, "4 sources are loaded.");
|
||||
});
|
|
@ -0,0 +1,49 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test keyboard shortcuts.
|
||||
*/
|
||||
|
||||
function pressResume(dbg) {
|
||||
pressKey(dbg, "resumeKey");
|
||||
return waitForPaused(dbg);
|
||||
}
|
||||
|
||||
function pressStepOver(dbg) {
|
||||
pressKey(dbg, "stepOverKey");
|
||||
return waitForPaused(dbg);
|
||||
}
|
||||
|
||||
function pressStepIn(dbg) {
|
||||
pressKey(dbg, "stepInKey");
|
||||
return waitForPaused(dbg);
|
||||
}
|
||||
|
||||
function pressStepOut(dbg) {
|
||||
pressKey(dbg, "stepOutKey");
|
||||
return waitForPaused(dbg);
|
||||
}
|
||||
|
||||
add_task(function*() {
|
||||
const dbg = yield initDebugger(
|
||||
"doc-debugger-statements.html",
|
||||
"debugger-statements.html"
|
||||
);
|
||||
|
||||
yield reload(dbg);
|
||||
yield waitForPaused(dbg);
|
||||
assertPausedLocation(dbg, "debugger-statements.html", 8);
|
||||
|
||||
yield pressResume(dbg);
|
||||
assertPausedLocation(dbg, "debugger-statements.html", 12);
|
||||
|
||||
yield pressStepIn(dbg);
|
||||
assertPausedLocation(dbg, "debugger-statements.html", 13);
|
||||
|
||||
yield pressStepOut(dbg);
|
||||
assertPausedLocation(dbg, "debugger-statements.html", 14);
|
||||
|
||||
yield pressStepOver(dbg);
|
||||
assertPausedLocation(dbg, "debugger-statements.html", 9);
|
||||
});
|
|
@ -95,28 +95,54 @@ function waitForState(dbg, predicate) {
|
|||
});
|
||||
}
|
||||
|
||||
function waitForMs(time) {
|
||||
return new Promise(resolve => setTimeout(resolve, time));
|
||||
function waitForSources(dbg, ...sources) {
|
||||
if(sources.length === 0) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
info("Waiting on sources: " + sources.join(", "));
|
||||
const {selectors: {getSources}, store} = dbg;
|
||||
return Promise.all(sources.map(url => {
|
||||
function sourceExists(state) {
|
||||
return getSources(state).some(s => s.get("url").includes(url));
|
||||
}
|
||||
|
||||
if(!sourceExists(store.getState())) {
|
||||
return waitForState(dbg, sourceExists);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
function assertPausedLocation(dbg, source, line) {
|
||||
const { selectors: { getSelectedSource, getPause }, getState } = dbg;
|
||||
source = findSource(dbg, source);
|
||||
|
||||
// support passing in a partial url and fetching the source
|
||||
if (typeof source == "string") {
|
||||
source = findSource(dbg, source);
|
||||
}
|
||||
|
||||
// check the selected source
|
||||
// Check the selected source
|
||||
is(getSelectedSource(getState()).get("url"), source.url);
|
||||
|
||||
// check the pause location
|
||||
// Check the pause location
|
||||
const location = getPause(getState()).getIn(["frame", "location"]);
|
||||
is(location.get("sourceId"), source.id);
|
||||
is(location.get("line"), line);
|
||||
|
||||
// check the debug line
|
||||
// Check the debug line
|
||||
ok(dbg.win.cm.lineInfo(line - 1).wrapClass.includes("debug-line"),
|
||||
"Line is highlighted as paused");
|
||||
}
|
||||
|
||||
function assertHighlightLocation(dbg, source, line) {
|
||||
const { selectors: { getSelectedSource, getPause }, getState } = dbg;
|
||||
source = findSource(dbg, source);
|
||||
|
||||
// Check the selected source
|
||||
is(getSelectedSource(getState()).get("url"), source.url);
|
||||
|
||||
// Check the highlight line
|
||||
const lineEl = findElement(dbg, "highlightLine");
|
||||
ok(lineEl, "Line is highlighted");
|
||||
ok(isVisibleWithin(findElement(dbg, "codeMirror"), lineEl),
|
||||
"Highlighted line is visible");
|
||||
ok(dbg.win.cm.lineInfo(line - 1).wrapClass.includes("highlight-line"),
|
||||
"Line is highlighted");
|
||||
}
|
||||
|
||||
|
@ -125,11 +151,11 @@ function isPaused(dbg) {
|
|||
return !!getPause(getState());
|
||||
}
|
||||
|
||||
const waitForPaused = Task.async(function* (dbg) {
|
||||
// We want to make sure that we get both a real paused event and
|
||||
// that the state is fully populated. The client may do some more
|
||||
// work (call other client methods) before populating the state.
|
||||
return Promise.all([
|
||||
function waitForPaused(dbg) {
|
||||
return Task.spawn(function* () {
|
||||
// We want to make sure that we get both a real paused event and
|
||||
// that the state is fully populated. The client may do some more
|
||||
// work (call other client methods) before populating the state.
|
||||
yield waitForThreadEvents(dbg, "paused"),
|
||||
yield waitForState(dbg, state => {
|
||||
const pause = dbg.selectors.getPause(state);
|
||||
|
@ -142,42 +168,32 @@ const waitForPaused = Task.async(function* (dbg) {
|
|||
const sourceId = pause.getIn(["frame", "location", "sourceId"]);
|
||||
const sourceText = dbg.selectors.getSourceText(dbg.getState(), sourceId);
|
||||
return sourceText && !sourceText.get("loading");
|
||||
})
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const initDebugger = Task.async(function* (url, ...sources) {
|
||||
const toolbox = yield openNewTabAndToolbox(EXAMPLE_URL + url, "jsdebugger");
|
||||
const win = toolbox.getPanel("jsdebugger").panelWin;
|
||||
const store = win.Debugger.store;
|
||||
const { getSources } = win.Debugger.selectors;
|
||||
function initDebugger(url, ...sources) {
|
||||
return Task.spawn(function* () {
|
||||
const toolbox = yield openNewTabAndToolbox(EXAMPLE_URL + url, "jsdebugger");
|
||||
const win = toolbox.getPanel("jsdebugger").panelWin;
|
||||
const store = win.Debugger.store;
|
||||
const { getSources } = win.Debugger.selectors;
|
||||
|
||||
const dbg = {
|
||||
actions: win.Debugger.actions,
|
||||
selectors: win.Debugger.selectors,
|
||||
getState: store.getState,
|
||||
store: store,
|
||||
client: win.Debugger.client,
|
||||
toolbox: toolbox,
|
||||
win: win
|
||||
};
|
||||
const dbg = {
|
||||
actions: win.Debugger.actions,
|
||||
selectors: win.Debugger.selectors,
|
||||
getState: store.getState,
|
||||
store: store,
|
||||
client: win.Debugger.client,
|
||||
toolbox: toolbox,
|
||||
win: win
|
||||
};
|
||||
|
||||
if(sources.length) {
|
||||
// TODO: Extract this out to a utility function
|
||||
info("Waiting on sources: " + sources.join(", "));
|
||||
yield Promise.all(sources.map(url => {
|
||||
function sourceExists(state) {
|
||||
return getSources(state).some(s => s.get("url").includes(url));
|
||||
}
|
||||
yield waitForSources(dbg, ...sources);
|
||||
|
||||
if(!sourceExists(store.getState())) {
|
||||
return waitForState(dbg, sourceExists);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
return dbg;
|
||||
});
|
||||
return dbg;
|
||||
});
|
||||
};
|
||||
|
||||
window.resumeTest = undefined;
|
||||
function pauseTest() {
|
||||
|
@ -188,6 +204,13 @@ function pauseTest() {
|
|||
// Actions
|
||||
|
||||
function findSource(dbg, url) {
|
||||
if(typeof url !== "string") {
|
||||
// Support passing in a source object itelf all APIs that use this
|
||||
// function support both styles
|
||||
const source = url;
|
||||
return source;
|
||||
}
|
||||
|
||||
const sources = dbg.selectors.getSources(dbg.getState());
|
||||
const source = sources.find(s => s.get("url").includes(url));
|
||||
|
||||
|
@ -198,12 +221,15 @@ function findSource(dbg, url) {
|
|||
return source.toJS();
|
||||
}
|
||||
|
||||
function selectSource(dbg, url) {
|
||||
function selectSource(dbg, url, line) {
|
||||
info("Selecting source: " + url);
|
||||
const source = findSource(dbg, url);
|
||||
dbg.actions.selectSource(source.id);
|
||||
const hasText = !!dbg.selectors.getSourceText(dbg.getState(), source.id);
|
||||
dbg.actions.selectSource(source.id, { line });
|
||||
|
||||
return waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
|
||||
if(!hasText) {
|
||||
return waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
|
||||
}
|
||||
}
|
||||
|
||||
function stepOver(dbg) {
|
||||
|
@ -234,10 +260,21 @@ function reload(dbg) {
|
|||
return dbg.client.reload();
|
||||
}
|
||||
|
||||
function addBreakpoint(dbg, sourceId, line, col) {
|
||||
function navigate(dbg, url, ...sources) {
|
||||
dbg.client.navigate(url);
|
||||
return waitForSources(dbg, ...sources)
|
||||
}
|
||||
|
||||
function addBreakpoint(dbg, source, line, col) {
|
||||
source = findSource(dbg, source);
|
||||
const sourceId = source.id;
|
||||
return dbg.actions.addBreakpoint({ sourceId, line, col });
|
||||
}
|
||||
|
||||
function removeBreakpoint(dbg, sourceId, line, col) {
|
||||
return dbg.actions.removeBreakpoint({ sourceId, line, col });
|
||||
}
|
||||
|
||||
function togglePauseOnExceptions(dbg,
|
||||
pauseOnExceptions, ignoreCaughtExceptions) {
|
||||
|
||||
|
@ -256,11 +293,30 @@ function togglePauseOnExceptions(dbg,
|
|||
// Helpers
|
||||
// invoke a global function in the debugged tab
|
||||
function invokeInTab(fnc) {
|
||||
info(`Invoking function ${fnc} in tab`);
|
||||
return ContentTask.spawn(gBrowser.selectedBrowser, fnc, function* (fnc) {
|
||||
content.wrappedJSObject[fnc](); // eslint-disable-line mozilla/no-cpows-in-tests, max-len
|
||||
});
|
||||
}
|
||||
|
||||
const isLinux = Services.appinfo.OS === "Linux";
|
||||
const keyMappings = {
|
||||
pauseKey: { code: "VK_F8" },
|
||||
resumeKey: { code: "VK_F8" },
|
||||
stepOverKey: { code: "VK_F10" },
|
||||
stepInKey: { code: "VK_F11", modifiers: { ctrlKey: isLinux } },
|
||||
stepOutKey: { code: "VK_F11", modifiers: { ctrlKey: isLinux, shiftKey: true } }
|
||||
};
|
||||
|
||||
function pressKey(dbg, keyName) {
|
||||
let keyEvent = keyMappings[keyName];
|
||||
const { code, modifiers } = keyEvent;
|
||||
return EventUtils.synthesizeKey(
|
||||
code,
|
||||
modifiers || {},
|
||||
dbg.win
|
||||
);
|
||||
}
|
||||
|
||||
function isVisibleWithin(outerEl, innerEl) {
|
||||
const innerRect = innerEl.getBoundingClientRect();
|
||||
|
@ -275,12 +331,13 @@ const selectors = {
|
|||
gutter: i => `.CodeMirror-code *:nth-child(${i}) .CodeMirror-linenumber`,
|
||||
pauseOnExceptions: ".pause-exceptions",
|
||||
breakpoint: ".CodeMirror-code > .new-breakpoint",
|
||||
highlightLine: ".CodeMirror-code > .highlight-line",
|
||||
codeMirror: ".CodeMirror",
|
||||
resume: ".resume.active",
|
||||
stepOver: ".stepOver.active",
|
||||
stepOut: ".stepOut.active",
|
||||
stepIn: ".stepIn.active"
|
||||
}
|
||||
};
|
||||
|
||||
function getSelector(elementName, ...args) {
|
||||
let selector = selectors[elementName];
|
||||
|
@ -300,6 +357,11 @@ function findElement(dbg, elementName, ...args) {
|
|||
return dbg.win.document.querySelector(selector);
|
||||
}
|
||||
|
||||
function findAllElements(dbg, elementName, ...args) {
|
||||
const selector = getSelector(elementName, ...args);
|
||||
return dbg.win.document.querySelectorAll(selector);
|
||||
}
|
||||
|
||||
// click an element in the debugger
|
||||
function clickElement(dbg, elementName, ...args) {
|
||||
const selector = getSelector(elementName, ...args);
|
||||
|
|
Загрузка…
Ссылка в новой задаче