зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1460371
- Update Debugger Frontend v51 r=jdescottes
--HG-- rename : devtools/client/debugger/new/debugger.css => devtools/client/debugger/new/dist/debugger.css rename : devtools/client/debugger/new/parser-worker.js => devtools/client/debugger/new/dist/parser-worker.js rename : devtools/client/debugger/new/pretty-print-worker.js => devtools/client/debugger/new/dist/pretty-print-worker.js rename : devtools/client/debugger/new/search-worker.js => devtools/client/debugger/new/dist/search-worker.js
This commit is contained in:
Родитель
f86cc21a3b
Коммит
40117fd237
|
@ -14,7 +14,7 @@ let whitelist = [
|
|||
{sourceName: /codemirror\.css$/i,
|
||||
isFromDevTools: true},
|
||||
// The debugger uses cross-browser CSS.
|
||||
{sourceName: /devtools\/client\/debugger\/new\/debugger.css/i,
|
||||
{sourceName: /devtools\/client\/debugger\/new\/dist\/debugger.css/i,
|
||||
isFromDevTools: true},
|
||||
// Reps uses cross-browser CSS.
|
||||
{sourceName: /devtools-client-shared\/components\/reps\/reps.css/i,
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,12 @@
|
|||
# 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/.
|
||||
|
||||
DevToolsModules(
|
||||
'debugger.css',
|
||||
'parser-worker.js',
|
||||
'pretty-print-worker.js',
|
||||
'search-worker.js',
|
||||
'vendors.js'
|
||||
)
|
|
@ -0,0 +1,466 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
.split-box {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.split-box.vert {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.split-box.horz {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.split-box > .uncontrolled {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.split-box > .controlled {
|
||||
display: flex;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.split-box > .splitter {
|
||||
background-image: none;
|
||||
border: 0;
|
||||
border-style: solid;
|
||||
border-color: transparent;
|
||||
background-color: var(--theme-splitter-color);
|
||||
background-clip: content-box;
|
||||
position: relative;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
/* Positive z-index positions the splitter on top of its siblings and makes
|
||||
it clickable on both sides. */
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.split-box.vert > .splitter {
|
||||
min-width: calc(var(--devtools-splitter-inline-start-width) +
|
||||
var(--devtools-splitter-inline-end-width) + 1px);
|
||||
|
||||
border-left-width: var(--devtools-splitter-inline-start-width);
|
||||
border-right-width: var(--devtools-splitter-inline-end-width);
|
||||
|
||||
margin-left: calc(-1 * var(--devtools-splitter-inline-start-width) - 1px);
|
||||
margin-right: calc(-1 * var(--devtools-splitter-inline-end-width));
|
||||
|
||||
cursor: ew-resize;
|
||||
}
|
||||
|
||||
.split-box.horz > .splitter {
|
||||
min-height: calc(var(--devtools-splitter-top-width) +
|
||||
var(--devtools-splitter-bottom-width) + 1px);
|
||||
|
||||
border-top-width: var(--devtools-splitter-top-width);
|
||||
border-bottom-width: var(--devtools-splitter-bottom-width);
|
||||
|
||||
margin-top: calc(-1 * var(--devtools-splitter-top-width) - 1px);
|
||||
margin-bottom: calc(-1 * var(--devtools-splitter-bottom-width));
|
||||
|
||||
cursor: ns-resize;
|
||||
}
|
||||
|
||||
.split-box.disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure splitter panels are not processing any mouse
|
||||
* events. This is good for performance during splitter
|
||||
* bar dragging.
|
||||
*/
|
||||
.split-box.dragging > .controlled,
|
||||
.split-box.dragging > .uncontrolled {
|
||||
pointer-events: none;
|
||||
}
|
||||
/* 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/>. */
|
||||
|
||||
.arrow,
|
||||
.worker,
|
||||
.refresh,
|
||||
.shortcut,
|
||||
.add-button {
|
||||
fill: var(--theme-splitter-color);
|
||||
}
|
||||
|
||||
.folder,
|
||||
.domain,
|
||||
.source-icon,
|
||||
.file,
|
||||
.extension {
|
||||
background-color: var(--theme-comment);
|
||||
}
|
||||
|
||||
.worker,
|
||||
.file,
|
||||
.folder,
|
||||
.source-icon,
|
||||
.extension {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.domain,
|
||||
.worker,
|
||||
.refresh,
|
||||
.add-button {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
.worker svg,
|
||||
.refresh svg,
|
||||
.shortcut svg,
|
||||
.add-button svg {
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
img.domain,
|
||||
img.folder,
|
||||
img.source-icon {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
img.extension {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
margin-inline-start: 2px;
|
||||
}
|
||||
|
||||
img.result-item-icon {
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
img.domain {
|
||||
mask: url("chrome://devtools/skin/images/debugger/domain.svg") no-repeat;
|
||||
}
|
||||
|
||||
img.folder {
|
||||
mask: url("chrome://devtools/skin/images/debugger/folder.svg") no-repeat;
|
||||
}
|
||||
|
||||
img.coffeescript {
|
||||
mask: url("chrome://devtools/skin/images/debugger/coffeescript.svg") no-repeat;
|
||||
}
|
||||
|
||||
img.javascript {
|
||||
mask: url("chrome://devtools/skin/images/debugger/javascript.svg") no-repeat;
|
||||
}
|
||||
|
||||
img.tab {
|
||||
mask: url("chrome://devtools/skin/images/debugger/tab.svg") no-repeat;
|
||||
}
|
||||
|
||||
img.react {
|
||||
mask: url("chrome://devtools/skin/images/debugger/react.svg") no-repeat;
|
||||
}
|
||||
|
||||
img.typescript {
|
||||
mask: url("chrome://devtools/skin/images/debugger/typescript.svg") no-repeat;
|
||||
}
|
||||
|
||||
img.extension {
|
||||
mask: url("chrome://devtools/skin/images/debugger/extension.svg") no-repeat;
|
||||
}
|
||||
|
||||
img.file {
|
||||
mask: url("chrome://devtools/skin/images/debugger/file.svg") no-repeat;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
img.domain,
|
||||
img.folder,
|
||||
img.file,
|
||||
img.source-icon,
|
||||
img.extension {
|
||||
mask-size: 100%;
|
||||
margin-inline-end: 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
img.result-item-icon {
|
||||
mask-size: 100%;
|
||||
margin-inline-end: 15px;
|
||||
margin-inline-start: 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.refresh svg,
|
||||
.shortcut svg,
|
||||
.worker svg {
|
||||
margin-inline-end: 5px;
|
||||
}
|
||||
|
||||
img.arrow {
|
||||
mask: url("chrome://devtools/skin/images/debugger/arrow.svg");
|
||||
margin-inline-end: 5px;
|
||||
margin-top: 3px;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
padding-top: 9px;
|
||||
background: var(--disclosure-arrow);
|
||||
mask-size: 100%;
|
||||
display: inline-block;
|
||||
margin-bottom: 1px;
|
||||
transform: rotate(-90deg);
|
||||
transition: transform 0.18s ease;
|
||||
}
|
||||
|
||||
html[dir="ltr"] img.arrow {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
html[dir="rtl"] img.arrow {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.arrow svg {
|
||||
transition: transform 0.125s ease;
|
||||
width: 10px;
|
||||
margin-inline-end: 5px;
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
html[dir="rtl"] .arrow svg,
|
||||
.arrow svg:dir(rtl),
|
||||
.arrow svg:-moz-locale-dir(rtl) {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.arrow.expanded.expanded svg {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.arrow.hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.webpack svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-right: 5px;
|
||||
vertical-align: sub;
|
||||
}
|
||||
|
||||
.function svg {
|
||||
height: 10px;
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.function path {
|
||||
fill: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.angular svg,
|
||||
.source-icon svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-right: 5px;
|
||||
vertical-align: sub;
|
||||
}
|
||||
|
||||
.angular,
|
||||
.webpack {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.theme-dark .angular,
|
||||
.theme-dark .webpack {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.source-icon svg {
|
||||
fill: var(--theme-comment);
|
||||
}
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.tree {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tree.inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tree.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tree.noselect {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tree .tree-node {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tree .tree-node:not(.focused):hover {
|
||||
background-color: var(--theme-selection-background-hover);
|
||||
}
|
||||
|
||||
.tree-indent {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
margin-inline-start: 5px;
|
||||
border-inline-start: 1px solid #A2D1FF;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Align with expandables siblings (where we have the arrow) */
|
||||
.tree-node[data-expandable="false"] .tree-indent:last-of-type {
|
||||
margin-inline-end: 15px;
|
||||
}
|
||||
|
||||
/* For non expandable root nodes, we don't have .tree-indent elements, so we declare
|
||||
the margin on the start of the node */
|
||||
.tree-node[data-expandable="false"][aria-level="1"] {
|
||||
padding-inline-start: 15px
|
||||
}
|
||||
|
||||
.tree .tree-node[data-expandable="true"] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.tree-node img.arrow {
|
||||
mask: url("chrome://devtools/skin/images/devtools-components/arrow.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
margin-inline-start: 1px;
|
||||
margin-inline-end: 4px;
|
||||
background-color: var(--theme-splitter-color, #9B9B9B);
|
||||
transform: rotate(-90deg);
|
||||
transition: transform 0.125s ease;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .tree-node img.arrow {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.tree-node img.arrow.expanded.expanded {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.tree .tree-node.focused {
|
||||
color: white;
|
||||
background-color: var(--theme-selection-background, #0a84ff);
|
||||
}
|
||||
|
||||
.tree-node.focused img.arrow {
|
||||
background-color: currentColor;
|
||||
}
|
||||
/* 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/. */
|
||||
|
||||
menu {
|
||||
display: inline;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
menu > menuitem::after {
|
||||
content: "\25BA";
|
||||
float: right;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
menu > menupopup {
|
||||
display: none;
|
||||
}
|
||||
|
||||
menu > menuitem:hover + menupopup,
|
||||
menu > menupopup:hover {
|
||||
display: block;
|
||||
}
|
||||
|
||||
menupopup {
|
||||
position: fixed;
|
||||
z-index: 10000;
|
||||
background: white;
|
||||
border: 1px solid #cccccc;
|
||||
padding: 5px 0;
|
||||
background: #f2f2f2;
|
||||
border-radius: 5px;
|
||||
color: #585858;
|
||||
box-shadow: 0 0 4px 0 rgba(190, 190, 190, 0.8);
|
||||
min-width: 130px;
|
||||
}
|
||||
|
||||
menuitem {
|
||||
display: block;
|
||||
padding: 0 20px;
|
||||
line-height: 20px;
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
menuitem:hover {
|
||||
background: #3780fb;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
menuitem[disabled=true] {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
menuitem[disabled=true]:hover {
|
||||
background-color: transparent;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
menuitem[type=checkbox]::before {
|
||||
content: "";
|
||||
width: 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
menuitem[type=checkbox][checked=true]::before {
|
||||
content: "\2713";
|
||||
left: -8px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
menuseparator {
|
||||
border-bottom: 1px solid #cacdd3;
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#contextmenu-mask.show {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 999;
|
||||
}
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -3,29 +3,25 @@
|
|||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<!DOCTYPE html>
|
||||
<html dir="">
|
||||
<head>
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="chrome://devtools/content/sourceeditor/codemirror/lib/codemirror.css" />
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="chrome://devtools/content/sourceeditor/codemirror/addon/dialog/dialog.css" />
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="chrome://devtools/content/sourceeditor/codemirror/mozilla.css" />
|
||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/debugger/new/debugger.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="mount"></div>
|
||||
<script type="application/javascript"
|
||||
src="chrome://devtools/content/shared/theme-switching.js"></script>
|
||||
<script type="text/javascript">
|
||||
const { BrowserLoader } = ChromeUtils.import("resource://devtools/client/shared/browser-loader.js", {});
|
||||
const { require } = BrowserLoader({
|
||||
baseURI: "resource://devtools/client/debugger/new/",
|
||||
window,
|
||||
});
|
||||
Debugger = require("devtools/client/debugger/new/debugger");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://devtools/content/sourceeditor/codemirror/lib/codemirror.css" />
|
||||
<link rel="stylesheet" type="text/css" href="chrome://devtools/content/sourceeditor/codemirror/addon/dialog/dialog.css" />
|
||||
<link rel="stylesheet" type="text/css" href="chrome://devtools/content/sourceeditor/codemirror/mozilla.css" />
|
||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/debugger/new/dist/debugger.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="mount"></div>
|
||||
<script type="application/javascript" src="chrome://devtools/content/shared/theme-switching.js"></script>
|
||||
<script type="text/javascript">
|
||||
const { BrowserLoader } = ChromeUtils.import("resource://devtools/client/shared/browser-loader.js", {});
|
||||
const { require } = BrowserLoader({
|
||||
baseURI: "resource://devtools/client/debugger/new",
|
||||
window,
|
||||
});
|
||||
Debugger = require("devtools/client/debugger/new/src/main");
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -3,11 +3,11 @@
|
|||
# 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 += [
|
||||
'dist',
|
||||
'src',
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'debugger.css',
|
||||
'debugger.js',
|
||||
'panel.js',
|
||||
'parser-worker.js',
|
||||
'pretty-print-worker.js',
|
||||
'search-worker.js',
|
||||
)
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.setSourceMetaData = setSourceMetaData;
|
||||
exports.setSymbols = setSymbols;
|
||||
exports.setOutOfScopeLocations = setOutOfScopeLocations;
|
||||
exports.setPausePoints = setPausePoints;
|
||||
|
||||
var _selectors = require("../selectors/index");
|
||||
|
||||
var _pause = require("./pause/index");
|
||||
|
||||
var _setInScopeLines = require("./ast/setInScopeLines");
|
||||
|
||||
var _parser = require("../workers/parser/index");
|
||||
|
||||
var _promise = require("./utils/middleware/promise");
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _prefs = require("../utils/prefs");
|
||||
|
||||
/* 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 setSourceMetaData(sourceId) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const source = (0, _selectors.getSource)(getState(), sourceId);
|
||||
|
||||
if (!source || !source.text || source.isWasm) {
|
||||
return;
|
||||
}
|
||||
|
||||
const framework = await (0, _parser.getFramework)(source.id);
|
||||
dispatch({
|
||||
type: "SET_SOURCE_METADATA",
|
||||
sourceId: source.id,
|
||||
sourceMetaData: {
|
||||
framework
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function setSymbols(sourceId) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const source = (0, _selectors.getSource)(getState(), sourceId);
|
||||
|
||||
if (!source || !source.text || source.isWasm || (0, _selectors.hasSymbols)(getState(), source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await dispatch({
|
||||
type: "SET_SYMBOLS",
|
||||
sourceId,
|
||||
[_promise.PROMISE]: (0, _parser.getSymbols)(sourceId)
|
||||
});
|
||||
|
||||
if ((0, _selectors.isPaused)(getState())) {
|
||||
await dispatch((0, _pause.fetchExtra)());
|
||||
await dispatch((0, _pause.mapFrames)());
|
||||
}
|
||||
|
||||
await dispatch(setPausePoints(sourceId));
|
||||
await dispatch(setSourceMetaData(sourceId));
|
||||
};
|
||||
}
|
||||
|
||||
function setOutOfScopeLocations() {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const location = (0, _selectors.getSelectedLocation)(getState());
|
||||
|
||||
if (!location) {
|
||||
return;
|
||||
}
|
||||
|
||||
const source = (0, _selectors.getSource)(getState(), location.sourceId);
|
||||
let locations = null;
|
||||
|
||||
if (location.line && source && (0, _selectors.isPaused)(getState())) {
|
||||
locations = await (0, _parser.findOutOfScopeLocations)(source.get("id"), location);
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: "OUT_OF_SCOPE_LOCATIONS",
|
||||
locations
|
||||
});
|
||||
dispatch((0, _setInScopeLines.setInScopeLines)());
|
||||
};
|
||||
}
|
||||
|
||||
function setPausePoints(sourceId) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) => {
|
||||
const source = (0, _selectors.getSource)(getState(), sourceId);
|
||||
|
||||
if (!_prefs.features.pausePoints || !source || !source.text || source.isWasm) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pausePoints = await (0, _parser.getPausePoints)(source.id);
|
||||
|
||||
if ((0, _devtoolsSourceMap.isGeneratedId)(source.id)) {
|
||||
await client.setPausePoints(source.id, pausePoints);
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: "SET_PAUSE_POINTS",
|
||||
source: source.toJS(),
|
||||
pausePoints
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
# 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(
|
||||
'setInScopeLines.js',
|
||||
)
|
|
@ -0,0 +1,46 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.setInScopeLines = setInScopeLines;
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
/* 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 getOutOfScopeLines(outOfScopeLocations) {
|
||||
if (!outOfScopeLocations) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (0, _lodash.uniq)((0, _lodash.flatMap)(outOfScopeLocations, location => (0, _lodash.range)(location.start.line, location.end.line)));
|
||||
}
|
||||
|
||||
function setInScopeLines() {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const sourceRecord = (0, _selectors.getSelectedSource)(getState());
|
||||
const outOfScopeLocations = (0, _selectors.getOutOfScopeLocations)(getState());
|
||||
|
||||
if (!sourceRecord || !sourceRecord.text) {
|
||||
return;
|
||||
}
|
||||
|
||||
const linesOutOfScope = getOutOfScopeLines(outOfScopeLocations);
|
||||
const sourceNumLines = (0, _source.getSourceLineCount)(sourceRecord);
|
||||
const sourceLines = (0, _lodash.range)(1, sourceNumLines + 1);
|
||||
const inScopeLines = !linesOutOfScope ? sourceLines : (0, _lodash.without)(sourceLines, ...linesOutOfScope);
|
||||
dispatch({
|
||||
type: "IN_SCOPE_LINES",
|
||||
lines: inScopeLines
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,497 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.syncBreakpoint = syncBreakpoint;
|
||||
exports.addBreakpoint = addBreakpoint;
|
||||
exports.addHiddenBreakpoint = addHiddenBreakpoint;
|
||||
exports.removeBreakpoint = removeBreakpoint;
|
||||
exports.enableBreakpoint = enableBreakpoint;
|
||||
exports.disableBreakpoint = disableBreakpoint;
|
||||
exports.toggleAllBreakpoints = toggleAllBreakpoints;
|
||||
exports.toggleBreakpoints = toggleBreakpoints;
|
||||
exports.removeAllBreakpoints = removeAllBreakpoints;
|
||||
exports.removeBreakpoints = removeBreakpoints;
|
||||
exports.remapBreakpoints = remapBreakpoints;
|
||||
exports.setBreakpointCondition = setBreakpointCondition;
|
||||
exports.toggleBreakpoint = toggleBreakpoint;
|
||||
exports.addOrToggleDisabledBreakpoint = addOrToggleDisabledBreakpoint;
|
||||
exports.toggleDisabledBreakpoint = toggleDisabledBreakpoint;
|
||||
|
||||
var _promise = require("./utils/middleware/promise");
|
||||
|
||||
var _selectors = require("../selectors/index");
|
||||
|
||||
var _breakpoint = require("../utils/breakpoint/index");
|
||||
|
||||
var _addBreakpoint = require("./breakpoints/addBreakpoint");
|
||||
|
||||
var _addBreakpoint2 = _interopRequireDefault(_addBreakpoint);
|
||||
|
||||
var _remapLocations = require("./breakpoints/remapLocations");
|
||||
|
||||
var _remapLocations2 = _interopRequireDefault(_remapLocations);
|
||||
|
||||
var _ast = require("../reducers/ast");
|
||||
|
||||
var _syncBreakpoint = require("./breakpoints/syncBreakpoint");
|
||||
|
||||
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; }
|
||||
|
||||
/**
|
||||
* Syncing a breakpoint add breakpoint information that is stored, and
|
||||
* contact the server for more data.
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
* @param {String} $1.sourceId String value
|
||||
* @param {PendingBreakpoint} $1.location PendingBreakpoint value
|
||||
*/
|
||||
function syncBreakpoint(sourceId, pendingBreakpoint) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) => {
|
||||
const {
|
||||
breakpoint,
|
||||
previousLocation
|
||||
} = await (0, _syncBreakpoint.syncClientBreakpoint)(getState, client, sourceMaps, sourceId, pendingBreakpoint);
|
||||
return dispatch({
|
||||
type: "SYNC_BREAKPOINT",
|
||||
breakpoint,
|
||||
previousLocation
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Add a new breakpoint
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
* @param {String} $1.condition Conditional breakpoint condition value
|
||||
* @param {Boolean} $1.disabled Disable value for breakpoint value
|
||||
*/
|
||||
|
||||
|
||||
function addBreakpoint(location, {
|
||||
condition,
|
||||
hidden
|
||||
} = {}) {
|
||||
const breakpoint = (0, _breakpoint.createBreakpoint)(location, {
|
||||
condition,
|
||||
hidden
|
||||
});
|
||||
return ({
|
||||
dispatch,
|
||||
getState,
|
||||
sourceMaps,
|
||||
client
|
||||
}) => {
|
||||
return dispatch({
|
||||
type: "ADD_BREAKPOINT",
|
||||
breakpoint,
|
||||
[_promise.PROMISE]: (0, _addBreakpoint2.default)(getState, client, sourceMaps, breakpoint)
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Add a new hidden breakpoint
|
||||
*
|
||||
* @memberOf actions/breakpoints
|
||||
* @param location
|
||||
* @return {function(ThunkArgs)}
|
||||
*/
|
||||
|
||||
|
||||
function addHiddenBreakpoint(location) {
|
||||
return ({
|
||||
dispatch
|
||||
}) => {
|
||||
return dispatch(addBreakpoint(location, {
|
||||
hidden: true
|
||||
}));
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Remove a single breakpoint
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function removeBreakpoint(location) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) => {
|
||||
const bp = (0, _selectors.getBreakpoint)(getState(), location);
|
||||
|
||||
if (!bp || bp.loading) {
|
||||
return;
|
||||
} // If the breakpoint is already disabled, we don't need to communicate
|
||||
// with the server. We just need to dispatch an action
|
||||
// simulating a successful server request
|
||||
|
||||
|
||||
if (bp.disabled) {
|
||||
return dispatch({
|
||||
type: "REMOVE_BREAKPOINT",
|
||||
breakpoint: bp,
|
||||
status: "done"
|
||||
});
|
||||
}
|
||||
|
||||
return dispatch({
|
||||
type: "REMOVE_BREAKPOINT",
|
||||
breakpoint: bp,
|
||||
disabled: false,
|
||||
[_promise.PROMISE]: client.removeBreakpoint(bp.generatedLocation)
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Enabling a breakpoint
|
||||
* will reuse the existing breakpoint information that is stored.
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
* @param {Location} $1.location Location value
|
||||
*/
|
||||
|
||||
|
||||
function enableBreakpoint(location) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) => {
|
||||
const breakpoint = (0, _selectors.getBreakpoint)(getState(), location);
|
||||
|
||||
if (!breakpoint || breakpoint.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
return dispatch({
|
||||
type: "ENABLE_BREAKPOINT",
|
||||
breakpoint,
|
||||
[_promise.PROMISE]: (0, _addBreakpoint2.default)(getState, client, sourceMaps, breakpoint)
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Disable a single breakpoint
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function disableBreakpoint(location) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) => {
|
||||
const bp = (0, _selectors.getBreakpoint)(getState(), location);
|
||||
|
||||
if (!bp || bp.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
await client.removeBreakpoint(bp.generatedLocation);
|
||||
|
||||
const newBreakpoint = _objectSpread({}, bp, {
|
||||
disabled: true
|
||||
});
|
||||
|
||||
return dispatch({
|
||||
type: "DISABLE_BREAKPOINT",
|
||||
breakpoint: newBreakpoint
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Toggle All Breakpoints
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function toggleAllBreakpoints(shouldDisableBreakpoints) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) => {
|
||||
const breakpoints = (0, _selectors.getBreakpoints)(getState());
|
||||
const modifiedBreakpoints = [];
|
||||
|
||||
for (const [, breakpoint] of breakpoints) {
|
||||
if (shouldDisableBreakpoints) {
|
||||
await client.removeBreakpoint(breakpoint.generatedLocation);
|
||||
|
||||
const newBreakpoint = _objectSpread({}, breakpoint, {
|
||||
disabled: true
|
||||
});
|
||||
|
||||
modifiedBreakpoints.push(newBreakpoint);
|
||||
} else {
|
||||
const newBreakpoint = _objectSpread({}, breakpoint, {
|
||||
disabled: false
|
||||
});
|
||||
|
||||
modifiedBreakpoints.push(newBreakpoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldDisableBreakpoints) {
|
||||
return dispatch({
|
||||
type: "DISABLE_ALL_BREAKPOINTS",
|
||||
breakpoints: modifiedBreakpoints
|
||||
});
|
||||
}
|
||||
|
||||
return dispatch({
|
||||
type: "ENABLE_ALL_BREAKPOINTS",
|
||||
breakpoints: modifiedBreakpoints
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Toggle Breakpoints
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function toggleBreakpoints(shouldDisableBreakpoints, breakpoints) {
|
||||
return async ({
|
||||
dispatch
|
||||
}) => {
|
||||
for (const [, breakpoint] of breakpoints) {
|
||||
if (shouldDisableBreakpoints) {
|
||||
await dispatch(disableBreakpoint(breakpoint.location));
|
||||
} else {
|
||||
await dispatch(enableBreakpoint(breakpoint.location));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Removes all breakpoints
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function removeAllBreakpoints() {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const breakpoints = (0, _selectors.getBreakpoints)(getState());
|
||||
|
||||
for (const [, breakpoint] of breakpoints) {
|
||||
await dispatch(removeBreakpoint(breakpoint.location));
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Removes breakpoints
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function removeBreakpoints(breakpoints) {
|
||||
return async ({
|
||||
dispatch
|
||||
}) => {
|
||||
for (const [, breakpoint] of breakpoints) {
|
||||
await dispatch(removeBreakpoint(breakpoint.location));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function remapBreakpoints(sourceId) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
sourceMaps
|
||||
}) => {
|
||||
const breakpoints = (0, _selectors.getBreakpoints)(getState());
|
||||
const newBreakpoints = await (0, _remapLocations2.default)(breakpoints, sourceId, sourceMaps);
|
||||
return dispatch({
|
||||
type: "REMAP_BREAKPOINTS",
|
||||
breakpoints: newBreakpoints
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Update the condition of a breakpoint.
|
||||
*
|
||||
* @throws {Error} "not implemented"
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
* @param {Location} location
|
||||
* @see DebuggerController.Breakpoints.addBreakpoint
|
||||
* @param {string} condition
|
||||
* The condition to set on the breakpoint
|
||||
* @param {Boolean} $1.disabled Disable value for breakpoint value
|
||||
*/
|
||||
|
||||
|
||||
function setBreakpointCondition(location, {
|
||||
condition
|
||||
} = {}) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) => {
|
||||
const bp = (0, _selectors.getBreakpoint)(getState(), location);
|
||||
|
||||
if (!bp) {
|
||||
return dispatch(addBreakpoint(location, {
|
||||
condition
|
||||
}));
|
||||
}
|
||||
|
||||
if (bp.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bp.disabled) {
|
||||
await dispatch(enableBreakpoint(location));
|
||||
bp.disabled = !bp.disabled;
|
||||
}
|
||||
|
||||
await client.setBreakpointCondition(bp.id, location, condition, sourceMaps.isOriginalId(bp.location.sourceId));
|
||||
|
||||
const newBreakpoint = _objectSpread({}, bp, {
|
||||
condition
|
||||
});
|
||||
|
||||
(0, _breakpoint.assertBreakpoint)(newBreakpoint);
|
||||
return dispatch({
|
||||
type: "SET_BREAKPOINT_CONDITION",
|
||||
breakpoint: newBreakpoint
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function toggleBreakpoint(line, column) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) => {
|
||||
if (!line) {
|
||||
return;
|
||||
}
|
||||
|
||||
const state = getState();
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(state);
|
||||
const bp = (0, _selectors.getBreakpointAtLocation)(state, {
|
||||
line,
|
||||
column
|
||||
});
|
||||
const isEmptyLine = (0, _ast.isEmptyLineInSource)(state, line, selectedSource);
|
||||
|
||||
if (!bp && isEmptyLine || bp && bp.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bp) {
|
||||
// NOTE: it's possible the breakpoint has slid to a column
|
||||
return dispatch(removeBreakpoint({
|
||||
sourceId: bp.location.sourceId,
|
||||
sourceUrl: bp.location.sourceUrl,
|
||||
line: bp.location.line,
|
||||
column: column || bp.location.column
|
||||
}));
|
||||
}
|
||||
|
||||
return dispatch(addBreakpoint({
|
||||
sourceId: selectedSource.get("id"),
|
||||
sourceUrl: selectedSource.get("url"),
|
||||
line: line,
|
||||
column: column
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
function addOrToggleDisabledBreakpoint(line, column) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) => {
|
||||
if (!line) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(getState());
|
||||
const bp = (0, _selectors.getBreakpointAtLocation)(getState(), {
|
||||
line,
|
||||
column
|
||||
});
|
||||
|
||||
if (bp && bp.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bp) {
|
||||
// NOTE: it's possible the breakpoint has slid to a column
|
||||
return dispatch(toggleDisabledBreakpoint(line, column || bp.location.column));
|
||||
}
|
||||
|
||||
return dispatch(addBreakpoint({
|
||||
sourceId: selectedSource.get("id"),
|
||||
sourceUrl: selectedSource.get("url"),
|
||||
line: line,
|
||||
column: column
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
function toggleDisabledBreakpoint(line, column) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) => {
|
||||
const bp = (0, _selectors.getBreakpointAtLocation)(getState(), {
|
||||
line,
|
||||
column
|
||||
});
|
||||
|
||||
if (!bp || bp.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bp.disabled) {
|
||||
return dispatch(disableBreakpoint(bp.location));
|
||||
}
|
||||
|
||||
return dispatch(enableBreakpoint(bp.location));
|
||||
};
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = addBreakpoint;
|
||||
|
||||
var _breakpoint = require("../../utils/breakpoint/index");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _sourceMaps = require("../../utils/source-maps");
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
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 addBreakpoint(getState, client, sourceMaps, breakpoint) {
|
||||
const state = getState();
|
||||
const source = (0, _selectors.getSource)(state, breakpoint.location.sourceId);
|
||||
|
||||
const location = _objectSpread({}, breakpoint.location, {
|
||||
sourceUrl: source.url
|
||||
});
|
||||
|
||||
const generatedLocation = await (0, _sourceMaps.getGeneratedLocation)(state, source, location, sourceMaps);
|
||||
const generatedSource = (0, _selectors.getSource)(state, generatedLocation.sourceId);
|
||||
(0, _breakpoint.assertLocation)(location);
|
||||
(0, _breakpoint.assertLocation)(generatedLocation);
|
||||
|
||||
if ((0, _breakpoint.breakpointExists)(state, location)) {
|
||||
const newBreakpoint = _objectSpread({}, breakpoint, {
|
||||
location,
|
||||
generatedLocation
|
||||
});
|
||||
|
||||
(0, _breakpoint.assertBreakpoint)(newBreakpoint);
|
||||
return {
|
||||
breakpoint: newBreakpoint
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
id,
|
||||
hitCount,
|
||||
actualLocation
|
||||
} = await client.setBreakpoint(generatedLocation, breakpoint.condition, sourceMaps.isOriginalId(location.sourceId));
|
||||
const newGeneratedLocation = actualLocation || generatedLocation;
|
||||
const newLocation = await sourceMaps.getOriginalLocation(newGeneratedLocation);
|
||||
const symbols = (0, _selectors.getSymbols)(getState(), source);
|
||||
const astLocation = await (0, _breakpoint.getASTLocation)(source, symbols, newLocation);
|
||||
const originalText = (0, _source.getTextAtPosition)(source, location);
|
||||
const text = (0, _source.getTextAtPosition)(generatedSource, actualLocation);
|
||||
const newBreakpoint = {
|
||||
id,
|
||||
disabled: false,
|
||||
hidden: breakpoint.hidden,
|
||||
loading: false,
|
||||
condition: breakpoint.condition,
|
||||
location: newLocation,
|
||||
astLocation,
|
||||
hitCount,
|
||||
generatedLocation: newGeneratedLocation,
|
||||
text,
|
||||
originalText
|
||||
};
|
||||
(0, _breakpoint.assertBreakpoint)(newBreakpoint);
|
||||
const previousLocation = (0, _breakpoint.locationMoved)(location, newLocation) ? location : null;
|
||||
return {
|
||||
breakpoint: newBreakpoint,
|
||||
previousLocation
|
||||
};
|
||||
}
|
|
@ -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(
|
||||
'addBreakpoint.js',
|
||||
'remapLocations.js',
|
||||
'syncBreakpoint.js',
|
||||
)
|
|
@ -0,0 +1,27 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = remapLocations;
|
||||
|
||||
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; }
|
||||
|
||||
/* 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 remapLocations(breakpoints, sourceId, sourceMaps) {
|
||||
const sourceBreakpoints = breakpoints.map(async breakpoint => {
|
||||
if (breakpoint.location.sourceId !== sourceId) {
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
const location = await sourceMaps.getOriginalLocation(breakpoint.location);
|
||||
return _objectSpread({}, breakpoint, {
|
||||
location
|
||||
});
|
||||
});
|
||||
return Promise.all(sourceBreakpoints.valueSeq());
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.syncClientBreakpoint = syncClientBreakpoint;
|
||||
|
||||
var _breakpoint = require("../../utils/breakpoint/index");
|
||||
|
||||
var _sourceMaps = require("../../utils/source-maps");
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
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 makeScopedLocation({
|
||||
name,
|
||||
offset
|
||||
}, location, source) {
|
||||
const scope = await (0, _breakpoint.findScopeByName)(source, name); // fallback onto the location line, if the scope is not found
|
||||
// note: we may at some point want to delete the breakpoint if the scope
|
||||
// disappears
|
||||
|
||||
const line = scope ? scope.location.start.line + offset.line : location.line;
|
||||
return {
|
||||
line,
|
||||
column: location.column,
|
||||
sourceUrl: source.url,
|
||||
sourceId: source.id
|
||||
};
|
||||
}
|
||||
|
||||
function createSyncData(id, pendingBreakpoint, location, generatedLocation, previousLocation, text, originalText) {
|
||||
const overrides = _objectSpread({}, pendingBreakpoint, {
|
||||
generatedLocation,
|
||||
id,
|
||||
text,
|
||||
originalText
|
||||
});
|
||||
|
||||
const breakpoint = (0, _breakpoint.createBreakpoint)(location, overrides);
|
||||
(0, _breakpoint.assertBreakpoint)(breakpoint);
|
||||
return {
|
||||
breakpoint,
|
||||
previousLocation
|
||||
};
|
||||
} // we have three forms of syncing: disabled syncing, existing server syncing
|
||||
// and adding a new breakpoint
|
||||
|
||||
|
||||
async function syncClientBreakpoint(getState, client, sourceMaps, sourceId, pendingBreakpoint) {
|
||||
(0, _breakpoint.assertPendingBreakpoint)(pendingBreakpoint);
|
||||
const source = (0, _selectors.getSource)(getState(), sourceId);
|
||||
const generatedSourceId = sourceMaps.isOriginalId(sourceId) ? (0, _devtoolsSourceMap.originalToGeneratedId)(sourceId) : sourceId;
|
||||
const generatedSource = (0, _selectors.getSource)(getState(), generatedSourceId);
|
||||
const {
|
||||
location,
|
||||
astLocation
|
||||
} = pendingBreakpoint;
|
||||
|
||||
const previousLocation = _objectSpread({}, location, {
|
||||
sourceId
|
||||
});
|
||||
|
||||
const scopedLocation = await makeScopedLocation(astLocation, previousLocation, source);
|
||||
const scopedGeneratedLocation = await (0, _sourceMaps.getGeneratedLocation)(getState(), source, scopedLocation, sourceMaps); // this is the generatedLocation of the pending breakpoint, with
|
||||
// the source id updated to reflect the new connection
|
||||
|
||||
const generatedLocation = _objectSpread({}, pendingBreakpoint.generatedLocation, {
|
||||
sourceId: generatedSourceId
|
||||
});
|
||||
|
||||
const isSameLocation = !(0, _breakpoint.locationMoved)(generatedLocation, scopedGeneratedLocation);
|
||||
const existingClient = client.getBreakpointByLocation(generatedLocation);
|
||||
/** ******* CASE 1: No server change ***********/
|
||||
// early return if breakpoint is disabled or we are in the sameLocation
|
||||
// send update only to redux
|
||||
|
||||
if (pendingBreakpoint.disabled || existingClient && isSameLocation) {
|
||||
const id = pendingBreakpoint.disabled ? "" : existingClient.id;
|
||||
const originalText = (0, _source.getTextAtPosition)(source, previousLocation);
|
||||
const text = (0, _source.getTextAtPosition)(generatedSource, generatedLocation);
|
||||
return createSyncData(id, pendingBreakpoint, scopedLocation, scopedGeneratedLocation, previousLocation, text, originalText);
|
||||
} // clear server breakpoints if they exist and we have moved
|
||||
|
||||
|
||||
if (existingClient) {
|
||||
await client.removeBreakpoint(generatedLocation);
|
||||
}
|
||||
/** ******* Case 2: Add New Breakpoint ***********/
|
||||
// If we are not disabled, set the breakpoint on the server and get
|
||||
// that info so we can set it on our breakpoints.
|
||||
|
||||
|
||||
if (!scopedGeneratedLocation.line) {
|
||||
return {
|
||||
previousLocation,
|
||||
breakpoint: null
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
id,
|
||||
actualLocation
|
||||
} = await client.setBreakpoint(scopedGeneratedLocation, pendingBreakpoint.condition, sourceMaps.isOriginalId(sourceId)); // the breakpoint might have slid server side, so we want to get the location
|
||||
// based on the server's return value
|
||||
|
||||
const newGeneratedLocation = actualLocation;
|
||||
const newLocation = await sourceMaps.getOriginalLocation(newGeneratedLocation);
|
||||
const originalText = (0, _source.getTextAtPosition)(source, newLocation);
|
||||
const text = (0, _source.getTextAtPosition)(generatedSource, newGeneratedLocation);
|
||||
return createSyncData(id, pendingBreakpoint, newLocation, newGeneratedLocation, previousLocation, text, originalText);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.recordCoverage = recordCoverage;
|
||||
|
||||
/* 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 recordCoverage() {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) {
|
||||
const {
|
||||
coverage
|
||||
} = await client.recordCoverage();
|
||||
return dispatch({
|
||||
type: "RECORD_COVERAGE",
|
||||
value: {
|
||||
coverage
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.updateWorkers = updateWorkers;
|
||||
|
||||
/* 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 updateWorkers() {
|
||||
return async function ({
|
||||
dispatch,
|
||||
client
|
||||
}) {
|
||||
const {
|
||||
workers
|
||||
} = await client.fetchWorkers();
|
||||
dispatch({
|
||||
type: "SET_WORKERS",
|
||||
workers
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.fetchEventListeners = fetchEventListeners;
|
||||
exports.updateEventBreakpoints = updateEventBreakpoints;
|
||||
|
||||
var _DevToolsUtils = require("../utils/DevToolsUtils");
|
||||
|
||||
var _selectors = require("../selectors/index");
|
||||
|
||||
var _waitService = require("./utils/middleware/wait-service");
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/* global window gThreadClient setNamedTimeout EVENTS */
|
||||
|
||||
/* eslint no-shadow: 0 */
|
||||
|
||||
/**
|
||||
* Redux actions for the event listeners state
|
||||
* @module actions/event-listeners
|
||||
*/
|
||||
// delay is in ms
|
||||
const FETCH_EVENT_LISTENERS_DELAY = 200;
|
||||
let fetchListenersTimerID;
|
||||
/**
|
||||
* @memberof utils/utils
|
||||
* @static
|
||||
*/
|
||||
|
||||
async function asPaused(state, client, func) {
|
||||
if (!(0, _selectors.isPaused)(state)) {
|
||||
await client.interrupt();
|
||||
let result;
|
||||
|
||||
try {
|
||||
result = await func(client);
|
||||
} catch (e) {
|
||||
// Try to put the debugger back in a working state by resuming
|
||||
// it
|
||||
await client.resume();
|
||||
throw e;
|
||||
}
|
||||
|
||||
await client.resume();
|
||||
return result;
|
||||
}
|
||||
|
||||
return func(client);
|
||||
}
|
||||
/**
|
||||
* @memberof actions/event-listeners
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function fetchEventListeners() {
|
||||
return ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) => {
|
||||
// Make sure we"re not sending a batch of closely repeated requests.
|
||||
// This can easily happen whenever new sources are fetched.
|
||||
if (fetchListenersTimerID) {
|
||||
clearTimeout(fetchListenersTimerID);
|
||||
}
|
||||
|
||||
fetchListenersTimerID = setTimeout(() => {
|
||||
// In case there is still a request of listeners going on (it
|
||||
// takes several RDP round trips right now), make sure we wait
|
||||
// on a currently running request
|
||||
if (getState().eventListeners.fetchingListeners) {
|
||||
dispatch({
|
||||
type: _waitService.NAME,
|
||||
predicate: action => action.type === "FETCH_EVENT_LISTENERS" && action.status === "done",
|
||||
run: dispatch => dispatch(fetchEventListeners())
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: "FETCH_EVENT_LISTENERS",
|
||||
status: "begin"
|
||||
});
|
||||
asPaused(getState(), client, _getEventListeners).then(listeners => {
|
||||
dispatch({
|
||||
type: "FETCH_EVENT_LISTENERS",
|
||||
status: "done",
|
||||
listeners: formatListeners(getState(), listeners)
|
||||
});
|
||||
});
|
||||
}, FETCH_EVENT_LISTENERS_DELAY);
|
||||
};
|
||||
}
|
||||
|
||||
function formatListeners(state, listeners) {
|
||||
return listeners.map(l => {
|
||||
return {
|
||||
selector: l.node.selector,
|
||||
type: l.type,
|
||||
sourceId: (0, _selectors.getSourceByURL)(state, l.function.location.url).get("id"),
|
||||
line: l.function.location.line
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async function _getEventListeners(threadClient) {
|
||||
const response = await threadClient.eventListeners(); // Make sure all the listeners are sorted by the event type, since
|
||||
// they"re not guaranteed to be clustered together.
|
||||
|
||||
response.listeners.sort((a, b) => a.type > b.type ? 1 : -1); // Add all the listeners in the debugger view event linsteners container.
|
||||
|
||||
const fetchedDefinitions = new Map();
|
||||
const listeners = [];
|
||||
|
||||
for (const listener of response.listeners) {
|
||||
let definitionSite;
|
||||
|
||||
if (fetchedDefinitions.has(listener.function.actor)) {
|
||||
definitionSite = fetchedDefinitions.get(listener.function.actor);
|
||||
} else if (listener.function.class == "Function") {
|
||||
definitionSite = await _getDefinitionSite(threadClient, listener.function);
|
||||
|
||||
if (!definitionSite) {
|
||||
// We don"t know where this listener comes from so don"t show it in
|
||||
// the UI as breaking on it doesn"t work (bug 942899).
|
||||
continue;
|
||||
}
|
||||
|
||||
fetchedDefinitions.set(listener.function.actor, definitionSite);
|
||||
}
|
||||
|
||||
listener.function.url = definitionSite;
|
||||
listeners.push(listener);
|
||||
}
|
||||
|
||||
fetchedDefinitions.clear();
|
||||
return listeners;
|
||||
}
|
||||
|
||||
async function _getDefinitionSite(threadClient, func) {
|
||||
const grip = threadClient.pauseGrip(func);
|
||||
let response;
|
||||
|
||||
try {
|
||||
response = await grip.getDefinitionSite();
|
||||
} catch (e) {
|
||||
// Don't make this error fatal, it would break the entire events pane.
|
||||
(0, _DevToolsUtils.reportException)("_getDefinitionSite", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return response.source.url;
|
||||
}
|
||||
/**
|
||||
* @memberof actions/event-listeners
|
||||
* @static
|
||||
* @param {string} eventNames
|
||||
*/
|
||||
|
||||
|
||||
function updateEventBreakpoints(eventNames) {
|
||||
return dispatch => {
|
||||
setNamedTimeout("event-breakpoints-update", 0, () => {
|
||||
gThreadClient.pauseOnDOMEvents(eventNames, () => {
|
||||
// Notify that event breakpoints were added/removed on the server.
|
||||
window.emit(EVENTS.EVENT_BREAKPOINTS_UPDATED);
|
||||
dispatch({
|
||||
type: "UPDATE_EVENT_BREAKPOINTS",
|
||||
eventNames: eventNames
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.addExpression = addExpression;
|
||||
exports.autocomplete = autocomplete;
|
||||
exports.clearExpressionError = clearExpressionError;
|
||||
exports.updateExpression = updateExpression;
|
||||
exports.deleteExpression = deleteExpression;
|
||||
exports.evaluateExpressions = evaluateExpressions;
|
||||
exports.getMappedExpression = getMappedExpression;
|
||||
|
||||
var _selectors = require("../selectors/index");
|
||||
|
||||
var _promise = require("./utils/middleware/promise");
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _expressions = require("../utils/expressions");
|
||||
|
||||
var _parser = require("../workers/parser/index");
|
||||
|
||||
var parser = _interopRequireWildcard(_parser);
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/**
|
||||
* Add expression for debugger to watch
|
||||
*
|
||||
* @param {object} expression
|
||||
* @param {number} expression.id
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
*/
|
||||
function addExpression(input) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
const expressionError = await parser.hasSyntaxError(input);
|
||||
const expression = (0, _selectors.getExpression)(getState(), input);
|
||||
|
||||
if (expression) {
|
||||
return dispatch(evaluateExpression(expression));
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: "ADD_EXPRESSION",
|
||||
input,
|
||||
expressionError
|
||||
});
|
||||
const newExpression = (0, _selectors.getExpression)(getState(), input);
|
||||
|
||||
if (newExpression) {
|
||||
return dispatch(evaluateExpression(newExpression));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function autocomplete(input, cursor) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) => {
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
const frameId = (0, _selectors.getSelectedFrameId)(getState());
|
||||
const result = await client.autocomplete(input, cursor, frameId);
|
||||
await dispatch({
|
||||
type: "AUTOCOMPLETE",
|
||||
input,
|
||||
result
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function clearExpressionError() {
|
||||
return {
|
||||
type: "CLEAR_EXPRESSION_ERROR"
|
||||
};
|
||||
}
|
||||
|
||||
function updateExpression(input, expression) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
const expressionError = await parser.hasSyntaxError(input);
|
||||
dispatch({
|
||||
type: "UPDATE_EXPRESSION",
|
||||
expression,
|
||||
input: expressionError ? expression.input : input,
|
||||
expressionError
|
||||
});
|
||||
dispatch(evaluateExpressions());
|
||||
};
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {object} expression
|
||||
* @param {number} expression.id
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function deleteExpression(expression) {
|
||||
return ({
|
||||
dispatch
|
||||
}) => {
|
||||
dispatch({
|
||||
type: "DELETE_EXPRESSION",
|
||||
input: expression.input
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @memberof actions/pause
|
||||
* @param {number} selectedFrameId
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function evaluateExpressions() {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) {
|
||||
const expressions = (0, _selectors.getExpressions)(getState()).toJS();
|
||||
const inputs = expressions.map(({
|
||||
input
|
||||
}) => input);
|
||||
const frameId = (0, _selectors.getSelectedFrameId)(getState());
|
||||
const results = await client.evaluateExpressions(inputs, frameId);
|
||||
dispatch({
|
||||
type: "EVALUATE_EXPRESSIONS",
|
||||
inputs,
|
||||
results
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function evaluateExpression(expression) {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) {
|
||||
if (!expression.input) {
|
||||
console.warn("Expressions should not be empty");
|
||||
return;
|
||||
}
|
||||
|
||||
let input = expression.input;
|
||||
const frame = (0, _selectors.getSelectedFrame)(getState());
|
||||
|
||||
if (frame) {
|
||||
const {
|
||||
location
|
||||
} = frame;
|
||||
const source = (0, _selectors.getSource)(getState(), location.sourceId);
|
||||
const sourceId = source.get("id");
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(getState());
|
||||
|
||||
if (selectedSource && !(0, _devtoolsSourceMap.isGeneratedId)(sourceId) && !(0, _devtoolsSourceMap.isGeneratedId)(selectedSource.get("id"))) {
|
||||
input = await dispatch(getMappedExpression(input));
|
||||
}
|
||||
}
|
||||
|
||||
const frameId = (0, _selectors.getSelectedFrameId)(getState());
|
||||
return dispatch({
|
||||
type: "EVALUATE_EXPRESSION",
|
||||
input: expression.input,
|
||||
[_promise.PROMISE]: client.evaluateInFrame((0, _expressions.wrapExpression)(input), frameId)
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Gets information about original variable names from the source map
|
||||
* and replaces all posible generated names.
|
||||
*/
|
||||
|
||||
|
||||
function getMappedExpression(expression) {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) {
|
||||
const mappings = (0, _selectors.getSelectedScopeMappings)(getState());
|
||||
|
||||
if (!mappings) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
return parser.mapOriginalExpression(expression, mappings);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.doSearch = doSearch;
|
||||
exports.doSearchForHighlight = doSearchForHighlight;
|
||||
exports.setFileSearchQuery = setFileSearchQuery;
|
||||
exports.toggleFileSearchModifier = toggleFileSearchModifier;
|
||||
exports.updateSearchResults = updateSearchResults;
|
||||
exports.searchContents = searchContents;
|
||||
exports.searchContentsForHighlight = searchContentsForHighlight;
|
||||
exports.traverseResults = traverseResults;
|
||||
exports.closeFileSearch = closeFileSearch;
|
||||
|
||||
var _editor = require("../utils/editor/index");
|
||||
|
||||
var _search = require("../workers/search/index");
|
||||
|
||||
var _selectors = require("../selectors/index");
|
||||
|
||||
var _ui = require("./ui");
|
||||
|
||||
/* 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 doSearch(query, editor) {
|
||||
return ({
|
||||
getState,
|
||||
dispatch
|
||||
}) => {
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(getState());
|
||||
|
||||
if (!selectedSource || !selectedSource.text) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(setFileSearchQuery(query));
|
||||
dispatch(searchContents(query, editor));
|
||||
};
|
||||
}
|
||||
|
||||
function doSearchForHighlight(query, editor, line, ch) {
|
||||
return async ({
|
||||
getState,
|
||||
dispatch
|
||||
}) => {
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(getState());
|
||||
|
||||
if (!selectedSource || !selectedSource.text) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(searchContentsForHighlight(query, editor, line, ch));
|
||||
};
|
||||
}
|
||||
|
||||
function setFileSearchQuery(query) {
|
||||
return {
|
||||
type: "UPDATE_FILE_SEARCH_QUERY",
|
||||
query
|
||||
};
|
||||
}
|
||||
|
||||
function toggleFileSearchModifier(modifier) {
|
||||
return {
|
||||
type: "TOGGLE_FILE_SEARCH_MODIFIER",
|
||||
modifier
|
||||
};
|
||||
}
|
||||
|
||||
function updateSearchResults(characterIndex, line, matches) {
|
||||
const matchIndex = matches.findIndex(elm => elm.line === line && elm.ch === characterIndex);
|
||||
return {
|
||||
type: "UPDATE_SEARCH_RESULTS",
|
||||
results: {
|
||||
matches,
|
||||
matchIndex,
|
||||
count: matches.length,
|
||||
index: characterIndex
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function searchContents(query, editor) {
|
||||
return async ({
|
||||
getState,
|
||||
dispatch
|
||||
}) => {
|
||||
const modifiers = (0, _selectors.getFileSearchModifiers)(getState());
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(getState());
|
||||
|
||||
if (!query || !editor || !selectedSource || !selectedSource.text || !modifiers) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ctx = {
|
||||
ed: editor,
|
||||
cm: editor.codeMirror
|
||||
};
|
||||
|
||||
const _modifiers = modifiers.toJS();
|
||||
|
||||
const matches = await (0, _search.getMatches)(query, selectedSource.text, _modifiers);
|
||||
const res = (0, _editor.find)(ctx, query, true, _modifiers);
|
||||
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
ch,
|
||||
line
|
||||
} = res;
|
||||
dispatch(updateSearchResults(ch, line, matches));
|
||||
};
|
||||
}
|
||||
|
||||
function searchContentsForHighlight(query, editor, line, ch) {
|
||||
return async ({
|
||||
getState,
|
||||
dispatch
|
||||
}) => {
|
||||
const modifiers = (0, _selectors.getFileSearchModifiers)(getState());
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(getState());
|
||||
|
||||
if (!query || !editor || !selectedSource || !selectedSource.text || !modifiers) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ctx = {
|
||||
ed: editor,
|
||||
cm: editor.codeMirror
|
||||
};
|
||||
|
||||
const _modifiers = modifiers.toJS();
|
||||
|
||||
(0, _editor.searchSourceForHighlight)(ctx, false, query, true, _modifiers, line, ch);
|
||||
};
|
||||
}
|
||||
|
||||
function traverseResults(rev, editor) {
|
||||
return async ({
|
||||
getState,
|
||||
dispatch
|
||||
}) => {
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ctx = {
|
||||
ed: editor,
|
||||
cm: editor.codeMirror
|
||||
};
|
||||
const query = (0, _selectors.getFileSearchQuery)(getState());
|
||||
const modifiers = (0, _selectors.getFileSearchModifiers)(getState());
|
||||
const {
|
||||
matches
|
||||
} = (0, _selectors.getFileSearchResults)(getState());
|
||||
|
||||
if (query === "") {
|
||||
dispatch((0, _ui.setActiveSearch)("file"));
|
||||
}
|
||||
|
||||
if (modifiers) {
|
||||
const matchedLocations = matches || [];
|
||||
const results = rev ? (0, _editor.findPrev)(ctx, query, true, modifiers.toJS()) : (0, _editor.findNext)(ctx, query, true, modifiers.toJS());
|
||||
|
||||
if (!results) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
ch,
|
||||
line
|
||||
} = results;
|
||||
dispatch(updateSearchResults(ch, line, matchedLocations));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function closeFileSearch(editor) {
|
||||
return ({
|
||||
getState,
|
||||
dispatch
|
||||
}) => {
|
||||
const query = (0, _selectors.getFileSearchQuery)(getState());
|
||||
|
||||
if (editor) {
|
||||
const ctx = {
|
||||
ed: editor,
|
||||
cm: editor.codeMirror
|
||||
};
|
||||
(0, _editor.removeOverlay)(ctx, query);
|
||||
}
|
||||
|
||||
dispatch(setFileSearchQuery(""));
|
||||
dispatch((0, _ui.closeActiveSearch)());
|
||||
dispatch((0, _ui.clearHighlightLineRange)());
|
||||
};
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _breakpoints = require("./breakpoints");
|
||||
|
||||
var breakpoints = _interopRequireWildcard(_breakpoints);
|
||||
|
||||
var _expressions = require("./expressions");
|
||||
|
||||
var expressions = _interopRequireWildcard(_expressions);
|
||||
|
||||
var _eventListeners = require("./event-listeners");
|
||||
|
||||
var eventListeners = _interopRequireWildcard(_eventListeners);
|
||||
|
||||
var _pause = require("./pause/index");
|
||||
|
||||
var pause = _interopRequireWildcard(_pause);
|
||||
|
||||
var _navigation = require("./navigation");
|
||||
|
||||
var navigation = _interopRequireWildcard(_navigation);
|
||||
|
||||
var _ui = require("./ui");
|
||||
|
||||
var ui = _interopRequireWildcard(_ui);
|
||||
|
||||
var _fileSearch = require("./file-search");
|
||||
|
||||
var fileSearch = _interopRequireWildcard(_fileSearch);
|
||||
|
||||
var _ast = require("./ast");
|
||||
|
||||
var ast = _interopRequireWildcard(_ast);
|
||||
|
||||
var _coverage = require("./coverage");
|
||||
|
||||
var coverage = _interopRequireWildcard(_coverage);
|
||||
|
||||
var _projectTextSearch = require("./project-text-search");
|
||||
|
||||
var projectTextSearch = _interopRequireWildcard(_projectTextSearch);
|
||||
|
||||
var _replay = require("./replay");
|
||||
|
||||
var replay = _interopRequireWildcard(_replay);
|
||||
|
||||
var _quickOpen = require("./quick-open");
|
||||
|
||||
var quickOpen = _interopRequireWildcard(_quickOpen);
|
||||
|
||||
var _sourceTree = require("./source-tree");
|
||||
|
||||
var sourceTree = _interopRequireWildcard(_sourceTree);
|
||||
|
||||
var _sources = require("./sources/index");
|
||||
|
||||
var sources = _interopRequireWildcard(_sources);
|
||||
|
||||
var _debuggee = require("./debuggee");
|
||||
|
||||
var debuggee = _interopRequireWildcard(_debuggee);
|
||||
|
||||
var _toolbox = require("./toolbox");
|
||||
|
||||
var toolbox = _interopRequireWildcard(_toolbox);
|
||||
|
||||
var _preview = require("./preview");
|
||||
|
||||
var preview = _interopRequireWildcard(_preview);
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
||||
|
||||
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; }
|
||||
|
||||
exports.default = _objectSpread({}, navigation, breakpoints, expressions, eventListeners, sources, pause, ui, fileSearch, ast, coverage, projectTextSearch, replay, quickOpen, sourceTree, debuggee, toolbox, preview);
|
|
@ -0,0 +1,31 @@
|
|||
# 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 += [
|
||||
'ast',
|
||||
'breakpoints',
|
||||
'pause',
|
||||
'sources',
|
||||
'utils',
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'ast.js',
|
||||
'breakpoints.js',
|
||||
'coverage.js',
|
||||
'debuggee.js',
|
||||
'event-listeners.js',
|
||||
'expressions.js',
|
||||
'file-search.js',
|
||||
'index.js',
|
||||
'navigation.js',
|
||||
'preview.js',
|
||||
'project-text-search.js',
|
||||
'quick-open.js',
|
||||
'replay.js',
|
||||
'source-tree.js',
|
||||
'toolbox.js',
|
||||
'ui.js',
|
||||
)
|
|
@ -0,0 +1,103 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.willNavigate = willNavigate;
|
||||
exports.navigate = navigate;
|
||||
exports.connect = connect;
|
||||
exports.navigated = navigated;
|
||||
|
||||
var _editor = require("../utils/editor/index");
|
||||
|
||||
var _sourceQueue = require("../utils/source-queue");
|
||||
|
||||
var _sourceQueue2 = _interopRequireDefault(_sourceQueue);
|
||||
|
||||
var _sources = require("../reducers/sources");
|
||||
|
||||
var _utils = require("../utils/utils");
|
||||
|
||||
var _sources2 = require("./sources/index");
|
||||
|
||||
var _debuggee = require("./debuggee");
|
||||
|
||||
var _parser = require("../workers/parser/index");
|
||||
|
||||
var _wasm = require("../utils/wasm");
|
||||
|
||||
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/>. */
|
||||
|
||||
/**
|
||||
* Redux actions for the navigation state
|
||||
* @module actions/navigation
|
||||
*/
|
||||
|
||||
/**
|
||||
* @memberof actions/navigation
|
||||
* @static
|
||||
*/
|
||||
function willNavigate(event) {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) {
|
||||
await sourceMaps.clearSourceMaps();
|
||||
(0, _wasm.clearWasmStates)();
|
||||
(0, _editor.clearDocuments)();
|
||||
(0, _editor.removeEditor)();
|
||||
(0, _parser.clearSymbols)();
|
||||
(0, _parser.clearASTs)();
|
||||
(0, _parser.clearScopes)();
|
||||
(0, _parser.clearSources)();
|
||||
dispatch(navigate(event.url));
|
||||
};
|
||||
}
|
||||
|
||||
function navigate(url) {
|
||||
_sourceQueue2.default.clear();
|
||||
|
||||
return {
|
||||
type: "NAVIGATE",
|
||||
url
|
||||
};
|
||||
}
|
||||
|
||||
function connect(url, canRewind) {
|
||||
return async function ({
|
||||
dispatch
|
||||
}) {
|
||||
await dispatch((0, _debuggee.updateWorkers)());
|
||||
dispatch({
|
||||
type: "CONNECT",
|
||||
url,
|
||||
canRewind
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @memberof actions/navigation
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function navigated() {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) {
|
||||
await (0, _utils.waitForMs)(100);
|
||||
|
||||
if ((0, _sources.getSources)(getState()).size == 0) {
|
||||
const sources = await client.fetchSources();
|
||||
dispatch((0, _sources2.newSources)(sources));
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.breakOnNext = breakOnNext;
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/**
|
||||
* Debugger breakOnNext command.
|
||||
* It's different from the comand action because we also want to
|
||||
* highlight the pause icon.
|
||||
*
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
*/
|
||||
function breakOnNext() {
|
||||
return ({
|
||||
dispatch,
|
||||
client
|
||||
}) => {
|
||||
client.breakOnNext();
|
||||
return dispatch({
|
||||
type: "BREAK_ON_NEXT",
|
||||
value: true
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.command = command;
|
||||
exports.stepIn = stepIn;
|
||||
exports.stepOver = stepOver;
|
||||
exports.stepOut = stepOut;
|
||||
exports.resume = resume;
|
||||
exports.rewind = rewind;
|
||||
exports.reverseStepIn = reverseStepIn;
|
||||
exports.reverseStepOver = reverseStepOver;
|
||||
exports.reverseStepOut = reverseStepOut;
|
||||
exports.astCommand = astCommand;
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _promise = require("../utils/middleware/promise");
|
||||
|
||||
var _parser = require("../../workers/parser/index");
|
||||
|
||||
var _breakpoints = require("../breakpoints");
|
||||
|
||||
var _prefs = require("../../utils/prefs");
|
||||
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2; js-indent-level: 2 -*- */
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/>. */
|
||||
|
||||
/**
|
||||
* Debugger commands like stepOver, stepIn, stepUp
|
||||
*
|
||||
* @param string $0.type
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
*/
|
||||
function command(type) {
|
||||
return async ({
|
||||
dispatch,
|
||||
client
|
||||
}) => {
|
||||
return dispatch({
|
||||
type: "COMMAND",
|
||||
command: type,
|
||||
[_promise.PROMISE]: client[type]()
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
* StepIn
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
* @returns {Function} {@link command}
|
||||
*/
|
||||
|
||||
|
||||
function stepIn() {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
if ((0, _selectors.isPaused)(getState())) {
|
||||
return dispatch(command("stepIn"));
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* stepOver
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
* @returns {Function} {@link command}
|
||||
*/
|
||||
|
||||
|
||||
function stepOver() {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
if ((0, _selectors.isPaused)(getState())) {
|
||||
return dispatch(astCommand("stepOver"));
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* stepOut
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
* @returns {Function} {@link command}
|
||||
*/
|
||||
|
||||
|
||||
function stepOut() {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
if ((0, _selectors.isPaused)(getState())) {
|
||||
return dispatch(command("stepOut"));
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* resume
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
* @returns {Function} {@link command}
|
||||
*/
|
||||
|
||||
|
||||
function resume() {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
if ((0, _selectors.isPaused)(getState())) {
|
||||
return dispatch(command("resume"));
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* rewind
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
* @returns {Function} {@link command}
|
||||
*/
|
||||
|
||||
|
||||
function rewind() {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
if ((0, _selectors.isPaused)(getState())) {
|
||||
return dispatch(command("rewind"));
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* reverseStepIn
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
* @returns {Function} {@link command}
|
||||
*/
|
||||
|
||||
|
||||
function reverseStepIn() {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
if ((0, _selectors.isPaused)(getState())) {
|
||||
return dispatch(command("reverseStepIn"));
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* reverseStepOver
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
* @returns {Function} {@link command}
|
||||
*/
|
||||
|
||||
|
||||
function reverseStepOver() {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
if ((0, _selectors.isPaused)(getState())) {
|
||||
return dispatch(astCommand("reverseStepOver"));
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* reverseStepOut
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
* @returns {Function} {@link command}
|
||||
*/
|
||||
|
||||
|
||||
function reverseStepOut() {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
if ((0, _selectors.isPaused)(getState())) {
|
||||
return dispatch(command("reverseStepOut"));
|
||||
}
|
||||
};
|
||||
}
|
||||
/*
|
||||
* Checks for await or yield calls on the paused line
|
||||
* This avoids potentially expensive parser calls when we are likely
|
||||
* not at an async expression.
|
||||
*/
|
||||
|
||||
|
||||
function hasAwait(source, pauseLocation) {
|
||||
const {
|
||||
line,
|
||||
column
|
||||
} = pauseLocation;
|
||||
|
||||
if (!source.text) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const lineText = source.text.split("\n")[line - 1];
|
||||
|
||||
if (!lineText) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const snippet = lineText.slice(column - 50, column + 50);
|
||||
return !!snippet.match(/(yield|await)/);
|
||||
}
|
||||
/**
|
||||
* @memberOf actions/pause
|
||||
* @static
|
||||
* @param stepType
|
||||
* @returns {function(ThunkArgs)}
|
||||
*/
|
||||
|
||||
|
||||
function astCommand(stepType) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
sourceMaps
|
||||
}) => {
|
||||
if (!_prefs.features.asyncStepping) {
|
||||
return dispatch(command(stepType));
|
||||
}
|
||||
|
||||
if (stepType == "stepOver") {
|
||||
// This type definition is ambiguous:
|
||||
const frame = (0, _selectors.getTopFrame)(getState());
|
||||
const source = (0, _selectors.getSource)(getState(), frame.location.sourceId);
|
||||
|
||||
if (source && hasAwait(source, frame.location)) {
|
||||
const nextLocation = await (0, _parser.getNextStep)(source.id, frame.location);
|
||||
|
||||
if (nextLocation) {
|
||||
await dispatch((0, _breakpoints.addHiddenBreakpoint)(nextLocation));
|
||||
return dispatch(command("resume"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dispatch(command(stepType));
|
||||
};
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.continueToHere = continueToHere;
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _breakpoints = require("../breakpoints");
|
||||
|
||||
var _commands = require("./commands");
|
||||
|
||||
/* 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 continueToHere(line) {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState
|
||||
}) {
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(getState());
|
||||
|
||||
if (!(0, _selectors.isPaused)(getState()) || !selectedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedFrame = (0, _selectors.getSelectedFrame)(getState());
|
||||
const debugLine = selectedFrame.location.line;
|
||||
|
||||
if (debugLine == line) {
|
||||
return;
|
||||
}
|
||||
|
||||
const action = (0, _selectors.getCanRewind)(getState()) && line < debugLine ? _commands.rewind : _commands.resume;
|
||||
await dispatch((0, _breakpoints.addHiddenBreakpoint)({
|
||||
line,
|
||||
column: undefined,
|
||||
sourceId: selectedSource.id
|
||||
}));
|
||||
dispatch(action());
|
||||
};
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.fetchExtra = fetchExtra;
|
||||
exports.getExtra = getExtra;
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _preview = require("../../utils/preview");
|
||||
|
||||
var _ast = require("../../utils/ast");
|
||||
|
||||
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 getReactProps(evaluate) {
|
||||
const componentNames = await evaluate(`
|
||||
if(this.hasOwnProperty('_reactInternalFiber')) {
|
||||
let componentNames = [];
|
||||
let componentNode = this._reactInternalFiber;
|
||||
while(componentNode) {
|
||||
componentNames.push(componentNode.type.name);
|
||||
componentNode = componentNode._debugOwner
|
||||
}
|
||||
componentNames;
|
||||
}
|
||||
else {
|
||||
[this._reactInternalInstance.getName()];
|
||||
}
|
||||
`);
|
||||
const items = componentNames.result.preview && componentNames.result.preview.items;
|
||||
|
||||
if (items) {
|
||||
return {
|
||||
displayName: items[0],
|
||||
componentStack: items
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function getImmutableProps(expression, evaluate) {
|
||||
const immutableEntries = await evaluate((exp => `${exp}.toJS()`)(expression));
|
||||
const immutableType = await evaluate((exp => `${exp}.constructor.name`)(expression));
|
||||
return {
|
||||
type: immutableType.result,
|
||||
entries: immutableEntries.result
|
||||
};
|
||||
}
|
||||
|
||||
async function getExtraProps(getState, expression, result, evaluate) {
|
||||
const props = {};
|
||||
|
||||
if ((0, _preview.isReactComponent)(result)) {
|
||||
const selectedFrame = (0, _selectors.getSelectedFrame)(getState());
|
||||
const source = (0, _selectors.getSource)(getState(), selectedFrame.location.sourceId);
|
||||
const symbols = (0, _selectors.getSymbols)(getState(), source);
|
||||
|
||||
if (symbols && symbols.classes) {
|
||||
const originalClass = (0, _ast.findClosestClass)(symbols, selectedFrame.location);
|
||||
|
||||
if (originalClass) {
|
||||
props.react = {
|
||||
displayName: originalClass.name
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
props.react = _objectSpread({}, (await getReactProps(evaluate)), props.react);
|
||||
}
|
||||
|
||||
if ((0, _preview.isImmutable)(result)) {
|
||||
props.immutable = await getImmutableProps(expression, evaluate);
|
||||
}
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
function fetchExtra() {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState
|
||||
}) {
|
||||
const frame = (0, _selectors.getSelectedFrame)(getState());
|
||||
const extra = await dispatch(getExtra("this;", frame.this));
|
||||
dispatch({
|
||||
type: "ADD_EXTRA",
|
||||
extra: extra
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function getExtra(expression, result) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) => {
|
||||
const selectedFrame = (0, _selectors.getSelectedFrame)(getState());
|
||||
|
||||
if (!selectedFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
const extra = await getExtraProps(getState, expression, result, expr => client.evaluateInFrame(expr, selectedFrame.id));
|
||||
return extra;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.fetchScopes = fetchScopes;
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _mapScopes = require("./mapScopes");
|
||||
|
||||
var _promise = require("../utils/middleware/promise");
|
||||
|
||||
var _extra = require("./extra");
|
||||
|
||||
/* 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 fetchScopes() {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) {
|
||||
const frame = (0, _selectors.getSelectedFrame)(getState());
|
||||
|
||||
if (!frame || (0, _selectors.getGeneratedFrameScope)(getState(), frame.id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const scopes = dispatch({
|
||||
type: "ADD_SCOPES",
|
||||
frame,
|
||||
[_promise.PROMISE]: client.getFrameScopes(frame)
|
||||
});
|
||||
await dispatch((0, _extra.fetchExtra)());
|
||||
await dispatch((0, _mapScopes.mapScopes)(scopes, frame));
|
||||
};
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _commands = require("./commands");
|
||||
|
||||
Object.defineProperty(exports, "stepIn", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _commands.stepIn;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "stepOver", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _commands.stepOver;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "stepOut", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _commands.stepOut;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "resume", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _commands.resume;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "rewind", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _commands.rewind;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "reverseStepIn", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _commands.reverseStepIn;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "reverseStepOver", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _commands.reverseStepOver;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "reverseStepOut", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _commands.reverseStepOut;
|
||||
}
|
||||
});
|
||||
|
||||
var _fetchScopes = require("./fetchScopes");
|
||||
|
||||
Object.defineProperty(exports, "fetchScopes", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _fetchScopes.fetchScopes;
|
||||
}
|
||||
});
|
||||
|
||||
var _paused = require("./paused");
|
||||
|
||||
Object.defineProperty(exports, "paused", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _paused.paused;
|
||||
}
|
||||
});
|
||||
|
||||
var _resumed = require("./resumed");
|
||||
|
||||
Object.defineProperty(exports, "resumed", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _resumed.resumed;
|
||||
}
|
||||
});
|
||||
|
||||
var _continueToHere = require("./continueToHere");
|
||||
|
||||
Object.defineProperty(exports, "continueToHere", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _continueToHere.continueToHere;
|
||||
}
|
||||
});
|
||||
|
||||
var _breakOnNext = require("./breakOnNext");
|
||||
|
||||
Object.defineProperty(exports, "breakOnNext", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _breakOnNext.breakOnNext;
|
||||
}
|
||||
});
|
||||
|
||||
var _mapFrames = require("./mapFrames");
|
||||
|
||||
Object.defineProperty(exports, "mapFrames", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _mapFrames.mapFrames;
|
||||
}
|
||||
});
|
||||
|
||||
var _extra = require("./extra");
|
||||
|
||||
Object.defineProperty(exports, "fetchExtra", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _extra.fetchExtra;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "getExtra", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _extra.getExtra;
|
||||
}
|
||||
});
|
||||
|
||||
var _setPopupObjectProperties = require("./setPopupObjectProperties");
|
||||
|
||||
Object.defineProperty(exports, "setPopupObjectProperties", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _setPopupObjectProperties.setPopupObjectProperties;
|
||||
}
|
||||
});
|
||||
|
||||
var _pauseOnExceptions = require("./pauseOnExceptions");
|
||||
|
||||
Object.defineProperty(exports, "pauseOnExceptions", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _pauseOnExceptions.pauseOnExceptions;
|
||||
}
|
||||
});
|
||||
|
||||
var _selectFrame = require("./selectFrame");
|
||||
|
||||
Object.defineProperty(exports, "selectFrame", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _selectFrame.selectFrame;
|
||||
}
|
||||
});
|
||||
|
||||
var _skipPausing = require("./skipPausing");
|
||||
|
||||
Object.defineProperty(exports, "toggleSkipPausing", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _skipPausing.toggleSkipPausing;
|
||||
}
|
||||
});
|
|
@ -0,0 +1,84 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.updateFrameLocation = updateFrameLocation;
|
||||
exports.mapDisplayNames = mapDisplayNames;
|
||||
exports.mapFrames = mapFrames;
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _ast = require("../../utils/ast");
|
||||
|
||||
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 updateFrameLocation(frame, sourceMaps) {
|
||||
return sourceMaps.getOriginalLocation(frame.location).then(loc => _objectSpread({}, frame, {
|
||||
location: loc,
|
||||
generatedLocation: frame.generatedLocation || frame.location
|
||||
}));
|
||||
}
|
||||
|
||||
function updateFrameLocations(frames, sourceMaps) {
|
||||
if (!frames || frames.length == 0) {
|
||||
return Promise.resolve(frames);
|
||||
}
|
||||
|
||||
return Promise.all(frames.map(frame => updateFrameLocation(frame, sourceMaps)));
|
||||
}
|
||||
|
||||
function mapDisplayNames(frames, getState) {
|
||||
return frames.map(frame => {
|
||||
const source = (0, _selectors.getSource)(getState(), frame.location.sourceId);
|
||||
const symbols = (0, _selectors.getSymbols)(getState(), source);
|
||||
|
||||
if (!symbols || !symbols.functions) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
const originalFunction = (0, _ast.findClosestFunction)(symbols, frame.location);
|
||||
|
||||
if (!originalFunction) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
const originalDisplayName = originalFunction.name;
|
||||
return _objectSpread({}, frame, {
|
||||
originalDisplayName
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Map call stack frame locations and display names to originals.
|
||||
* e.g.
|
||||
* 1. When the debuggee pauses
|
||||
* 2. When a source is pretty printed
|
||||
* 3. When symbols are loaded
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function mapFrames() {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState,
|
||||
sourceMaps
|
||||
}) {
|
||||
const frames = (0, _selectors.getFrames)(getState());
|
||||
|
||||
if (!frames) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mappedFrames = await updateFrameLocations(frames, sourceMaps);
|
||||
mappedFrames = mapDisplayNames(mappedFrames, getState);
|
||||
dispatch({
|
||||
type: "MAP_FRAMES",
|
||||
frames: mappedFrames
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.mapScopes = mapScopes;
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _loadSourceText = require("../sources/loadSourceText");
|
||||
|
||||
var _promise = require("../utils/middleware/promise");
|
||||
|
||||
var _prefs = require("../../utils/prefs");
|
||||
|
||||
var _log = require("../../utils/log");
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _mapScopes = require("../../utils/pause/mapScopes/index");
|
||||
|
||||
/* 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 mapScopes(scopes, frame) {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) {
|
||||
const generatedSourceRecord = (0, _selectors.getSource)(getState(), frame.generatedLocation.sourceId);
|
||||
const sourceRecord = (0, _selectors.getSource)(getState(), frame.location.sourceId);
|
||||
const shouldMapScopes = _prefs.features.mapScopes && !generatedSourceRecord.isWasm && !sourceRecord.isPrettyPrinted && !(0, _devtoolsSourceMap.isGeneratedId)(frame.location.sourceId);
|
||||
await dispatch({
|
||||
type: "MAP_SCOPES",
|
||||
frame,
|
||||
[_promise.PROMISE]: async function () {
|
||||
if (!shouldMapScopes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
await dispatch((0, _loadSourceText.loadSourceText)(sourceRecord));
|
||||
|
||||
try {
|
||||
return await (0, _mapScopes.buildMappedScopes)(sourceRecord.toJS(), frame, (await scopes), sourceMaps, client);
|
||||
} catch (e) {
|
||||
(0, _log.log)(e);
|
||||
return null;
|
||||
}
|
||||
}()
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# 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(
|
||||
'breakOnNext.js',
|
||||
'commands.js',
|
||||
'continueToHere.js',
|
||||
'extra.js',
|
||||
'fetchScopes.js',
|
||||
'index.js',
|
||||
'mapFrames.js',
|
||||
'mapScopes.js',
|
||||
'paused.js',
|
||||
'pauseOnExceptions.js',
|
||||
'resumed.js',
|
||||
'selectFrame.js',
|
||||
'setPopupObjectProperties.js',
|
||||
'skipPausing.js',
|
||||
)
|
|
@ -0,0 +1,31 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.pauseOnExceptions = pauseOnExceptions;
|
||||
|
||||
var _promise = require("../utils/middleware/promise");
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/**
|
||||
*
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
*/
|
||||
function pauseOnExceptions(shouldPauseOnExceptions, shouldPauseOnCaughtExceptions) {
|
||||
return ({
|
||||
dispatch,
|
||||
client
|
||||
}) => {
|
||||
return dispatch({
|
||||
type: "PAUSE_ON_EXCEPTIONS",
|
||||
shouldPauseOnExceptions,
|
||||
shouldPauseOnCaughtExceptions,
|
||||
[_promise.PROMISE]: client.pauseOnExceptions(shouldPauseOnExceptions, shouldPauseOnCaughtExceptions)
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.paused = paused;
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _ = require("./index");
|
||||
|
||||
var _breakpoints = require("../breakpoints");
|
||||
|
||||
var _expressions = require("../expressions");
|
||||
|
||||
var _sources = require("../sources/index");
|
||||
|
||||
var _loadSourceText = require("../sources/loadSourceText");
|
||||
|
||||
var _ui = require("../ui");
|
||||
|
||||
var _commands = require("./commands");
|
||||
|
||||
var _pause = require("../../utils/pause/index");
|
||||
|
||||
var _mapFrames = require("./mapFrames");
|
||||
|
||||
var _fetchScopes = require("./fetchScopes");
|
||||
|
||||
/* 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/>. */
|
||||
async function getOriginalSourceForFrame(state, frame) {
|
||||
return (0, _selectors.getSources)(state).get(frame.location.sourceId);
|
||||
}
|
||||
/**
|
||||
* Debugger has just paused
|
||||
*
|
||||
* @param {object} pauseInfo
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function paused(pauseInfo) {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) {
|
||||
const {
|
||||
frames,
|
||||
why,
|
||||
loadedObjects
|
||||
} = pauseInfo;
|
||||
const rootFrame = frames.length > 0 ? frames[0] : null;
|
||||
|
||||
if (rootFrame) {
|
||||
const mappedFrame = await (0, _mapFrames.updateFrameLocation)(rootFrame, sourceMaps);
|
||||
const source = await getOriginalSourceForFrame(getState(), mappedFrame); // Ensure that the original file has loaded if there is one.
|
||||
|
||||
await dispatch((0, _loadSourceText.loadSourceText)(source));
|
||||
|
||||
if ((0, _pause.shouldStep)(mappedFrame, getState(), sourceMaps)) {
|
||||
dispatch((0, _commands.command)("stepOver"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: "PAUSED",
|
||||
why,
|
||||
frames,
|
||||
selectedFrameId: rootFrame ? rootFrame.id : undefined,
|
||||
loadedObjects: loadedObjects || []
|
||||
});
|
||||
const hiddenBreakpointLocation = (0, _selectors.getHiddenBreakpointLocation)(getState());
|
||||
|
||||
if (hiddenBreakpointLocation) {
|
||||
dispatch((0, _breakpoints.removeBreakpoint)(hiddenBreakpointLocation));
|
||||
}
|
||||
|
||||
await dispatch((0, _.mapFrames)());
|
||||
const selectedFrame = (0, _selectors.getSelectedFrame)(getState());
|
||||
|
||||
if (selectedFrame) {
|
||||
const visibleFrame = (0, _selectors.getVisibleSelectedFrame)(getState());
|
||||
const location = (0, _devtoolsSourceMap.isGeneratedId)(visibleFrame.location.sourceId) ? selectedFrame.generatedLocation : selectedFrame.location;
|
||||
await dispatch((0, _sources.selectLocation)(location));
|
||||
}
|
||||
|
||||
dispatch((0, _ui.togglePaneCollapse)("end", false));
|
||||
await dispatch((0, _fetchScopes.fetchScopes)()); // Run after fetching scoping data so that it may make use of the sourcemap
|
||||
// expression mappings for local variables.
|
||||
|
||||
const atException = why.type == "exception";
|
||||
|
||||
if (!atException || !(0, _selectors.isEvaluatingExpression)(getState())) {
|
||||
await dispatch((0, _expressions.evaluateExpressions)());
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.resumed = resumed;
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _expressions = require("../expressions");
|
||||
|
||||
var _pause = require("../../utils/pause/index");
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/**
|
||||
* Debugger has just resumed
|
||||
*
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
*/
|
||||
function resumed() {
|
||||
return async ({
|
||||
dispatch,
|
||||
client,
|
||||
getState
|
||||
}) => {
|
||||
const why = (0, _selectors.getPauseReason)(getState());
|
||||
const wasPausedInEval = (0, _pause.inDebuggerEval)(why);
|
||||
const wasStepping = (0, _selectors.isStepping)(getState());
|
||||
dispatch({
|
||||
type: "RESUME"
|
||||
});
|
||||
|
||||
if (!wasStepping && !wasPausedInEval) {
|
||||
await dispatch((0, _expressions.evaluateExpressions)());
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.selectFrame = selectFrame;
|
||||
|
||||
var _sources = require("../sources/index");
|
||||
|
||||
var _expressions = require("../expressions");
|
||||
|
||||
var _fetchScopes = require("./fetchScopes");
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/**
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
*/
|
||||
function selectFrame(frame) {
|
||||
return async ({
|
||||
dispatch,
|
||||
client,
|
||||
getState,
|
||||
sourceMaps
|
||||
}) => {
|
||||
dispatch({
|
||||
type: "SELECT_FRAME",
|
||||
frame
|
||||
});
|
||||
dispatch((0, _sources.selectLocation)(frame.location));
|
||||
dispatch((0, _expressions.evaluateExpressions)());
|
||||
dispatch((0, _fetchScopes.fetchScopes)());
|
||||
};
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.setPopupObjectProperties = setPopupObjectProperties;
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/**
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
*/
|
||||
function setPopupObjectProperties(object, properties) {
|
||||
return ({
|
||||
dispatch,
|
||||
client,
|
||||
getState
|
||||
}) => {
|
||||
const objectId = object.actor || object.objectId;
|
||||
|
||||
if ((0, _selectors.getPopupObjectProperties)(getState(), object.actor)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: "SET_POPUP_OBJECT_PROPERTIES",
|
||||
objectId,
|
||||
properties
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.toggleSkipPausing = toggleSkipPausing;
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/**
|
||||
* @memberof actions/pause
|
||||
* @static
|
||||
*/
|
||||
function toggleSkipPausing() {
|
||||
return async ({
|
||||
dispatch,
|
||||
client,
|
||||
getState,
|
||||
sourceMaps
|
||||
}) => {
|
||||
const skipPausing = !(0, _selectors.getSkipPausing)(getState()); // NOTE: enable this when we land the endpoint in m-c
|
||||
// await client.setSkipPausing(skipPausing);
|
||||
|
||||
dispatch({
|
||||
type: "TOGGLE_SKIP_PAUSING",
|
||||
skipPausing
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.updatePreview = updatePreview;
|
||||
exports.setPreview = setPreview;
|
||||
exports.clearPreview = clearPreview;
|
||||
|
||||
var _preview = require("../utils/preview");
|
||||
|
||||
var _ast = require("../utils/ast");
|
||||
|
||||
var _editor = require("../utils/editor/index");
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _promise = require("./utils/middleware/promise");
|
||||
|
||||
var _getExpression = require("../utils/editor/get-expression");
|
||||
|
||||
var _selectors = require("../selectors/index");
|
||||
|
||||
var _expressions = require("./expressions");
|
||||
|
||||
var _pause = require("./pause/index");
|
||||
|
||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
/* 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 isInvalidTarget(target) {
|
||||
if (!target || !target.innerText) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const tokenText = target.innerText.trim();
|
||||
const cursorPos = target.getBoundingClientRect(); // exclude literal tokens where it does not make sense to show a preview
|
||||
|
||||
const invalidType = ["cm-atom", ""].includes(target.className); // exclude syntax where the expression would be a syntax error
|
||||
|
||||
const invalidToken = tokenText === "" || tokenText.match(/^[(){}\|&%,.;=<>\+-/\*\s](?=)/);
|
||||
const isPresentation = target.attributes.role && target.attributes.getNamedItem("role").value == "presentation"; // exclude codemirror elements that are not tokens
|
||||
|
||||
const invalidTarget = target.parentElement && !target.parentElement.closest(".CodeMirror-line") || cursorPos.top == 0;
|
||||
return invalidTarget || invalidToken || invalidType || isPresentation;
|
||||
}
|
||||
|
||||
function updatePreview(target, editor) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) => {
|
||||
const tokenPos = (0, _editor.getTokenLocation)(editor.codeMirror, target);
|
||||
const cursorPos = target.getBoundingClientRect();
|
||||
const preview = (0, _selectors.getPreview)(getState());
|
||||
|
||||
if ((0, _selectors.getCanRewind)(getState())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (preview) {
|
||||
// Return early if we are currently showing another preview or
|
||||
// if we are mousing over the same token as before
|
||||
if (preview.updating || (0, _lodash.isEqual)(preview.tokenPos, tokenPos)) {
|
||||
return;
|
||||
} // We are mousing over a new token that is not in the preview
|
||||
|
||||
|
||||
if (!target.classList.contains("debug-expression")) {
|
||||
dispatch(clearPreview());
|
||||
}
|
||||
}
|
||||
|
||||
if (isInvalidTarget(target)) {
|
||||
dispatch(clearPreview());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(0, _selectors.isSelectedFrameVisible)(getState()) || !(0, _selectors.isLineInScope)(getState(), tokenPos.line)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const source = (0, _selectors.getSelectedSource)(getState());
|
||||
const symbols = (0, _selectors.getSymbols)(getState(), source);
|
||||
let match;
|
||||
|
||||
if (!symbols || symbols.loading) {
|
||||
match = (0, _getExpression.getExpressionFromCoords)(editor.codeMirror, tokenPos);
|
||||
} else {
|
||||
match = (0, _ast.findBestMatchExpression)(symbols, tokenPos);
|
||||
}
|
||||
|
||||
if (!match || !match.expression) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
expression,
|
||||
location
|
||||
} = match;
|
||||
|
||||
if ((0, _preview.isConsole)(expression)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(setPreview(expression, location, tokenPos, cursorPos));
|
||||
};
|
||||
}
|
||||
|
||||
function setPreview(expression, location, tokenPos, cursorPos) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) => {
|
||||
await dispatch({
|
||||
type: "SET_PREVIEW",
|
||||
[_promise.PROMISE]: async function () {
|
||||
const source = (0, _selectors.getSelectedSource)(getState());
|
||||
const sourceId = source.id;
|
||||
const selectedFrame = (0, _selectors.getSelectedFrame)(getState());
|
||||
|
||||
if (location && !(0, _devtoolsSourceMap.isGeneratedId)(sourceId)) {
|
||||
expression = await dispatch((0, _expressions.getMappedExpression)(expression));
|
||||
}
|
||||
|
||||
if (!selectedFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
result
|
||||
} = await client.evaluateInFrame(expression, selectedFrame.id);
|
||||
|
||||
if (result === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const extra = await dispatch((0, _pause.getExtra)(expression, result));
|
||||
return {
|
||||
expression,
|
||||
result,
|
||||
location,
|
||||
tokenPos,
|
||||
cursorPos,
|
||||
extra
|
||||
};
|
||||
}()
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function clearPreview() {
|
||||
return ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) => {
|
||||
const currentSelection = (0, _selectors.getPreview)(getState());
|
||||
|
||||
if (!currentSelection) {
|
||||
return;
|
||||
}
|
||||
|
||||
return dispatch({
|
||||
type: "CLEAR_SELECTION"
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.addSearchQuery = addSearchQuery;
|
||||
exports.clearSearchQuery = clearSearchQuery;
|
||||
exports.clearSearchResults = clearSearchResults;
|
||||
exports.clearSearch = clearSearch;
|
||||
exports.updateSearchStatus = updateSearchStatus;
|
||||
exports.closeProjectSearch = closeProjectSearch;
|
||||
exports.searchSources = searchSources;
|
||||
exports.searchSource = searchSource;
|
||||
|
||||
var _search = require("../workers/search/index");
|
||||
|
||||
var _selectors = require("../selectors/index");
|
||||
|
||||
var _source = require("../utils/source");
|
||||
|
||||
var _loadSourceText = require("./sources/loadSourceText");
|
||||
|
||||
var _projectTextSearch = require("../reducers/project-text-search");
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/**
|
||||
* Redux actions for the search state
|
||||
* @module actions/search
|
||||
*/
|
||||
function addSearchQuery(query) {
|
||||
return {
|
||||
type: "ADD_QUERY",
|
||||
query
|
||||
};
|
||||
}
|
||||
|
||||
function clearSearchQuery() {
|
||||
return {
|
||||
type: "CLEAR_QUERY"
|
||||
};
|
||||
}
|
||||
|
||||
function clearSearchResults() {
|
||||
return {
|
||||
type: "CLEAR_SEARCH_RESULTS"
|
||||
};
|
||||
}
|
||||
|
||||
function clearSearch() {
|
||||
return {
|
||||
type: "CLEAR_SEARCH"
|
||||
};
|
||||
}
|
||||
|
||||
function updateSearchStatus(status) {
|
||||
return {
|
||||
type: "UPDATE_STATUS",
|
||||
status
|
||||
};
|
||||
}
|
||||
|
||||
function closeProjectSearch() {
|
||||
return {
|
||||
type: "CLOSE_PROJECT_SEARCH"
|
||||
};
|
||||
}
|
||||
|
||||
function searchSources(query) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
await dispatch(clearSearchResults());
|
||||
await dispatch(addSearchQuery(query));
|
||||
dispatch(updateSearchStatus(_projectTextSearch.statusType.fetching));
|
||||
const sources = (0, _selectors.getSources)(getState());
|
||||
const validSources = sources.valueSeq().filter(source => !(0, _selectors.hasPrettySource)(getState(), source.id) && !(0, _source.isThirdParty)(source));
|
||||
|
||||
for (const source of validSources) {
|
||||
await dispatch((0, _loadSourceText.loadSourceText)(source));
|
||||
await dispatch(searchSource(source.id, query));
|
||||
}
|
||||
|
||||
dispatch(updateSearchStatus(_projectTextSearch.statusType.done));
|
||||
};
|
||||
}
|
||||
|
||||
function searchSource(sourceId, query) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const sourceRecord = (0, _selectors.getSource)(getState(), sourceId);
|
||||
|
||||
if (!sourceRecord) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matches = await (0, _search.findSourceMatches)(sourceRecord.toJS(), query);
|
||||
|
||||
if (!matches.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: "ADD_SEARCH_RESULT",
|
||||
result: {
|
||||
sourceId: sourceRecord.id,
|
||||
filepath: sourceRecord.url,
|
||||
matches
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.setQuickOpenQuery = setQuickOpenQuery;
|
||||
exports.openQuickOpen = openQuickOpen;
|
||||
exports.closeQuickOpen = closeQuickOpen;
|
||||
|
||||
/* 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 setQuickOpenQuery(query) {
|
||||
return {
|
||||
type: "SET_QUICK_OPEN_QUERY",
|
||||
query
|
||||
};
|
||||
}
|
||||
|
||||
function openQuickOpen(query) {
|
||||
if (query != null) {
|
||||
return {
|
||||
type: "OPEN_QUICK_OPEN",
|
||||
query
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: "OPEN_QUICK_OPEN"
|
||||
};
|
||||
}
|
||||
|
||||
function closeQuickOpen() {
|
||||
return {
|
||||
type: "CLOSE_QUICK_OPEN"
|
||||
};
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.timeTravelTo = timeTravelTo;
|
||||
exports.clearHistory = clearHistory;
|
||||
|
||||
var _selectors = require("../selectors/index");
|
||||
|
||||
var _sources = require("./sources/index");
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/**
|
||||
* Redux actions for replay
|
||||
* @module actions/replay
|
||||
*/
|
||||
function timeTravelTo(position) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const data = (0, _selectors.getHistoryFrame)(getState(), position);
|
||||
dispatch({
|
||||
type: "TRAVEL_TO",
|
||||
data,
|
||||
position
|
||||
});
|
||||
dispatch((0, _sources.selectLocation)(data.paused.frames[0].location));
|
||||
};
|
||||
}
|
||||
|
||||
function clearHistory() {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
dispatch({
|
||||
type: "CLEAR_HISTORY"
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.setExpandedState = setExpandedState;
|
||||
|
||||
/* 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 setExpandedState(expanded) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
dispatch({
|
||||
type: "SET_EXPANDED_STATE",
|
||||
expanded
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.toggleBlackBox = toggleBlackBox;
|
||||
|
||||
var _promise = require("../utils/middleware/promise");
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/**
|
||||
* Redux actions for the sources state
|
||||
* @module actions/sources
|
||||
*/
|
||||
function toggleBlackBox(source) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) => {
|
||||
const {
|
||||
isBlackBoxed,
|
||||
id
|
||||
} = source;
|
||||
return dispatch({
|
||||
type: "BLACKBOX",
|
||||
source,
|
||||
[_promise.PROMISE]: client.blackBox(id, isBlackBoxed)
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _loadSourceText = require("./loadSourceText");
|
||||
|
||||
Object.keys(_loadSourceText).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _loadSourceText[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var _prettyPrint = require("./prettyPrint");
|
||||
|
||||
Object.keys(_prettyPrint).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _prettyPrint[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var _newSources = require("./newSources");
|
||||
|
||||
Object.keys(_newSources).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _newSources[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var _blackbox = require("./blackbox");
|
||||
|
||||
Object.keys(_blackbox).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _blackbox[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var _select = require("./select");
|
||||
|
||||
Object.keys(_select).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _select[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var _tabs = require("./tabs");
|
||||
|
||||
Object.keys(_tabs).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _tabs[key];
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,114 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.loadSourceText = loadSourceText;
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _promise = require("../utils/middleware/promise");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _parser = require("../../workers/parser/index");
|
||||
|
||||
var parser = _interopRequireWildcard(_parser);
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _defer = require("../../utils/defer");
|
||||
|
||||
var _defer2 = _interopRequireDefault(_defer);
|
||||
|
||||
var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"];
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const requests = new Map();
|
||||
|
||||
const loadSourceHistogram = _devtoolsModules.Services.telemetry.getHistogramById("DEVTOOLS_DEBUGGER_LOAD_SOURCE_MS");
|
||||
|
||||
async function loadSource(source, {
|
||||
sourceMaps,
|
||||
client
|
||||
}) {
|
||||
const id = source.get("id");
|
||||
|
||||
if ((0, _devtoolsSourceMap.isOriginalId)(id)) {
|
||||
return await sourceMaps.getOriginalSourceText(source.toJS());
|
||||
}
|
||||
|
||||
const response = await client.sourceContents(id);
|
||||
return {
|
||||
id,
|
||||
text: response.source,
|
||||
contentType: response.contentType || "text/javascript"
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function loadSourceText(source) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) => {
|
||||
const id = source.get("id"); // Fetch the source text only once.
|
||||
|
||||
if (requests.has(id)) {
|
||||
return requests.get(id);
|
||||
}
|
||||
|
||||
if ((0, _source.isLoaded)(source)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const telemetryStart = performance.now();
|
||||
const deferred = (0, _defer2.default)();
|
||||
requests.set(id, deferred.promise);
|
||||
|
||||
try {
|
||||
await dispatch({
|
||||
type: "LOAD_SOURCE_TEXT",
|
||||
sourceId: id,
|
||||
[_promise.PROMISE]: loadSource(source, {
|
||||
sourceMaps,
|
||||
client
|
||||
})
|
||||
});
|
||||
} catch (e) {
|
||||
deferred.resolve();
|
||||
requests.delete(id);
|
||||
return;
|
||||
}
|
||||
|
||||
const newSource = (0, _selectors.getSource)(getState(), source.get("id")).toJS();
|
||||
|
||||
if ((0, _devtoolsSourceMap.isOriginalId)(newSource.id) && !newSource.isWasm) {
|
||||
const generatedSource = (0, _selectors.getGeneratedSource)(getState(), source.toJS());
|
||||
await dispatch(loadSourceText(generatedSource));
|
||||
}
|
||||
|
||||
if (!newSource.isWasm) {
|
||||
await parser.setSource(newSource);
|
||||
} // signal that the action is finished
|
||||
|
||||
|
||||
deferred.resolve();
|
||||
requests.delete(id);
|
||||
const telemetryEnd = performance.now();
|
||||
const duration = telemetryEnd - telemetryStart;
|
||||
loadSourceHistogram.add(duration);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
# 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(
|
||||
'blackbox.js',
|
||||
'index.js',
|
||||
'loadSourceText.js',
|
||||
'newSources.js',
|
||||
'prettyPrint.js',
|
||||
'select.js',
|
||||
'tabs.js',
|
||||
)
|
|
@ -0,0 +1,206 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.newSource = newSource;
|
||||
exports.newSources = newSources;
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
var _blackbox = require("./blackbox");
|
||||
|
||||
var _breakpoints = require("../breakpoints");
|
||||
|
||||
var _loadSourceText = require("./loadSourceText");
|
||||
|
||||
var _prettyPrint = require("./prettyPrint");
|
||||
|
||||
var _sources = require("../sources/index");
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
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 createOriginalSource(originalUrl, generatedSource, sourceMaps) {
|
||||
return {
|
||||
url: originalUrl,
|
||||
id: sourceMaps.generatedToOriginalId(generatedSource.id, originalUrl),
|
||||
isPrettyPrinted: false,
|
||||
isWasm: false,
|
||||
isBlackBoxed: false,
|
||||
loadedState: "unloaded"
|
||||
};
|
||||
}
|
||||
|
||||
function loadSourceMaps(sources) {
|
||||
return async function ({
|
||||
dispatch,
|
||||
sourceMaps
|
||||
}) {
|
||||
if (!sourceMaps) {
|
||||
return;
|
||||
}
|
||||
|
||||
const originalSources = await Promise.all(sources.map(source => dispatch(loadSourceMap(source.id))));
|
||||
await dispatch(newSources((0, _lodash.flatten)(originalSources)));
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function loadSourceMap(sourceId) {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState,
|
||||
sourceMaps
|
||||
}) {
|
||||
const source = (0, _selectors.getSource)(getState(), sourceId).toJS();
|
||||
|
||||
if (!sourceMaps || !(0, _devtoolsSourceMap.isGeneratedId)(sourceId) || !source.sourceMapURL) {
|
||||
return;
|
||||
}
|
||||
|
||||
let urls = null;
|
||||
|
||||
try {
|
||||
urls = await sourceMaps.getOriginalURLs(source);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
if (!urls) {
|
||||
// If this source doesn't have a sourcemap, enable it for pretty printing
|
||||
dispatch({
|
||||
type: "UPDATE_SOURCE",
|
||||
source: _objectSpread({}, source, {
|
||||
sourceMapURL: ""
|
||||
})
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
return urls.map(url => createOriginalSource(url, source, sourceMaps));
|
||||
};
|
||||
} // If a request has been made to show this source, go ahead and
|
||||
// select it.
|
||||
|
||||
|
||||
function checkSelectedSource(sourceId) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const source = (0, _selectors.getSource)(getState(), sourceId);
|
||||
const pendingLocation = (0, _selectors.getPendingSelectedLocation)(getState());
|
||||
|
||||
if (!pendingLocation || !pendingLocation.url || !source.url) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pendingUrl = pendingLocation.url;
|
||||
const rawPendingUrl = (0, _source.getRawSourceURL)(pendingUrl);
|
||||
|
||||
if (rawPendingUrl === source.url) {
|
||||
if ((0, _source.isPrettyURL)(pendingUrl)) {
|
||||
return await dispatch((0, _prettyPrint.togglePrettyPrint)(source.id));
|
||||
}
|
||||
|
||||
await dispatch((0, _sources.selectLocation)(_objectSpread({}, pendingLocation, {
|
||||
sourceId: source.id
|
||||
})));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function checkPendingBreakpoints(sourceId) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
// source may have been modified by selectLocation
|
||||
const source = (0, _selectors.getSource)(getState(), sourceId);
|
||||
const pendingBreakpoints = (0, _selectors.getPendingBreakpointsForSource)(getState(), source.get("url"));
|
||||
|
||||
if (!pendingBreakpoints.size) {
|
||||
return;
|
||||
} // load the source text if there is a pending breakpoint for it
|
||||
|
||||
|
||||
await dispatch((0, _loadSourceText.loadSourceText)(source));
|
||||
const pendingBreakpointsArray = pendingBreakpoints.valueSeq().toJS();
|
||||
|
||||
for (const pendingBreakpoint of pendingBreakpointsArray) {
|
||||
await dispatch((0, _breakpoints.syncBreakpoint)(sourceId, pendingBreakpoint));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function restoreBlackBoxedSources(sources) {
|
||||
return async ({
|
||||
dispatch
|
||||
}) => {
|
||||
const tabs = (0, _selectors.getBlackBoxList)();
|
||||
|
||||
if (tabs.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const source of sources) {
|
||||
if (tabs.includes(source.url) && !source.isBlackBoxed) {
|
||||
dispatch((0, _blackbox.toggleBlackBox)(source));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Handler for the debugger client's unsolicited newSource notification.
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function newSource(source) {
|
||||
return async ({
|
||||
dispatch
|
||||
}) => {
|
||||
await dispatch(newSources([source]));
|
||||
};
|
||||
}
|
||||
|
||||
function newSources(sources) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const filteredSources = sources.filter(source => source && !(0, _selectors.getSource)(getState(), source.id));
|
||||
|
||||
if (filteredSources.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: "ADD_SOURCES",
|
||||
sources: filteredSources
|
||||
});
|
||||
|
||||
for (const source of filteredSources) {
|
||||
dispatch(checkSelectedSource(source.id));
|
||||
dispatch(checkPendingBreakpoints(source.id));
|
||||
}
|
||||
|
||||
await dispatch(loadSourceMaps(filteredSources)); // We would like to restore the blackboxed state
|
||||
// after loading all states to make sure the correctness.
|
||||
|
||||
await dispatch(restoreBlackBoxedSources(filteredSources));
|
||||
};
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.createPrettySource = createPrettySource;
|
||||
exports.togglePrettyPrint = togglePrettyPrint;
|
||||
|
||||
var _assert = require("../../utils/assert");
|
||||
|
||||
var _assert2 = _interopRequireDefault(_assert);
|
||||
|
||||
var _breakpoints = require("../breakpoints");
|
||||
|
||||
var _ast = require("../ast");
|
||||
|
||||
var _prettyPrint = require("../../workers/pretty-print/index");
|
||||
|
||||
var _parser = require("../../workers/parser/index");
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _loadSourceText = require("./loadSourceText");
|
||||
|
||||
var _sources = require("../sources/index");
|
||||
|
||||
var _pause = require("../pause/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 createPrettySource(sourceId) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
sourceMaps
|
||||
}) => {
|
||||
const source = (0, _selectors.getSource)(getState(), sourceId);
|
||||
const url = (0, _source.getPrettySourceURL)(source.url);
|
||||
const id = await sourceMaps.generatedToOriginalId(sourceId, url);
|
||||
const prettySource = {
|
||||
url,
|
||||
id,
|
||||
isBlackBoxed: false,
|
||||
isPrettyPrinted: true,
|
||||
isWasm: false,
|
||||
contentType: "text/javascript",
|
||||
loadedState: "loading"
|
||||
};
|
||||
dispatch({
|
||||
type: "ADD_SOURCE",
|
||||
source: prettySource
|
||||
});
|
||||
const {
|
||||
code,
|
||||
mappings
|
||||
} = await (0, _prettyPrint.prettyPrint)({
|
||||
source,
|
||||
url
|
||||
});
|
||||
await sourceMaps.applySourceMap(source.id, url, code, mappings);
|
||||
|
||||
const loadedPrettySource = _objectSpread({}, prettySource, {
|
||||
text: code,
|
||||
loadedState: "loaded"
|
||||
});
|
||||
|
||||
(0, _parser.setSource)(loadedPrettySource);
|
||||
dispatch({
|
||||
type: "UPDATE_SOURCE",
|
||||
source: loadedPrettySource
|
||||
});
|
||||
return prettySource;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Toggle the pretty printing of a source's text. All subsequent calls to
|
||||
* |getText| will return the pretty-toggled text. Nothing will happen for
|
||||
* non-javascript files.
|
||||
*
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
* @param string id The source form from the RDP.
|
||||
* @returns Promise
|
||||
* A promise that resolves to [aSource, prettyText] or rejects to
|
||||
* [aSource, error].
|
||||
*/
|
||||
|
||||
|
||||
function togglePrettyPrint(sourceId) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) => {
|
||||
const source = (0, _selectors.getSource)(getState(), sourceId);
|
||||
|
||||
if (!source) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!(0, _source.isLoaded)(source)) {
|
||||
await dispatch((0, _loadSourceText.loadSourceText)(source));
|
||||
}
|
||||
|
||||
(0, _assert2.default)(sourceMaps.isGeneratedId(sourceId), "Pretty-printing only allowed on generated sources");
|
||||
const selectedLocation = (0, _selectors.getSelectedLocation)(getState());
|
||||
const url = (0, _source.getPrettySourceURL)(source.url);
|
||||
const prettySource = (0, _selectors.getSourceByURL)(getState(), url);
|
||||
const options = {};
|
||||
|
||||
if (selectedLocation) {
|
||||
options.location = await sourceMaps.getOriginalLocation(selectedLocation);
|
||||
}
|
||||
|
||||
if (prettySource) {
|
||||
const _sourceId = prettySource.get("id");
|
||||
|
||||
return dispatch((0, _sources.selectLocation)(_objectSpread({}, options.location, {
|
||||
sourceId: _sourceId
|
||||
})));
|
||||
}
|
||||
|
||||
const newPrettySource = await dispatch(createPrettySource(sourceId));
|
||||
await dispatch((0, _breakpoints.remapBreakpoints)(sourceId));
|
||||
await dispatch((0, _pause.mapFrames)());
|
||||
await dispatch((0, _ast.setPausePoints)(newPrettySource.id));
|
||||
await dispatch((0, _ast.setSymbols)(newPrettySource.id));
|
||||
return dispatch((0, _sources.selectLocation)(_objectSpread({}, options.location, {
|
||||
sourceId: newPrettySource.id
|
||||
})));
|
||||
};
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.selectSourceURL = selectSourceURL;
|
||||
exports.selectSource = selectSource;
|
||||
exports.selectLocation = selectLocation;
|
||||
exports.selectSpecificLocation = selectSpecificLocation;
|
||||
exports.selectSpecificSource = selectSpecificSource;
|
||||
exports.jumpToMappedLocation = jumpToMappedLocation;
|
||||
exports.jumpToMappedSelectedLocation = jumpToMappedSelectedLocation;
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _ast = require("../ast");
|
||||
|
||||
var _ui = require("../ui");
|
||||
|
||||
var _prettyPrint = require("./prettyPrint");
|
||||
|
||||
var _tabs = require("./tabs");
|
||||
|
||||
var _loadSourceText = require("./loadSourceText");
|
||||
|
||||
var _prefs = require("../../utils/prefs");
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _location = require("../../utils/location");
|
||||
|
||||
var _sourceMaps = require("../../utils/source-maps");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
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; }
|
||||
|
||||
/**
|
||||
* Deterministically select a source that has a given URL. This will
|
||||
* work regardless of the connection status or if the source exists
|
||||
* yet. This exists mostly for external things to interact with the
|
||||
* debugger.
|
||||
*
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
*/
|
||||
function selectSourceURL(url, options = {}) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const source = (0, _selectors.getSourceByURL)(getState(), url);
|
||||
|
||||
if (source) {
|
||||
const sourceId = source.id;
|
||||
const location = (0, _location.createLocation)(_objectSpread({}, options.location, {
|
||||
sourceId
|
||||
}));
|
||||
await dispatch(selectLocation(location));
|
||||
} else {
|
||||
dispatch({
|
||||
type: "SELECT_SOURCE_URL",
|
||||
url: url,
|
||||
line: options.location ? options.location.line : null
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function selectSource(sourceId) {
|
||||
return async ({
|
||||
dispatch
|
||||
}) => {
|
||||
const location = (0, _location.createLocation)({
|
||||
sourceId
|
||||
});
|
||||
return await dispatch(selectLocation(location));
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function selectLocation(location) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) => {
|
||||
if (!client) {
|
||||
// No connection, do nothing. This happens when the debugger is
|
||||
// shut down too fast and it tries to display a default source.
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceRecord = (0, _selectors.getSource)(getState(), location.sourceId);
|
||||
|
||||
if (!sourceRecord) {
|
||||
// If there is no source we deselect the current selected source
|
||||
return dispatch({
|
||||
type: "CLEAR_SELECTED_SOURCE"
|
||||
});
|
||||
}
|
||||
|
||||
const activeSearch = (0, _selectors.getActiveSearch)(getState());
|
||||
|
||||
if (activeSearch !== "file") {
|
||||
dispatch((0, _ui.closeActiveSearch)());
|
||||
}
|
||||
|
||||
const source = sourceRecord.toJS();
|
||||
dispatch((0, _tabs.addTab)(source, 0));
|
||||
dispatch({
|
||||
type: "SELECT_SOURCE",
|
||||
source,
|
||||
location
|
||||
});
|
||||
await dispatch((0, _loadSourceText.loadSourceText)(sourceRecord));
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(getState());
|
||||
|
||||
if (!selectedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceId = selectedSource.id;
|
||||
|
||||
if (_prefs.prefs.autoPrettyPrint && !(0, _selectors.getPrettySource)(getState(), sourceId) && (0, _source.shouldPrettyPrint)(selectedSource) && (0, _source.isMinified)(selectedSource)) {
|
||||
await dispatch((0, _prettyPrint.togglePrettyPrint)(sourceId));
|
||||
dispatch((0, _tabs.closeTab)(source.url));
|
||||
}
|
||||
|
||||
dispatch((0, _ast.setSymbols)(sourceId));
|
||||
dispatch((0, _ast.setOutOfScopeLocations)());
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function selectSpecificLocation(location) {
|
||||
return async ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) => {
|
||||
if (!client) {
|
||||
// No connection, do nothing. This happens when the debugger is
|
||||
// shut down too fast and it tries to display a default source.
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceRecord = (0, _selectors.getSource)(getState(), location.sourceId);
|
||||
|
||||
if (!sourceRecord) {
|
||||
// If there is no source we deselect the current selected source
|
||||
return dispatch({
|
||||
type: "CLEAR_SELECTED_SOURCE"
|
||||
});
|
||||
}
|
||||
|
||||
const activeSearch = (0, _selectors.getActiveSearch)(getState());
|
||||
|
||||
if (activeSearch !== "file") {
|
||||
dispatch((0, _ui.closeActiveSearch)());
|
||||
}
|
||||
|
||||
const source = sourceRecord.toJS();
|
||||
dispatch((0, _tabs.addTab)(source, 0));
|
||||
dispatch({
|
||||
type: "SELECT_SOURCE",
|
||||
source,
|
||||
location
|
||||
});
|
||||
await dispatch((0, _loadSourceText.loadSourceText)(sourceRecord));
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(getState());
|
||||
|
||||
if (!selectedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceId = selectedSource.id;
|
||||
dispatch((0, _ast.setSymbols)(sourceId));
|
||||
dispatch((0, _ast.setOutOfScopeLocations)());
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function selectSpecificSource(sourceId) {
|
||||
return async ({
|
||||
dispatch
|
||||
}) => {
|
||||
const location = (0, _location.createLocation)({
|
||||
sourceId
|
||||
});
|
||||
return await dispatch(selectSpecificLocation(location));
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function jumpToMappedLocation(location) {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) {
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
const source = (0, _selectors.getSource)(getState(), location.sourceId);
|
||||
let pairedLocation;
|
||||
|
||||
if ((0, _devtoolsSourceMap.isOriginalId)(location.sourceId)) {
|
||||
pairedLocation = await (0, _sourceMaps.getGeneratedLocation)(getState(), source, location, sourceMaps);
|
||||
} else {
|
||||
pairedLocation = await sourceMaps.getOriginalLocation(location, source.toJS());
|
||||
}
|
||||
|
||||
return dispatch(selectLocation(_objectSpread({}, pairedLocation)));
|
||||
};
|
||||
}
|
||||
|
||||
function jumpToMappedSelectedLocation() {
|
||||
return async function ({
|
||||
dispatch,
|
||||
getState
|
||||
}) {
|
||||
const location = (0, _selectors.getSelectedLocation)(getState());
|
||||
await dispatch(jumpToMappedLocation(location));
|
||||
};
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.addTab = addTab;
|
||||
exports.moveTab = moveTab;
|
||||
exports.closeTab = closeTab;
|
||||
exports.closeTabs = closeTabs;
|
||||
|
||||
var _editor = require("../../utils/editor/index");
|
||||
|
||||
var _sources = require("../sources/index");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/**
|
||||
* Redux actions for the sources state
|
||||
* @module actions/sources
|
||||
*/
|
||||
function addTab(source, tabIndex) {
|
||||
return {
|
||||
type: "ADD_TAB",
|
||||
source,
|
||||
tabIndex
|
||||
};
|
||||
}
|
||||
|
||||
function moveTab(url, tabIndex) {
|
||||
return {
|
||||
type: "MOVE_TAB",
|
||||
url,
|
||||
tabIndex
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function closeTab(url) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) => {
|
||||
(0, _editor.removeDocument)(url);
|
||||
const tabs = (0, _selectors.removeSourceFromTabList)((0, _selectors.getSourceTabs)(getState()), url);
|
||||
const sourceId = (0, _selectors.getNewSelectedSourceId)(getState(), tabs);
|
||||
dispatch({
|
||||
type: "CLOSE_TAB",
|
||||
url,
|
||||
tabs
|
||||
});
|
||||
dispatch((0, _sources.selectSource)(sourceId));
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function closeTabs(urls) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState,
|
||||
client
|
||||
}) => {
|
||||
urls.forEach(url => {
|
||||
const source = (0, _selectors.getSourceByURL)(getState(), url);
|
||||
|
||||
if (source) {
|
||||
(0, _editor.removeDocument)(source.get("id"));
|
||||
}
|
||||
});
|
||||
const tabs = (0, _selectors.removeSourcesFromTabList)((0, _selectors.getSourceTabs)(getState()), urls);
|
||||
dispatch({
|
||||
type: "CLOSE_TABS",
|
||||
urls,
|
||||
tabs
|
||||
});
|
||||
const sourceId = (0, _selectors.getNewSelectedSourceId)(getState(), tabs);
|
||||
dispatch((0, _sources.selectSource)(sourceId));
|
||||
};
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.openLink = openLink;
|
||||
exports.openWorkerToolbox = openWorkerToolbox;
|
||||
exports.evaluateInConsole = evaluateInConsole;
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const {
|
||||
isDevelopment
|
||||
} = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"];
|
||||
|
||||
const {
|
||||
getSelectedFrameId
|
||||
} = require("../selectors/index");
|
||||
|
||||
/**
|
||||
* @memberof actions/toolbox
|
||||
* @static
|
||||
*/
|
||||
function openLink(url) {
|
||||
return async function ({
|
||||
openLink: openLinkCommand
|
||||
}) {
|
||||
if (isDevelopment()) {
|
||||
const win = window.open(url, "_blank");
|
||||
win.focus();
|
||||
} else {
|
||||
openLinkCommand(url);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function openWorkerToolbox(worker) {
|
||||
return async function ({
|
||||
getState,
|
||||
openWorkerToolbox: openWorkerToolboxCommand
|
||||
}) {
|
||||
if (isDevelopment()) {
|
||||
alert(worker.url);
|
||||
} else {
|
||||
openWorkerToolboxCommand(worker);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function evaluateInConsole(inputString) {
|
||||
return async ({
|
||||
client,
|
||||
getState
|
||||
}) => {
|
||||
const frameId = getSelectedFrameId(getState());
|
||||
client.evaluate(`console.log("${inputString}"); console.log(${inputString})`, {
|
||||
frameId
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.setContextMenu = setContextMenu;
|
||||
exports.setPrimaryPaneTab = setPrimaryPaneTab;
|
||||
exports.closeActiveSearch = closeActiveSearch;
|
||||
exports.setActiveSearch = setActiveSearch;
|
||||
exports.toggleFrameworkGrouping = toggleFrameworkGrouping;
|
||||
exports.showSource = showSource;
|
||||
exports.togglePaneCollapse = togglePaneCollapse;
|
||||
exports.highlightLineRange = highlightLineRange;
|
||||
exports.flashLineRange = flashLineRange;
|
||||
exports.clearHighlightLineRange = clearHighlightLineRange;
|
||||
exports.openConditionalPanel = openConditionalPanel;
|
||||
exports.closeConditionalPanel = closeConditionalPanel;
|
||||
exports.clearProjectDirectoryRoot = clearProjectDirectoryRoot;
|
||||
exports.setProjectDirectoryRoot = setProjectDirectoryRoot;
|
||||
exports.setOrientation = setOrientation;
|
||||
|
||||
var _selectors = require("../selectors/index");
|
||||
|
||||
var _ui = require("../reducers/ui");
|
||||
|
||||
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 setContextMenu(type, event) {
|
||||
return ({
|
||||
dispatch
|
||||
}) => {
|
||||
dispatch({
|
||||
type: "SET_CONTEXT_MENU",
|
||||
contextMenu: {
|
||||
type,
|
||||
event
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function setPrimaryPaneTab(tabName) {
|
||||
return {
|
||||
type: "SET_PRIMARY_PANE_TAB",
|
||||
tabName
|
||||
};
|
||||
}
|
||||
|
||||
function closeActiveSearch() {
|
||||
return {
|
||||
type: "TOGGLE_ACTIVE_SEARCH",
|
||||
value: null
|
||||
};
|
||||
}
|
||||
|
||||
function setActiveSearch(activeSearch) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const activeSearchState = (0, _selectors.getActiveSearch)(getState());
|
||||
|
||||
if (activeSearchState === activeSearch) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((0, _selectors.getQuickOpenEnabled)(getState())) {
|
||||
dispatch({
|
||||
type: "CLOSE_QUICK_OPEN"
|
||||
});
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: "TOGGLE_ACTIVE_SEARCH",
|
||||
value: activeSearch
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function toggleFrameworkGrouping(toggleValue) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
dispatch({
|
||||
type: "TOGGLE_FRAMEWORK_GROUPING",
|
||||
value: toggleValue
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function showSource(sourceId) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const source = (0, _selectors.getSource)(getState(), sourceId);
|
||||
|
||||
if ((0, _selectors.getPaneCollapse)(getState(), "start")) {
|
||||
dispatch({
|
||||
type: "TOGGLE_PANE",
|
||||
position: "start",
|
||||
paneCollapsed: false
|
||||
});
|
||||
}
|
||||
|
||||
dispatch(setPrimaryPaneTab("sources"));
|
||||
dispatch({
|
||||
type: "SHOW_SOURCE",
|
||||
sourceUrl: ""
|
||||
});
|
||||
dispatch({
|
||||
type: "SHOW_SOURCE",
|
||||
sourceUrl: (0, _source.getRawSourceURL)(source.get("url"))
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function togglePaneCollapse(position, paneCollapsed) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const prevPaneCollapse = (0, _selectors.getPaneCollapse)(getState(), position);
|
||||
|
||||
if (prevPaneCollapse === paneCollapsed) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: "TOGGLE_PANE",
|
||||
position,
|
||||
paneCollapsed
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function highlightLineRange(location) {
|
||||
return {
|
||||
type: "HIGHLIGHT_LINES",
|
||||
location
|
||||
};
|
||||
}
|
||||
|
||||
function flashLineRange(location) {
|
||||
return ({
|
||||
dispatch
|
||||
}) => {
|
||||
dispatch(highlightLineRange(location));
|
||||
setTimeout(() => dispatch(clearHighlightLineRange()), 200);
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @memberof actions/sources
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function clearHighlightLineRange() {
|
||||
return {
|
||||
type: "CLEAR_HIGHLIGHT_LINES"
|
||||
};
|
||||
}
|
||||
|
||||
function openConditionalPanel(line) {
|
||||
if (!line) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
type: "OPEN_CONDITIONAL_PANEL",
|
||||
line
|
||||
};
|
||||
}
|
||||
|
||||
function closeConditionalPanel() {
|
||||
return {
|
||||
type: "CLOSE_CONDITIONAL_PANEL"
|
||||
};
|
||||
}
|
||||
|
||||
function clearProjectDirectoryRoot() {
|
||||
return {
|
||||
type: "SET_PROJECT_DIRECTORY_ROOT",
|
||||
url: ""
|
||||
};
|
||||
}
|
||||
|
||||
function setProjectDirectoryRoot(newRoot) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const curRoot = (0, _ui.getProjectDirectoryRoot)(getState());
|
||||
|
||||
if (newRoot && curRoot) {
|
||||
const newRootArr = newRoot.replace(/\/+/g, "/").split("/");
|
||||
const curRootArr = curRoot.replace(/^\//, "").replace(/\/+/g, "/").split("/");
|
||||
|
||||
if (newRootArr[0] !== curRootArr[0]) {
|
||||
newRootArr.splice(0, 2);
|
||||
newRoot = `${curRoot}/${newRootArr.join("/")}`;
|
||||
}
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: "SET_PROJECT_DIRECTORY_ROOT",
|
||||
url: newRoot
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function setOrientation(orientation) {
|
||||
return {
|
||||
type: "SET_ORIENTATION",
|
||||
orientation
|
||||
};
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _redux = require("devtools/client/shared/vendor/redux");
|
||||
|
||||
var _waitService = require("./middleware/wait-service");
|
||||
|
||||
var _log = require("./middleware/log");
|
||||
|
||||
var _history = require("./middleware/history");
|
||||
|
||||
var _promise = require("./middleware/promise");
|
||||
|
||||
var _thunk = require("./middleware/thunk");
|
||||
|
||||
var _timing = require("./middleware/timing");
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/* global window */
|
||||
|
||||
/**
|
||||
* Redux store utils
|
||||
* @module utils/create-store
|
||||
*/
|
||||
|
||||
/**
|
||||
* This creates a dispatcher with all the standard middleware in place
|
||||
* that all code requires. It can also be optionally configured in
|
||||
* various ways, such as logging and recording.
|
||||
*
|
||||
* @param {object} opts:
|
||||
* - log: log all dispatched actions to console
|
||||
* - history: an array to store every action in. Should only be
|
||||
* used in tests.
|
||||
* - middleware: array of middleware to be included in the redux store
|
||||
* @memberof utils/create-store
|
||||
* @static
|
||||
*/
|
||||
const configureStore = (opts = {}) => {
|
||||
const middleware = [(0, _thunk.thunk)(opts.makeThunkArgs), _promise.promise, // Order is important: services must go last as they always
|
||||
// operate on "already transformed" actions. Actions going through
|
||||
// them shouldn't have any special fields like promises, they
|
||||
// should just be normal JSON objects.
|
||||
_waitService.waitUntilService];
|
||||
|
||||
if (opts.history) {
|
||||
middleware.push((0, _history.history)(opts.history));
|
||||
}
|
||||
|
||||
if (opts.middleware) {
|
||||
opts.middleware.forEach(fn => middleware.push(fn));
|
||||
}
|
||||
|
||||
if (opts.log) {
|
||||
middleware.push(_log.log);
|
||||
}
|
||||
|
||||
if (opts.timing) {
|
||||
middleware.push(_timing.timing);
|
||||
} // Hook in the redux devtools browser extension if it exists
|
||||
|
||||
|
||||
const devtoolsExt = typeof window === "object" && window.devToolsExtension ? window.devToolsExtension() : f => f;
|
||||
return (0, _redux.applyMiddleware)(...middleware)(devtoolsExt(_redux.createStore));
|
||||
};
|
||||
|
||||
exports.default = configureStore;
|
|
@ -0,0 +1,32 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.history = undefined;
|
||||
|
||||
var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"];
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/* global window */
|
||||
|
||||
/**
|
||||
* A middleware that stores every action coming through the store in the passed
|
||||
* in logging object. Should only be used for tests, as it collects all
|
||||
* action information, which will cause memory bloat.
|
||||
*/
|
||||
const history = exports.history = (log = []) => ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
return next => action => {
|
||||
if ((0, _devtoolsEnvironment.isDevelopment)()) {
|
||||
log.push(action);
|
||||
}
|
||||
|
||||
return next(action);
|
||||
};
|
||||
};
|
|
@ -0,0 +1,117 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.log = log;
|
||||
|
||||
var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"];
|
||||
|
||||
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; }
|
||||
|
||||
const blacklist = ["SET_POPUP_OBJECT_PROPERTIES", "SET_PAUSE_POINTS", "SET_SYMBOLS", "OUT_OF_SCOPE_LOCATIONS", "MAP_SCOPES", "MAP_FRAMES", "ADD_SCOPES", "IN_SCOPE_LINES", "REMOVE_BREAKPOINT", "ADD_BREAKPOINT"];
|
||||
|
||||
function cloneAction(action) {
|
||||
action = action || {};
|
||||
action = _objectSpread({}, action); // ADD_TAB, ...
|
||||
|
||||
if (action.source && action.source.text) {
|
||||
const source = _objectSpread({}, action.source, {
|
||||
text: ""
|
||||
});
|
||||
|
||||
action.source = source;
|
||||
}
|
||||
|
||||
if (action.sources) {
|
||||
const sources = action.sources.slice(0, 20).map(source => {
|
||||
const url = !source.url || source.url.includes("data:") ? "" : source.url;
|
||||
return _objectSpread({}, source, {
|
||||
url
|
||||
});
|
||||
});
|
||||
action.sources = sources;
|
||||
} // LOAD_SOURCE_TEXT
|
||||
|
||||
|
||||
if (action.text) {
|
||||
action.text = "";
|
||||
}
|
||||
|
||||
if (action.value && action.value.text) {
|
||||
const value = _objectSpread({}, action.value, {
|
||||
text: ""
|
||||
});
|
||||
|
||||
action.value = value;
|
||||
}
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
function formatFrame(frame) {
|
||||
const {
|
||||
id,
|
||||
location,
|
||||
displayName
|
||||
} = frame;
|
||||
return {
|
||||
id,
|
||||
location,
|
||||
displayName
|
||||
};
|
||||
}
|
||||
|
||||
function formatPause(pause) {
|
||||
return _objectSpread({}, pause, {
|
||||
pauseInfo: {
|
||||
why: pause.why
|
||||
},
|
||||
scopes: [],
|
||||
frames: pause.frames.map(formatFrame),
|
||||
loadedObjects: []
|
||||
});
|
||||
}
|
||||
|
||||
function serializeAction(action) {
|
||||
try {
|
||||
action = cloneAction(action);
|
||||
|
||||
if (blacklist.includes(action.type)) {
|
||||
action = {};
|
||||
}
|
||||
|
||||
if (action.type === "PAUSED") {
|
||||
action = formatPause(action);
|
||||
} // dump(`> ${action.type}...\n ${JSON.stringify(action)}\n`);
|
||||
|
||||
|
||||
return JSON.stringify(action);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* A middleware that logs all actions coming through the system
|
||||
* to the console.
|
||||
*/
|
||||
|
||||
|
||||
function log({
|
||||
dispatch,
|
||||
getState
|
||||
}) {
|
||||
return next => action => {
|
||||
const asyncMsg = !action.status ? "" : `[${action.status}]`;
|
||||
|
||||
if ((0, _devtoolsEnvironment.isTesting)()) {
|
||||
dump(`[ACTION] ${action.type} ${asyncMsg} - ${serializeAction(action)}\n`);
|
||||
} else {
|
||||
console.log(action, asyncMsg);
|
||||
}
|
||||
|
||||
next(action);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
# 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(
|
||||
'history.js',
|
||||
'log.js',
|
||||
'promise.js',
|
||||
'thunk.js',
|
||||
'timing.js',
|
||||
'wait-service.js',
|
||||
)
|
|
@ -0,0 +1,70 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.promise = exports.PROMISE = undefined;
|
||||
|
||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
var _DevToolsUtils = require("../../../utils/DevToolsUtils");
|
||||
|
||||
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; }
|
||||
|
||||
let seqIdVal = 1;
|
||||
|
||||
function seqIdGen() {
|
||||
return seqIdVal++;
|
||||
}
|
||||
|
||||
function filterAction(action) {
|
||||
return (0, _lodash.fromPairs)((0, _lodash.toPairs)(action).filter(pair => pair[0] !== PROMISE));
|
||||
}
|
||||
|
||||
function promiseMiddleware({
|
||||
dispatch,
|
||||
getState
|
||||
}) {
|
||||
return next => action => {
|
||||
if (!(PROMISE in action)) {
|
||||
return next(action);
|
||||
}
|
||||
|
||||
const promiseInst = action[PROMISE];
|
||||
const seqId = seqIdGen().toString(); // Create a new action that doesn't have the promise field and has
|
||||
// the `seqId` field that represents the sequence id
|
||||
|
||||
action = _objectSpread({}, filterAction(action), {
|
||||
seqId
|
||||
});
|
||||
dispatch(_objectSpread({}, action, {
|
||||
status: "start"
|
||||
})); // Return the promise so action creators can still compose if they
|
||||
// want to.
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
promiseInst.then(value => {
|
||||
(0, _DevToolsUtils.executeSoon)(() => {
|
||||
dispatch(_objectSpread({}, action, {
|
||||
status: "done",
|
||||
value: value
|
||||
}));
|
||||
resolve(value);
|
||||
});
|
||||
}, error => {
|
||||
(0, _DevToolsUtils.executeSoon)(() => {
|
||||
dispatch(_objectSpread({}, action, {
|
||||
status: "error",
|
||||
error: error.message || error
|
||||
}));
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const PROMISE = exports.PROMISE = "@@dispatch/promise";
|
||||
exports.promise = promiseMiddleware;
|
|
@ -0,0 +1,34 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.thunk = thunk;
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/* global window */
|
||||
|
||||
/**
|
||||
* A middleware that allows thunks (functions) to be dispatched. If
|
||||
* it's a thunk, it is called with an argument that contains
|
||||
* `dispatch`, `getState`, and any additional args passed in via the
|
||||
* middleware constructure. This allows the action to create multiple
|
||||
* actions (most likely asynchronously).
|
||||
*/
|
||||
function thunk(makeArgs) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const args = {
|
||||
dispatch,
|
||||
getState
|
||||
};
|
||||
return next => action => {
|
||||
return typeof action === "function" ? action(makeArgs ? makeArgs(args, getState()) : args) : next(action);
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.timing = timing;
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/* global window */
|
||||
|
||||
/**
|
||||
* Redux middleware that sets performance markers for all actions such that they
|
||||
* will appear in performance tooling under the User Timing API
|
||||
*/
|
||||
const mark = window.performance && window.performance.mark ? window.performance.mark.bind(window.performance) : () => {};
|
||||
const measure = window.performance && window.performance.measure ? window.performance.measure.bind(window.performance) : () => {};
|
||||
|
||||
function timing(store) {
|
||||
return next => action => {
|
||||
mark(`${action.type}_start`);
|
||||
const result = next(action);
|
||||
mark(`${action.type}_end`);
|
||||
measure(`${action.type}`, `${action.type}_start`, `${action.type}_end`);
|
||||
return result;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.waitUntilService = waitUntilService;
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
/* global window */
|
||||
|
||||
/**
|
||||
* A middleware which acts like a service, because it is stateful
|
||||
* and "long-running" in the background. It provides the ability
|
||||
* for actions to install a function to be run once when a specific
|
||||
* condition is met by an action coming through the system. Think of
|
||||
* it as a thunk that blocks until the condition is met. Example:
|
||||
*
|
||||
* ```js
|
||||
* const services = { WAIT_UNTIL: require('wait-service').NAME };
|
||||
*
|
||||
* { type: services.WAIT_UNTIL,
|
||||
* predicate: action => action.type === "ADD_ITEM",
|
||||
* run: (dispatch, getState, action) => {
|
||||
* // Do anything here. You only need to accept the arguments
|
||||
* // if you need them. `action` is the action that satisfied
|
||||
* // the predicate.
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
const NAME = exports.NAME = "@@service/waitUntil";
|
||||
|
||||
function waitUntilService({
|
||||
dispatch,
|
||||
getState
|
||||
}) {
|
||||
let pending = [];
|
||||
|
||||
function checkPending(action) {
|
||||
const readyRequests = [];
|
||||
const stillPending = []; // Find the pending requests whose predicates are satisfied with
|
||||
// this action. Wait to run the requests until after we update the
|
||||
// pending queue because the request handler may synchronously
|
||||
// dispatch again and run this service (that use case is
|
||||
// completely valid).
|
||||
|
||||
for (const request of pending) {
|
||||
if (request.predicate(action)) {
|
||||
readyRequests.push(request);
|
||||
} else {
|
||||
stillPending.push(request);
|
||||
}
|
||||
}
|
||||
|
||||
pending = stillPending;
|
||||
|
||||
for (const request of readyRequests) {
|
||||
request.run(dispatch, getState, action);
|
||||
}
|
||||
}
|
||||
|
||||
return next => action => {
|
||||
if (action.type === NAME) {
|
||||
pending.push(action);
|
||||
return null;
|
||||
}
|
||||
|
||||
const result = next(action);
|
||||
checkPending(action);
|
||||
return result;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
# 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 += [
|
||||
'middleware',
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'create-store.js',
|
||||
)
|
|
@ -0,0 +1,89 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.clientEvents = exports.clientCommands = exports.createObjectClient = undefined;
|
||||
exports.onConnect = onConnect;
|
||||
|
||||
var _commands = require("./firefox/commands");
|
||||
|
||||
var _events = require("./firefox/events");
|
||||
|
||||
var _prefs = require("../utils/prefs");
|
||||
|
||||
/* 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/>. */
|
||||
let DebuggerClient;
|
||||
|
||||
function createObjectClient(grip) {
|
||||
return DebuggerClient.createObjectClient(grip);
|
||||
}
|
||||
|
||||
async function onConnect(connection, actions) {
|
||||
const {
|
||||
tabConnection: {
|
||||
tabTarget,
|
||||
threadClient,
|
||||
debuggerClient
|
||||
}
|
||||
} = connection;
|
||||
DebuggerClient = debuggerClient;
|
||||
|
||||
if (!tabTarget || !threadClient || !debuggerClient) {
|
||||
return {
|
||||
bpClients: {}
|
||||
};
|
||||
}
|
||||
|
||||
const supportsWasm = _prefs.features.wasm && !!debuggerClient.mainRoot.traits.wasmBinarySource;
|
||||
const {
|
||||
bpClients
|
||||
} = (0, _commands.setupCommands)({
|
||||
threadClient,
|
||||
tabTarget,
|
||||
debuggerClient,
|
||||
supportsWasm
|
||||
});
|
||||
|
||||
if (actions) {
|
||||
(0, _events.setupEvents)({
|
||||
threadClient,
|
||||
actions,
|
||||
supportsWasm
|
||||
});
|
||||
}
|
||||
|
||||
tabTarget.on("will-navigate", actions.willNavigate);
|
||||
tabTarget.on("navigate", actions.navigated);
|
||||
await threadClient.reconfigure({
|
||||
observeAsmJS: true,
|
||||
wasmBinarySource: supportsWasm
|
||||
}); // In Firefox, we need to initially request all of the sources. This
|
||||
// usually fires off individual `newSource` notifications as the
|
||||
// debugger finds them, but there may be existing sources already in
|
||||
// the debugger (if it's paused already, or if loading the page from
|
||||
// bfcache) so explicity fire `newSource` events for all returned
|
||||
// sources.
|
||||
|
||||
const sources = await _commands.clientCommands.fetchSources();
|
||||
const traits = tabTarget.activeTab ? tabTarget.activeTab.traits : null;
|
||||
await actions.connect(tabTarget.url, traits && traits.canRewind);
|
||||
await actions.newSources(sources); // If the threadClient is already paused, make sure to show a
|
||||
// paused state.
|
||||
|
||||
const pausedPacket = threadClient.getLastPausePacket();
|
||||
|
||||
if (pausedPacket) {
|
||||
_events.clientEvents.paused("paused", pausedPacket);
|
||||
}
|
||||
|
||||
return {
|
||||
bpClients
|
||||
};
|
||||
}
|
||||
|
||||
exports.createObjectClient = createObjectClient;
|
||||
exports.clientCommands = _commands.clientCommands;
|
||||
exports.clientEvents = _events.clientEvents;
|
|
@ -0,0 +1,437 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.clientCommands = exports.setupCommands = undefined;
|
||||
|
||||
var _breakpoint = require("../../utils/breakpoint/index");
|
||||
|
||||
var _create = require("./create");
|
||||
|
||||
var _frontsDevice = require("devtools/shared/fronts/device");
|
||||
|
||||
var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"];
|
||||
|
||||
/* 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/>. */
|
||||
let bpClients;
|
||||
let threadClient;
|
||||
let tabTarget;
|
||||
let debuggerClient;
|
||||
let supportsWasm;
|
||||
|
||||
function setupCommands(dependencies) {
|
||||
threadClient = dependencies.threadClient;
|
||||
tabTarget = dependencies.tabTarget;
|
||||
debuggerClient = dependencies.debuggerClient;
|
||||
supportsWasm = dependencies.supportsWasm;
|
||||
bpClients = {};
|
||||
return {
|
||||
bpClients
|
||||
};
|
||||
}
|
||||
|
||||
function sendPacket(packet, callback = r => r) {
|
||||
return debuggerClient.request(packet).then(callback);
|
||||
}
|
||||
|
||||
function resume() {
|
||||
return new Promise(resolve => {
|
||||
threadClient.resume(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function stepIn() {
|
||||
return new Promise(resolve => {
|
||||
threadClient.stepIn(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function stepOver() {
|
||||
return new Promise(resolve => {
|
||||
threadClient.stepOver(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function stepOut() {
|
||||
return new Promise(resolve => {
|
||||
threadClient.stepOut(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function rewind() {
|
||||
return new Promise(resolve => {
|
||||
threadClient.rewind(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function reverseStepIn() {
|
||||
return new Promise(resolve => {
|
||||
threadClient.reverseStepIn(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function reverseStepOver() {
|
||||
return new Promise(resolve => {
|
||||
threadClient.reverseStepOver(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function reverseStepOut() {
|
||||
return new Promise(resolve => {
|
||||
threadClient.reverseStepOut(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function breakOnNext() {
|
||||
return threadClient.breakOnNext();
|
||||
}
|
||||
|
||||
function sourceContents(sourceId) {
|
||||
const sourceClient = threadClient.source({
|
||||
actor: sourceId
|
||||
});
|
||||
return sourceClient.source();
|
||||
}
|
||||
|
||||
function getBreakpointByLocation(location) {
|
||||
const id = (0, _breakpoint.makePendingLocationId)(location);
|
||||
const bpClient = bpClients[id];
|
||||
|
||||
if (bpClient) {
|
||||
const {
|
||||
actor,
|
||||
url,
|
||||
line,
|
||||
column,
|
||||
condition
|
||||
} = bpClient.location;
|
||||
return {
|
||||
id: bpClient.actor,
|
||||
condition,
|
||||
actualLocation: {
|
||||
line,
|
||||
column,
|
||||
sourceId: actor,
|
||||
sourceUrl: url
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function setBreakpoint(location, condition, noSliding) {
|
||||
const sourceClient = threadClient.source({
|
||||
actor: location.sourceId
|
||||
});
|
||||
return sourceClient.setBreakpoint({
|
||||
line: location.line,
|
||||
column: location.column,
|
||||
condition,
|
||||
noSliding
|
||||
}).then(([{
|
||||
actualLocation
|
||||
}, bpClient]) => {
|
||||
actualLocation = (0, _create.createBreakpointLocation)(location, actualLocation);
|
||||
const id = (0, _breakpoint.makePendingLocationId)(actualLocation);
|
||||
bpClients[id] = bpClient;
|
||||
bpClient.location.line = actualLocation.line;
|
||||
bpClient.location.column = actualLocation.column;
|
||||
bpClient.location.url = actualLocation.sourceUrl || "";
|
||||
return {
|
||||
id,
|
||||
actualLocation
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function removeBreakpoint(generatedLocation) {
|
||||
try {
|
||||
const id = (0, _breakpoint.makePendingLocationId)(generatedLocation);
|
||||
const bpClient = bpClients[id];
|
||||
|
||||
if (!bpClient) {
|
||||
console.warn("No breakpoint to delete on server");
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
delete bpClients[id];
|
||||
return bpClient.remove();
|
||||
} catch (_error) {
|
||||
console.warn("No breakpoint to delete on server");
|
||||
}
|
||||
}
|
||||
|
||||
function setBreakpointCondition(breakpointId, location, condition, noSliding) {
|
||||
const bpClient = bpClients[breakpointId];
|
||||
delete bpClients[breakpointId];
|
||||
return bpClient.setCondition(threadClient, condition, noSliding).then(_bpClient => {
|
||||
bpClients[breakpointId] = _bpClient;
|
||||
return {
|
||||
id: breakpointId
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async function evaluateInFrame(script, frameId) {
|
||||
return evaluate(script, {
|
||||
frameId
|
||||
});
|
||||
}
|
||||
|
||||
async function evaluateExpressions(scripts, frameId) {
|
||||
return Promise.all(scripts.map(script => evaluate(script, {
|
||||
frameId
|
||||
})));
|
||||
}
|
||||
|
||||
function evaluate(script, {
|
||||
frameId
|
||||
} = {}) {
|
||||
const params = frameId ? {
|
||||
frameActor: frameId
|
||||
} : {};
|
||||
|
||||
if (!tabTarget || !tabTarget.activeConsole || !script) {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
return new Promise(resolve => {
|
||||
tabTarget.activeConsole.evaluateJSAsync(script, result => resolve(result), params);
|
||||
});
|
||||
}
|
||||
|
||||
function autocomplete(input, cursor, frameId) {
|
||||
if (!tabTarget || !tabTarget.activeConsole || !input) {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
return new Promise(resolve => {
|
||||
tabTarget.activeConsole.autocomplete(input, cursor, result => resolve(result), frameId);
|
||||
});
|
||||
}
|
||||
|
||||
function debuggeeCommand(script) {
|
||||
tabTarget.activeConsole.evaluateJS(script, () => {}, {});
|
||||
|
||||
if (!debuggerClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
const consoleActor = tabTarget.form.consoleActor;
|
||||
|
||||
const request = debuggerClient._activeRequests.get(consoleActor);
|
||||
|
||||
request.emit("json-reply", {});
|
||||
|
||||
debuggerClient._activeRequests.delete(consoleActor);
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function navigate(url) {
|
||||
return tabTarget.activeTab.navigateTo(url);
|
||||
}
|
||||
|
||||
function reload() {
|
||||
return tabTarget.activeTab.reload();
|
||||
}
|
||||
|
||||
function getProperties(grip) {
|
||||
const objClient = threadClient.pauseGrip(grip);
|
||||
return objClient.getPrototypeAndProperties().then(resp => {
|
||||
const {
|
||||
ownProperties,
|
||||
safeGetterValues
|
||||
} = resp;
|
||||
|
||||
for (const name in safeGetterValues) {
|
||||
const {
|
||||
enumerable,
|
||||
writable,
|
||||
getterValue
|
||||
} = safeGetterValues[name];
|
||||
ownProperties[name] = {
|
||||
enumerable,
|
||||
writable,
|
||||
value: getterValue
|
||||
};
|
||||
}
|
||||
|
||||
return resp;
|
||||
});
|
||||
}
|
||||
|
||||
async function getFrameScopes(frame) {
|
||||
if (frame.scope) {
|
||||
return frame.scope;
|
||||
}
|
||||
|
||||
return threadClient.getEnvironment(frame.id);
|
||||
}
|
||||
|
||||
function pauseOnExceptions(shouldPauseOnExceptions, shouldPauseOnCaughtExceptions) {
|
||||
return threadClient.pauseOnExceptions(shouldPauseOnExceptions, // Providing opposite value because server
|
||||
// uses "shouldIgnoreCaughtExceptions"
|
||||
!shouldPauseOnCaughtExceptions);
|
||||
}
|
||||
|
||||
function prettyPrint(sourceId, indentSize) {
|
||||
const sourceClient = threadClient.source({
|
||||
actor: sourceId
|
||||
});
|
||||
return sourceClient.prettyPrint(indentSize);
|
||||
}
|
||||
|
||||
async function blackBox(sourceId, isBlackBoxed) {
|
||||
const sourceClient = threadClient.source({
|
||||
actor: sourceId
|
||||
});
|
||||
|
||||
if (isBlackBoxed) {
|
||||
await sourceClient.unblackBox();
|
||||
} else {
|
||||
await sourceClient.blackBox();
|
||||
}
|
||||
|
||||
return {
|
||||
isBlackBoxed: !isBlackBoxed
|
||||
};
|
||||
}
|
||||
|
||||
function disablePrettyPrint(sourceId) {
|
||||
const sourceClient = threadClient.source({
|
||||
actor: sourceId
|
||||
});
|
||||
return sourceClient.disablePrettyPrint();
|
||||
}
|
||||
|
||||
async function setPausePoints(sourceId, pausePoints) {
|
||||
return sendPacket({
|
||||
to: sourceId,
|
||||
type: "setPausePoints",
|
||||
pausePoints
|
||||
});
|
||||
}
|
||||
|
||||
async function setSkipPausing(shouldSkip) {
|
||||
return threadClient.request({
|
||||
skip: shouldSkip,
|
||||
to: threadClient.actor,
|
||||
type: "skipPausing"
|
||||
});
|
||||
}
|
||||
|
||||
function interrupt() {
|
||||
return threadClient.interrupt();
|
||||
}
|
||||
|
||||
function eventListeners() {
|
||||
return threadClient.eventListeners();
|
||||
}
|
||||
|
||||
function pauseGrip(func) {
|
||||
return threadClient.pauseGrip(func);
|
||||
}
|
||||
|
||||
async function fetchSources() {
|
||||
const {
|
||||
sources
|
||||
} = await threadClient.getSources();
|
||||
return sources.map(source => (0, _create.createSource)(source, {
|
||||
supportsWasm
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* Temporary helper to check if the current server will support a call to
|
||||
* listWorkers. On Fennec 60 or older, the call will silently crash and prevent
|
||||
* the client from resuming.
|
||||
* XXX: Remove when FF60 for Android is no longer used or available.
|
||||
*
|
||||
* See https://bugzilla.mozilla.org/show_bug.cgi?id=1443550 for more details.
|
||||
*/
|
||||
|
||||
|
||||
async function checkServerSupportsListWorkers() {
|
||||
const root = await tabTarget.root; // root is not available on all debug targets.
|
||||
|
||||
if (!root) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const deviceFront = await (0, _frontsDevice.getDeviceFront)(debuggerClient, root);
|
||||
const description = await deviceFront.getDescription();
|
||||
const isFennec = description.apptype === "mobile/android";
|
||||
|
||||
if (!isFennec) {
|
||||
// Explicitly return true early to avoid calling Services.vs.compare.
|
||||
// This would force us to extent the Services shim provided by
|
||||
// devtools-modules, used when this code runs in a tab.
|
||||
return true;
|
||||
} // We are only interested in Fennec release versions here.
|
||||
// We assume that the server fix for Bug 1443550 will land in FF61.
|
||||
|
||||
|
||||
const version = description.platformversion;
|
||||
return _devtoolsModules.Services.vc.compare(version, "61.0") >= 0;
|
||||
}
|
||||
|
||||
async function fetchWorkers() {
|
||||
// Temporary workaround for Bug 1443550
|
||||
// XXX: Remove when FF60 for Android is no longer used or available.
|
||||
const supportsListWorkers = await checkServerSupportsListWorkers(); // NOTE: The Worker and Browser Content toolboxes do not have a parent
|
||||
// with a listWorkers function
|
||||
// TODO: there is a listWorkers property, but it is not a function on the
|
||||
// parent. Investigate what it is
|
||||
|
||||
if (!threadClient._parent || typeof threadClient._parent.listWorkers != "function" || !supportsListWorkers) {
|
||||
return Promise.resolve({
|
||||
workers: []
|
||||
});
|
||||
}
|
||||
|
||||
return threadClient._parent.listWorkers();
|
||||
}
|
||||
|
||||
const clientCommands = {
|
||||
autocomplete,
|
||||
blackBox,
|
||||
interrupt,
|
||||
eventListeners,
|
||||
pauseGrip,
|
||||
resume,
|
||||
stepIn,
|
||||
stepOut,
|
||||
stepOver,
|
||||
rewind,
|
||||
reverseStepIn,
|
||||
reverseStepOut,
|
||||
reverseStepOver,
|
||||
breakOnNext,
|
||||
sourceContents,
|
||||
getBreakpointByLocation,
|
||||
setBreakpoint,
|
||||
removeBreakpoint,
|
||||
setBreakpointCondition,
|
||||
evaluate,
|
||||
evaluateInFrame,
|
||||
evaluateExpressions,
|
||||
debuggeeCommand,
|
||||
navigate,
|
||||
reload,
|
||||
getProperties,
|
||||
getFrameScopes,
|
||||
pauseOnExceptions,
|
||||
prettyPrint,
|
||||
disablePrettyPrint,
|
||||
fetchSources,
|
||||
fetchWorkers,
|
||||
sendPacket,
|
||||
setPausePoints,
|
||||
setSkipPausing
|
||||
};
|
||||
exports.setupCommands = setupCommands;
|
||||
exports.clientCommands = clientCommands;
|
|
@ -0,0 +1,85 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.createFrame = createFrame;
|
||||
exports.createSource = createSource;
|
||||
exports.createPause = createPause;
|
||||
exports.createBreakpointLocation = createBreakpointLocation;
|
||||
|
||||
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; }
|
||||
|
||||
/* 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/>. */
|
||||
// This module converts Firefox specific types to the generic types
|
||||
function createFrame(frame) {
|
||||
if (!frame) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let title;
|
||||
|
||||
if (frame.type == "call") {
|
||||
const c = frame.callee;
|
||||
title = c.name || c.userDisplayName || c.displayName || L10N.getStr("anonymous");
|
||||
} else {
|
||||
title = `(${frame.type})`;
|
||||
}
|
||||
|
||||
const location = {
|
||||
sourceId: frame.where.source.actor,
|
||||
line: frame.where.line,
|
||||
column: frame.where.column
|
||||
};
|
||||
return {
|
||||
id: frame.actor,
|
||||
displayName: title,
|
||||
location,
|
||||
generatedLocation: location,
|
||||
this: frame.this,
|
||||
scope: frame.environment
|
||||
};
|
||||
}
|
||||
|
||||
function createSource(source, {
|
||||
supportsWasm
|
||||
}) {
|
||||
return {
|
||||
id: source.actor,
|
||||
url: source.url,
|
||||
isPrettyPrinted: false,
|
||||
isWasm: supportsWasm && source.introductionType === "wasm",
|
||||
sourceMapURL: source.sourceMapURL,
|
||||
isBlackBoxed: false,
|
||||
loadedState: "unloaded"
|
||||
};
|
||||
}
|
||||
|
||||
function createPause(packet, response) {
|
||||
// NOTE: useful when the debugger is already paused
|
||||
const frame = packet.frame || response.frames[0];
|
||||
return _objectSpread({}, packet, {
|
||||
frame: createFrame(frame),
|
||||
frames: response.frames.map(createFrame)
|
||||
});
|
||||
} // Firefox only returns `actualLocation` if it actually changed,
|
||||
// but we want it always to exist. Format `actualLocation` if it
|
||||
// exists, otherwise use `location`.
|
||||
|
||||
|
||||
function createBreakpointLocation(location, actualLocation) {
|
||||
if (!actualLocation) {
|
||||
return location;
|
||||
}
|
||||
|
||||
return {
|
||||
sourceId: actualLocation.source.actor,
|
||||
sourceUrl: actualLocation.source.url,
|
||||
line: actualLocation.line,
|
||||
column: actualLocation.column
|
||||
};
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.clientEvents = exports.setupEvents = undefined;
|
||||
|
||||
var _create = require("./create");
|
||||
|
||||
var _sourceQueue = require("../../utils/source-queue");
|
||||
|
||||
var _sourceQueue2 = _interopRequireDefault(_sourceQueue);
|
||||
|
||||
var _prefs = require("../../utils/prefs");
|
||||
|
||||
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/>. */
|
||||
const CALL_STACK_PAGE_SIZE = 1000;
|
||||
let threadClient;
|
||||
let actions;
|
||||
let supportsWasm;
|
||||
let isInterrupted;
|
||||
|
||||
function setupEvents(dependencies) {
|
||||
threadClient = dependencies.threadClient;
|
||||
actions = dependencies.actions;
|
||||
supportsWasm = dependencies.supportsWasm;
|
||||
|
||||
_sourceQueue2.default.initialize({
|
||||
actions,
|
||||
supportsWasm,
|
||||
createSource: _create.createSource
|
||||
});
|
||||
|
||||
if (threadClient) {
|
||||
Object.keys(clientEvents).forEach(eventName => {
|
||||
threadClient.addListener(eventName, clientEvents[eventName]);
|
||||
});
|
||||
|
||||
if (threadClient._parent) {
|
||||
threadClient._parent.addListener("workerListChanged", workerListChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function paused(_, packet) {
|
||||
// If paused by an explicit interrupt, which are generated by the
|
||||
// slow script dialog and internal events such as setting
|
||||
// breakpoints, ignore the event.
|
||||
const {
|
||||
why
|
||||
} = packet;
|
||||
|
||||
if (why.type === "interrupted" && !packet.why.onNext) {
|
||||
isInterrupted = true;
|
||||
return;
|
||||
} // Eagerly fetch the frames
|
||||
|
||||
|
||||
const response = await threadClient.getFrames(0, CALL_STACK_PAGE_SIZE);
|
||||
|
||||
if (why.type != "alreadyPaused") {
|
||||
const pause = (0, _create.createPause)(packet, response);
|
||||
await _sourceQueue2.default.flush();
|
||||
actions.paused(pause);
|
||||
}
|
||||
}
|
||||
|
||||
function resumed(_, packet) {
|
||||
// NOTE: the client suppresses resumed events while interrupted
|
||||
// to prevent unintentional behavior.
|
||||
// see [client docs](../README.md#interrupted) for more information.
|
||||
if (isInterrupted) {
|
||||
isInterrupted = false;
|
||||
return;
|
||||
}
|
||||
|
||||
actions.resumed(packet);
|
||||
}
|
||||
|
||||
function newSource(_, {
|
||||
source
|
||||
}) {
|
||||
_sourceQueue2.default.queue(source);
|
||||
|
||||
if (_prefs.features.eventListeners) {
|
||||
actions.fetchEventListeners();
|
||||
}
|
||||
}
|
||||
|
||||
function workerListChanged() {
|
||||
actions.updateWorkers();
|
||||
}
|
||||
|
||||
const clientEvents = {
|
||||
paused,
|
||||
resumed,
|
||||
newSource
|
||||
};
|
||||
exports.setupEvents = setupEvents;
|
||||
exports.clientEvents = clientEvents;
|
|
@ -0,0 +1,21 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getDeviceFront = getDeviceFront;
|
||||
|
||||
/* 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 getDeviceFront() {
|
||||
return {
|
||||
getDescription: function () {
|
||||
return {
|
||||
// Return anything that will not match Fennec v60
|
||||
apptype: "apptype",
|
||||
version: "version"
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
# 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(
|
||||
'commands.js',
|
||||
'create.js',
|
||||
'events.js',
|
||||
'fronts-device.js',
|
||||
)
|
|
@ -0,0 +1,73 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.onConnect = undefined;
|
||||
|
||||
var _firefox = require("./firefox");
|
||||
|
||||
var firefox = _interopRequireWildcard(_firefox);
|
||||
|
||||
var _prefs = require("../utils/prefs");
|
||||
|
||||
var _dbg = require("../utils/dbg");
|
||||
|
||||
var _bootstrap = require("../utils/bootstrap");
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
||||
|
||||
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 loadFromPrefs(actions) {
|
||||
const {
|
||||
pauseOnExceptions,
|
||||
pauseOnCaughtExceptions
|
||||
} = _prefs.prefs;
|
||||
|
||||
if (pauseOnExceptions || pauseOnCaughtExceptions) {
|
||||
return actions.pauseOnExceptions(pauseOnExceptions, pauseOnCaughtExceptions);
|
||||
}
|
||||
}
|
||||
|
||||
async function onConnect(connection, {
|
||||
services,
|
||||
toolboxActions
|
||||
}) {
|
||||
// NOTE: the landing page does not connect to a JS process
|
||||
if (!connection) {
|
||||
return;
|
||||
}
|
||||
|
||||
const commands = firefox.clientCommands;
|
||||
const {
|
||||
store,
|
||||
actions,
|
||||
selectors
|
||||
} = (0, _bootstrap.bootstrapStore)(commands, {
|
||||
services,
|
||||
toolboxActions
|
||||
});
|
||||
const workers = (0, _bootstrap.bootstrapWorkers)();
|
||||
await firefox.onConnect(connection, actions);
|
||||
await loadFromPrefs(actions);
|
||||
(0, _dbg.setupHelper)({
|
||||
store,
|
||||
actions,
|
||||
selectors,
|
||||
workers: _objectSpread({}, workers, services),
|
||||
connection,
|
||||
client: firefox.clientCommands
|
||||
});
|
||||
(0, _bootstrap.bootstrapApp)(store);
|
||||
return {
|
||||
store,
|
||||
actions,
|
||||
selectors,
|
||||
client: commands
|
||||
};
|
||||
}
|
||||
|
||||
exports.onConnect = onConnect;
|
|
@ -0,0 +1,13 @@
|
|||
# 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 += [
|
||||
'firefox',
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'firefox.js',
|
||||
'index.js',
|
||||
)
|
|
@ -0,0 +1,297 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _propTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
var _propTypes2 = _interopRequireDefault(_propTypes);
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _prefs = require("../utils/prefs");
|
||||
|
||||
var _actions = require("../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _ShortcutsModal = require("./ShortcutsModal");
|
||||
|
||||
var _selectors = require("../selectors/index");
|
||||
|
||||
var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"];
|
||||
|
||||
var _devtoolsSplitter = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-splitter"];
|
||||
|
||||
var _devtoolsSplitter2 = _interopRequireDefault(_devtoolsSplitter);
|
||||
|
||||
var _ProjectSearch = require("./ProjectSearch");
|
||||
|
||||
var _ProjectSearch2 = _interopRequireDefault(_ProjectSearch);
|
||||
|
||||
var _PrimaryPanes = require("./PrimaryPanes/index");
|
||||
|
||||
var _PrimaryPanes2 = _interopRequireDefault(_PrimaryPanes);
|
||||
|
||||
var _Editor = require("./Editor/index");
|
||||
|
||||
var _Editor2 = _interopRequireDefault(_Editor);
|
||||
|
||||
var _SecondaryPanes = require("./SecondaryPanes/index");
|
||||
|
||||
var _SecondaryPanes2 = _interopRequireDefault(_SecondaryPanes);
|
||||
|
||||
var _WelcomeBox = require("./WelcomeBox");
|
||||
|
||||
var _WelcomeBox2 = _interopRequireDefault(_WelcomeBox);
|
||||
|
||||
var _Tabs = require("./Editor/Tabs");
|
||||
|
||||
var _Tabs2 = _interopRequireDefault(_Tabs);
|
||||
|
||||
var _QuickOpenModal = require("./QuickOpenModal");
|
||||
|
||||
var _QuickOpenModal2 = _interopRequireDefault(_QuickOpenModal);
|
||||
|
||||
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/>. */
|
||||
const shortcuts = new _devtoolsModules.KeyShortcuts({
|
||||
window
|
||||
});
|
||||
const {
|
||||
appinfo
|
||||
} = _devtoolsModules.Services;
|
||||
const isMacOS = appinfo.OS === "Darwin";
|
||||
const horizontalLayoutBreakpoint = window.matchMedia("(min-width: 800px)");
|
||||
const verticalLayoutBreakpoint = window.matchMedia("(min-width: 10px) and (max-width: 800px)");
|
||||
|
||||
class App extends _react.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.getChildContext = () => {
|
||||
return {
|
||||
shortcuts
|
||||
};
|
||||
};
|
||||
|
||||
this.onEscape = (_, e) => {
|
||||
const {
|
||||
activeSearch,
|
||||
closeActiveSearch,
|
||||
closeQuickOpen,
|
||||
quickOpenEnabled
|
||||
} = this.props;
|
||||
|
||||
if (activeSearch) {
|
||||
e.preventDefault();
|
||||
closeActiveSearch();
|
||||
}
|
||||
|
||||
if (quickOpenEnabled) {
|
||||
e.preventDefault();
|
||||
closeQuickOpen();
|
||||
}
|
||||
};
|
||||
|
||||
this.onCommandSlash = () => {
|
||||
this.toggleShortcutsModal();
|
||||
};
|
||||
|
||||
this.toggleQuickOpenModal = (_, e, query) => {
|
||||
const {
|
||||
quickOpenEnabled,
|
||||
openQuickOpen,
|
||||
closeQuickOpen
|
||||
} = this.props;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (quickOpenEnabled === true) {
|
||||
closeQuickOpen();
|
||||
return;
|
||||
}
|
||||
|
||||
if (query != null) {
|
||||
openQuickOpen(query);
|
||||
return;
|
||||
}
|
||||
|
||||
openQuickOpen();
|
||||
return;
|
||||
};
|
||||
|
||||
this.onLayoutChange = () => {
|
||||
this.setOrientation();
|
||||
};
|
||||
|
||||
this.renderEditorPane = () => {
|
||||
const {
|
||||
startPanelCollapsed,
|
||||
endPanelCollapsed
|
||||
} = this.props;
|
||||
const {
|
||||
endPanelSize,
|
||||
startPanelSize
|
||||
} = this.state;
|
||||
const horizontal = this.isHorizontal();
|
||||
return _react2.default.createElement("div", {
|
||||
className: "editor-pane"
|
||||
}, _react2.default.createElement("div", {
|
||||
className: "editor-container"
|
||||
}, _react2.default.createElement(_Tabs2.default, {
|
||||
startPanelCollapsed: startPanelCollapsed,
|
||||
endPanelCollapsed: endPanelCollapsed,
|
||||
horizontal: horizontal,
|
||||
startPanelSize: startPanelSize,
|
||||
endPanelSize: endPanelSize
|
||||
}), _react2.default.createElement(_Editor2.default, {
|
||||
horizontal: horizontal,
|
||||
startPanelSize: startPanelSize,
|
||||
endPanelSize: endPanelSize
|
||||
}), !this.props.selectedSource ? _react2.default.createElement(_WelcomeBox2.default, {
|
||||
horizontal: horizontal
|
||||
}) : null, _react2.default.createElement(_ProjectSearch2.default, null)));
|
||||
};
|
||||
|
||||
this.renderLayout = () => {
|
||||
const {
|
||||
startPanelCollapsed,
|
||||
endPanelCollapsed
|
||||
} = this.props;
|
||||
const horizontal = this.isHorizontal();
|
||||
const maxSize = horizontal ? "70%" : "95%";
|
||||
const primaryInitialSize = horizontal ? "250px" : "150px";
|
||||
return _react2.default.createElement(_devtoolsSplitter2.default, {
|
||||
style: {
|
||||
width: "100vw"
|
||||
},
|
||||
initialHeight: 400,
|
||||
initialWidth: 300,
|
||||
minSize: 30,
|
||||
maxSize: maxSize,
|
||||
splitterSize: 1,
|
||||
vert: horizontal,
|
||||
startPanel: _react2.default.createElement(_devtoolsSplitter2.default, {
|
||||
style: {
|
||||
width: "100vw"
|
||||
},
|
||||
initialSize: primaryInitialSize,
|
||||
minSize: 30,
|
||||
maxSize: "85%",
|
||||
splitterSize: 1,
|
||||
startPanelCollapsed: startPanelCollapsed,
|
||||
startPanel: _react2.default.createElement(_PrimaryPanes2.default, {
|
||||
horizontal: horizontal
|
||||
}),
|
||||
endPanel: this.renderEditorPane()
|
||||
}),
|
||||
endPanelControl: true,
|
||||
endPanel: _react2.default.createElement(_SecondaryPanes2.default, {
|
||||
horizontal: horizontal,
|
||||
toggleShortcutsModal: () => this.toggleShortcutsModal()
|
||||
}),
|
||||
endPanelCollapsed: endPanelCollapsed
|
||||
});
|
||||
};
|
||||
|
||||
this.state = {
|
||||
shortcutsModalEnabled: false,
|
||||
startPanelSize: 0,
|
||||
endPanelSize: 0
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
horizontalLayoutBreakpoint.addListener(this.onLayoutChange);
|
||||
verticalLayoutBreakpoint.addListener(this.onLayoutChange);
|
||||
this.setOrientation();
|
||||
shortcuts.on(L10N.getStr("symbolSearch.search.key2"), (_, e) => this.toggleQuickOpenModal(_, e, "@"));
|
||||
const searchKeys = [L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key")];
|
||||
searchKeys.forEach(key => shortcuts.on(key, this.toggleQuickOpenModal));
|
||||
shortcuts.on(L10N.getStr("gotoLineModal.key2"), (_, e) => this.toggleQuickOpenModal(_, e, ":"));
|
||||
shortcuts.on("Escape", this.onEscape);
|
||||
shortcuts.on("Cmd+/", this.onCommandSlash);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
horizontalLayoutBreakpoint.removeListener(this.onLayoutChange);
|
||||
verticalLayoutBreakpoint.removeListener(this.onLayoutChange);
|
||||
shortcuts.off(L10N.getStr("symbolSearch.search.key2"), this.toggleQuickOpenModal);
|
||||
const searchKeys = [L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key")];
|
||||
searchKeys.forEach(key => shortcuts.off(key, this.toggleQuickOpenModal));
|
||||
shortcuts.off(L10N.getStr("gotoLineModal.key2"), this.toggleQuickOpenModal);
|
||||
shortcuts.off("Escape", this.onEscape);
|
||||
}
|
||||
|
||||
isHorizontal() {
|
||||
return this.props.orientation === "horizontal";
|
||||
}
|
||||
|
||||
setOrientation() {
|
||||
// If the orientation does not match (if it is not visible) it will
|
||||
// not setOrientation, or if it is the same as before, calling
|
||||
// setOrientation will not cause a rerender.
|
||||
if (horizontalLayoutBreakpoint.matches) {
|
||||
this.props.setOrientation("horizontal");
|
||||
} else if (verticalLayoutBreakpoint.matches) {
|
||||
this.props.setOrientation("vertical");
|
||||
}
|
||||
}
|
||||
|
||||
toggleShortcutsModal() {
|
||||
this.setState(prevState => ({
|
||||
shortcutsModalEnabled: !prevState.shortcutsModalEnabled
|
||||
}));
|
||||
}
|
||||
|
||||
renderShortcutsModal() {
|
||||
const additionalClass = isMacOS ? "mac" : "";
|
||||
|
||||
if (!_prefs.features.shortcuts) {
|
||||
return;
|
||||
}
|
||||
|
||||
return _react2.default.createElement(_ShortcutsModal.ShortcutsModal, {
|
||||
additionalClass: additionalClass,
|
||||
enabled: this.state.shortcutsModalEnabled,
|
||||
handleClose: () => this.toggleShortcutsModal()
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
quickOpenEnabled
|
||||
} = this.props;
|
||||
return _react2.default.createElement("div", {
|
||||
className: "debugger"
|
||||
}, this.renderLayout(), quickOpenEnabled === true && _react2.default.createElement(_QuickOpenModal2.default, {
|
||||
shortcutsModalEnabled: this.state.shortcutsModalEnabled,
|
||||
toggleShortcutsModal: () => this.toggleShortcutsModal()
|
||||
}), this.renderShortcutsModal());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
App.childContextTypes = {
|
||||
shortcuts: _propTypes2.default.object
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
selectedSource: (0, _selectors.getSelectedSource)(state),
|
||||
startPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "start"),
|
||||
endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end"),
|
||||
activeSearch: (0, _selectors.getActiveSearch)(state),
|
||||
quickOpenEnabled: (0, _selectors.getQuickOpenEnabled)(state),
|
||||
orientation: (0, _selectors.getOrientation)(state)
|
||||
});
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(App);
|
|
@ -0,0 +1,138 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _reactDom = require("devtools/client/shared/vendor/react-dom");
|
||||
|
||||
var _reactDom2 = _interopRequireDefault(_reactDom);
|
||||
|
||||
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
|
||||
|
||||
var _classnames2 = _interopRequireDefault(_classnames);
|
||||
|
||||
var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"];
|
||||
|
||||
var _Svg2 = _interopRequireDefault(_Svg);
|
||||
|
||||
var _editor = require("../../utils/editor/index");
|
||||
|
||||
var _prefs = require("../../utils/prefs");
|
||||
|
||||
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/>. */
|
||||
const breakpointSvg = document.createElement("div");
|
||||
|
||||
_reactDom2.default.render(_react2.default.createElement(_Svg2.default, {
|
||||
name: "breakpoint"
|
||||
}), breakpointSvg);
|
||||
|
||||
function makeMarker(isDisabled) {
|
||||
const bp = breakpointSvg.cloneNode(true);
|
||||
bp.className = (0, _classnames2.default)("editor new-breakpoint", {
|
||||
"breakpoint-disabled": isDisabled,
|
||||
"folding-enabled": _prefs.features.codeFolding
|
||||
});
|
||||
return bp;
|
||||
}
|
||||
|
||||
class Breakpoint extends _react.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.addBreakpoint = () => {
|
||||
const {
|
||||
breakpoint,
|
||||
editor,
|
||||
selectedSource
|
||||
} = this.props; // Hidden Breakpoints are never rendered on the client
|
||||
|
||||
if (breakpoint.hidden) {
|
||||
return;
|
||||
} // NOTE: we need to wait for the breakpoint to be loaded
|
||||
// to get the generated location
|
||||
|
||||
|
||||
if (!selectedSource || breakpoint.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceId = selectedSource.id;
|
||||
const line = (0, _editor.toEditorLine)(sourceId, breakpoint.location.line);
|
||||
editor.codeMirror.setGutterMarker(line, "breakpoints", makeMarker(breakpoint.disabled));
|
||||
editor.codeMirror.addLineClass(line, "line", "new-breakpoint");
|
||||
|
||||
if (breakpoint.condition) {
|
||||
editor.codeMirror.addLineClass(line, "line", "has-condition");
|
||||
} else {
|
||||
editor.codeMirror.removeLineClass(line, "line", "has-condition");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const {
|
||||
editor,
|
||||
breakpoint,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
return editor !== nextProps.editor || breakpoint.disabled !== nextProps.breakpoint.disabled || breakpoint.hidden !== nextProps.breakpoint.hidden || breakpoint.condition !== nextProps.breakpoint.condition || breakpoint.loading !== nextProps.breakpoint.loading || selectedSource !== nextProps.selectedSource;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.addBreakpoint();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.addBreakpoint();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const {
|
||||
editor,
|
||||
breakpoint,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
|
||||
if (!selectedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (breakpoint.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceId = selectedSource.id;
|
||||
const doc = (0, _editor.getDocument)(sourceId);
|
||||
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
const line = (0, _editor.toEditorLine)(sourceId, breakpoint.location.line); // NOTE: when we upgrade codemirror we can use `doc.setGutterMarker`
|
||||
|
||||
if (doc.setGutterMarker) {
|
||||
doc.setGutterMarker(line, "breakpoints", null);
|
||||
} else {
|
||||
editor.codeMirror.setGutterMarker(line, "breakpoints", null);
|
||||
}
|
||||
|
||||
doc.removeLineClass(line, "line", "new-breakpoint");
|
||||
doc.removeLineClass(line, "line", "has-condition");
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.default = Breakpoint;
|
|
@ -0,0 +1,63 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _Breakpoint = require("./Breakpoint");
|
||||
|
||||
var _Breakpoint2 = _interopRequireDefault(_Breakpoint);
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _breakpoint = require("../../utils/breakpoint/index");
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
class Breakpoints extends _react.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (nextProps.selectedSource && !(0, _source.isLoaded)(nextProps.selectedSource)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
breakpoints,
|
||||
selectedSource,
|
||||
editor
|
||||
} = this.props;
|
||||
|
||||
if (!selectedSource || !breakpoints || selectedSource.get("isBlackBoxed")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return _react2.default.createElement("div", null, breakpoints.valueSeq().map(bp => {
|
||||
return _react2.default.createElement(_Breakpoint2.default, {
|
||||
key: (0, _breakpoint.makeLocationId)(bp.location),
|
||||
breakpoint: bp,
|
||||
selectedSource: selectedSource,
|
||||
editor: editor
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(state => ({
|
||||
breakpoints: (0, _selectors.getVisibleBreakpoints)(state),
|
||||
selectedSource: (0, _selectors.getSelectedSource)(state)
|
||||
}))(Breakpoints);
|
|
@ -0,0 +1,99 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _editor = require("../../utils/editor/index");
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
class CallSite extends _react.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.addCallSite = nextProps => {
|
||||
const {
|
||||
editor,
|
||||
callSite,
|
||||
breakpoint,
|
||||
source
|
||||
} = nextProps || this.props;
|
||||
const className = !breakpoint ? "call-site" : "call-site-bp";
|
||||
const sourceId = source.get("id");
|
||||
const editorRange = (0, _editor.toEditorRange)(sourceId, callSite.location);
|
||||
this.marker = (0, _editor.markText)(editor, className, editorRange);
|
||||
};
|
||||
|
||||
this.clearCallSite = () => {
|
||||
if (this.marker) {
|
||||
this.marker.clear();
|
||||
this.marker = null;
|
||||
}
|
||||
};
|
||||
|
||||
this.marker = undefined;
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return this.props.editor !== nextProps.editor;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
breakpoint,
|
||||
showCallSite
|
||||
} = this.props;
|
||||
|
||||
if (!breakpoint && !showCallSite) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.addCallSite();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const {
|
||||
breakpoint,
|
||||
showCallSite
|
||||
} = this.props;
|
||||
|
||||
if (nextProps.breakpoint !== breakpoint) {
|
||||
if (this.marker) {
|
||||
this.clearCallSite();
|
||||
}
|
||||
|
||||
if (nextProps.showCallSite) {
|
||||
this.addCallSite(nextProps);
|
||||
}
|
||||
}
|
||||
|
||||
if (nextProps.showCallSite !== showCallSite) {
|
||||
if (nextProps.showCallSite) {
|
||||
if (!this.marker) {
|
||||
this.addCallSite();
|
||||
}
|
||||
} else if (!nextProps.breakpoint) {
|
||||
this.clearCallSite();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (!this.marker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.marker.clear();
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.default = CallSite;
|
|
@ -0,0 +1,257 @@
|
|||
"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 _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
var _CallSite = require("./CallSite");
|
||||
|
||||
var _CallSite2 = _interopRequireDefault(_CallSite);
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _editor = require("../../utils/editor/index");
|
||||
|
||||
var _wasm = require("../../utils/wasm");
|
||||
|
||||
var _actions = require("../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
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 getCallSiteAtLocation(callSites, location) {
|
||||
return callSites.find(callSite => (0, _lodash.isEqualWith)(callSite.location, location, (cloc, loc) => {
|
||||
return loc.line === cloc.start.line && loc.column >= cloc.start.column && loc.column <= cloc.end.column;
|
||||
}));
|
||||
}
|
||||
|
||||
class CallSites extends _react.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onKeyUp = e => {
|
||||
if (e.key === "Alt") {
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
showCallSites: false
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.onKeyDown = e => {
|
||||
if (e.key === "Alt") {
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
showCallSites: true
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.state = {
|
||||
showCallSites: false
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
editor
|
||||
} = this.props;
|
||||
const codeMirrorWrapper = editor.codeMirror.getWrapperElement();
|
||||
codeMirrorWrapper.addEventListener("click", e => this.onTokenClick(e));
|
||||
document.body.addEventListener("keydown", this.onKeyDown);
|
||||
document.body.addEventListener("keyup", this.onKeyUp);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const {
|
||||
editor
|
||||
} = this.props;
|
||||
const codeMirrorWrapper = editor.codeMirror.getWrapperElement();
|
||||
codeMirrorWrapper.removeEventListener("click", e => this.onTokenClick(e));
|
||||
document.body.removeEventListener("keydown", this.onKeyDown);
|
||||
document.body.removeEventListener("keyup", this.onKeyUp);
|
||||
}
|
||||
|
||||
onTokenClick(e) {
|
||||
const {
|
||||
target
|
||||
} = e;
|
||||
const {
|
||||
editor,
|
||||
selectedLocation
|
||||
} = this.props;
|
||||
|
||||
if (!e.altKey && !target.classList.contains("call-site-bp") || !target.classList.contains("call-site") && !target.classList.contains("call-site-bp")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
sourceId
|
||||
} = selectedLocation;
|
||||
const {
|
||||
line,
|
||||
column
|
||||
} = (0, _editor.getTokenLocation)(editor.codeMirror, target);
|
||||
this.toggleBreakpoint(line, (0, _wasm.isWasm)(sourceId) ? undefined : column);
|
||||
}
|
||||
|
||||
toggleBreakpoint(line, column = undefined) {
|
||||
const {
|
||||
selectedSource,
|
||||
selectedLocation,
|
||||
addBreakpoint,
|
||||
removeBreakpoint,
|
||||
callSites
|
||||
} = this.props;
|
||||
const callSite = getCallSiteAtLocation(callSites, {
|
||||
line,
|
||||
column
|
||||
});
|
||||
|
||||
if (!callSite) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bp = callSite.breakpoint;
|
||||
|
||||
if (bp && bp.loading || !selectedLocation || !selectedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
sourceId
|
||||
} = selectedLocation;
|
||||
|
||||
if (bp) {
|
||||
// NOTE: it's possible the breakpoint has slid to a column
|
||||
column = column || bp.location.column;
|
||||
removeBreakpoint({
|
||||
sourceId: sourceId,
|
||||
line: line,
|
||||
column
|
||||
});
|
||||
} else {
|
||||
addBreakpoint({
|
||||
sourceId: sourceId,
|
||||
sourceUrl: selectedSource.get("url"),
|
||||
line: line,
|
||||
column: column
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
editor,
|
||||
callSites,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
const {
|
||||
showCallSites
|
||||
} = this.state;
|
||||
let sites;
|
||||
|
||||
if (!callSites) {
|
||||
return null;
|
||||
}
|
||||
|
||||
editor.codeMirror.operation(() => {
|
||||
const childCallSites = callSites.map((callSite, index) => {
|
||||
const props = {
|
||||
key: index,
|
||||
callSite,
|
||||
editor,
|
||||
source: selectedSource,
|
||||
breakpoint: callSite.breakpoint,
|
||||
showCallSite: showCallSites
|
||||
};
|
||||
return _react2.default.createElement(_CallSite2.default, props);
|
||||
});
|
||||
sites = _react2.default.createElement("div", null, childCallSites);
|
||||
});
|
||||
return sites;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getCallSites(symbols, breakpoints) {
|
||||
if (!symbols || !symbols.callExpressions) {
|
||||
return;
|
||||
}
|
||||
|
||||
const callSites = symbols.callExpressions; // NOTE: we create a breakpoint map keyed on location
|
||||
// to speed up the lookups. Hopefully we'll fix the
|
||||
// inconsistency with column offsets so that we can expect
|
||||
// a breakpoint to be added at the beginning of a call expression.
|
||||
|
||||
const bpLocationMap = (0, _lodash.keyBy)(breakpoints.valueSeq().toJS(), ({
|
||||
location
|
||||
}) => locationKey(location));
|
||||
|
||||
function locationKey({
|
||||
line,
|
||||
column
|
||||
}) {
|
||||
return `${line}/${column}`;
|
||||
}
|
||||
|
||||
function findBreakpoint(callSite) {
|
||||
const {
|
||||
location: {
|
||||
start,
|
||||
end
|
||||
}
|
||||
} = callSite;
|
||||
const breakpointId = (0, _lodash.range)(start.column - 1, end.column).map(column => locationKey({
|
||||
line: start.line,
|
||||
column
|
||||
})).find(key => bpLocationMap[key]);
|
||||
|
||||
if (breakpointId) {
|
||||
return bpLocationMap[breakpointId];
|
||||
}
|
||||
}
|
||||
|
||||
return callSites.filter(({
|
||||
location
|
||||
}) => location.start.line === location.end.line).map(callSite => _objectSpread({}, callSite, {
|
||||
breakpoint: findBreakpoint(callSite)
|
||||
}));
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const selectedLocation = (0, _selectors.getSelectedLocation)(state);
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(state);
|
||||
const sourceId = selectedLocation && selectedLocation.sourceId;
|
||||
const symbols = (0, _selectors.getSymbols)(state, selectedSource);
|
||||
const breakpoints = (0, _selectors.getBreakpointsForSource)(state, sourceId);
|
||||
return {
|
||||
selectedLocation,
|
||||
selectedSource,
|
||||
callSites: getCallSites(symbols, breakpoints),
|
||||
breakpoints: breakpoints
|
||||
};
|
||||
};
|
||||
|
||||
const {
|
||||
addBreakpoint,
|
||||
removeBreakpoint
|
||||
} = _actions2.default;
|
||||
const mapDispatchToProps = {
|
||||
addBreakpoint,
|
||||
removeBreakpoint
|
||||
};
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(CallSites);
|
|
@ -0,0 +1,213 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.ConditionalPanel = undefined;
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _reactDom = require("devtools/client/shared/vendor/react-dom");
|
||||
|
||||
var _reactDom2 = _interopRequireDefault(_reactDom);
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _editor = require("../../utils/editor/index");
|
||||
|
||||
var _actions = require("../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
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/>. */
|
||||
class ConditionalPanel extends _react.PureComponent {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.saveAndClose = () => {
|
||||
if (this.input) {
|
||||
this.setBreakpoint(this.input.value);
|
||||
}
|
||||
|
||||
this.props.closeConditionalPanel();
|
||||
};
|
||||
|
||||
this.onKey = e => {
|
||||
if (e.key === "Enter") {
|
||||
this.saveAndClose();
|
||||
} else if (e.key === "Escape") {
|
||||
this.props.closeConditionalPanel();
|
||||
}
|
||||
};
|
||||
|
||||
this.repositionOnScroll = () => {
|
||||
if (this.panelNode && this.scrollParent) {
|
||||
const {
|
||||
scrollLeft
|
||||
} = this.scrollParent;
|
||||
this.panelNode.style.transform = `translateX(${scrollLeft}px)`;
|
||||
}
|
||||
};
|
||||
|
||||
this.cbPanel = null;
|
||||
}
|
||||
|
||||
keepFocusOnInput() {
|
||||
if (this.input) {
|
||||
this.input.focus();
|
||||
}
|
||||
}
|
||||
|
||||
setBreakpoint(condition) {
|
||||
const {
|
||||
selectedLocation,
|
||||
line
|
||||
} = this.props;
|
||||
const sourceId = selectedLocation ? selectedLocation.sourceId : "";
|
||||
const location = {
|
||||
sourceId,
|
||||
line
|
||||
};
|
||||
return this.props.setBreakpointCondition(location, {
|
||||
condition
|
||||
});
|
||||
}
|
||||
|
||||
clearConditionalPanel() {
|
||||
if (this.cbPanel) {
|
||||
this.cbPanel.clear();
|
||||
this.cbPanel = null;
|
||||
}
|
||||
|
||||
if (this.scrollParent) {
|
||||
this.scrollParent.removeEventListener("scroll", this.repositionOnScroll);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
if (this.props.line) {
|
||||
return this.renderToWidget(this.props);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps) {
|
||||
if (nextProps.line) {
|
||||
return this.renderToWidget(nextProps);
|
||||
}
|
||||
|
||||
return this.clearConditionalPanel();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
// This is called if CodeMirror is re-initializing itself before the
|
||||
// user closes the conditional panel. Clear the widget, and re-render it
|
||||
// as soon as this component gets remounted
|
||||
return this.clearConditionalPanel();
|
||||
}
|
||||
|
||||
renderToWidget(props) {
|
||||
if (this.cbPanel) {
|
||||
if (this.props.line && this.props.line == props.line) {
|
||||
return props.closeConditionalPanel();
|
||||
}
|
||||
|
||||
this.clearConditionalPanel();
|
||||
}
|
||||
|
||||
const {
|
||||
selectedLocation,
|
||||
line,
|
||||
editor
|
||||
} = props;
|
||||
const sourceId = selectedLocation ? selectedLocation.sourceId : "";
|
||||
const editorLine = (0, _editor.toEditorLine)(sourceId, line);
|
||||
this.cbPanel = editor.codeMirror.addLineWidget(editorLine, this.renderConditionalPanel(props), {
|
||||
coverGutter: true,
|
||||
noHScroll: false
|
||||
});
|
||||
|
||||
if (this.input) {
|
||||
let parent = this.input.parentNode;
|
||||
|
||||
while (parent) {
|
||||
if (parent instanceof HTMLElement && parent.classList.contains("CodeMirror-scroll")) {
|
||||
this.scrollParent = parent;
|
||||
break;
|
||||
}
|
||||
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
|
||||
if (this.scrollParent) {
|
||||
this.scrollParent.addEventListener("scroll", this.repositionOnScroll);
|
||||
this.repositionOnScroll();
|
||||
}
|
||||
|
||||
this.input.focus();
|
||||
}
|
||||
}
|
||||
|
||||
renderConditionalPanel(props) {
|
||||
const {
|
||||
breakpoint
|
||||
} = props;
|
||||
const condition = breakpoint ? breakpoint.condition : "";
|
||||
const panel = document.createElement("div");
|
||||
|
||||
_reactDom2.default.render(_react2.default.createElement("div", {
|
||||
className: "conditional-breakpoint-panel",
|
||||
onClick: () => this.keepFocusOnInput(),
|
||||
onBlur: this.props.closeConditionalPanel,
|
||||
ref: node => this.panelNode = node
|
||||
}, _react2.default.createElement("div", {
|
||||
className: "prompt"
|
||||
}, "\xBB"), _react2.default.createElement("input", {
|
||||
defaultValue: condition,
|
||||
placeholder: L10N.getStr("editor.conditionalPanel.placeholder"),
|
||||
onKeyDown: this.onKey,
|
||||
ref: input => {
|
||||
this.input = input;
|
||||
this.keepFocusOnInput();
|
||||
}
|
||||
})), panel);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.ConditionalPanel = ConditionalPanel;
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const line = (0, _selectors.getConditionalPanelLine)(state);
|
||||
const selectedLocation = (0, _selectors.getSelectedLocation)(state);
|
||||
return {
|
||||
selectedLocation,
|
||||
breakpoint: (0, _selectors.getBreakpointForLine)(state, selectedLocation.sourceId, line),
|
||||
line
|
||||
};
|
||||
};
|
||||
|
||||
const {
|
||||
setBreakpointCondition,
|
||||
openConditionalPanel,
|
||||
closeConditionalPanel
|
||||
} = _actions2.default;
|
||||
const mapDispatchToProps = {
|
||||
setBreakpointCondition,
|
||||
openConditionalPanel,
|
||||
closeConditionalPanel
|
||||
};
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(ConditionalPanel);
|
|
@ -0,0 +1,134 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.DebugLine = undefined;
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _editor = require("../../utils/editor/index");
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _pause = require("../../utils/pause/index");
|
||||
|
||||
var _indentation = require("../../utils/indentation");
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
/* 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 isDocumentReady(selectedSource, selectedFrame) {
|
||||
return selectedFrame && (0, _source.isLoaded)(selectedSource) && (0, _editor.hasDocument)(selectedFrame.location.sourceId);
|
||||
}
|
||||
|
||||
class DebugLine extends _react.Component {
|
||||
componentDidUpdate(prevProps) {
|
||||
const {
|
||||
why,
|
||||
selectedFrame,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
this.setDebugLine(why, selectedFrame, selectedSource);
|
||||
}
|
||||
|
||||
componentWillUpdate() {
|
||||
const {
|
||||
why,
|
||||
selectedFrame,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
this.clearDebugLine(selectedFrame, selectedSource, why);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
why,
|
||||
selectedFrame,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
this.setDebugLine(why, selectedFrame, selectedSource);
|
||||
}
|
||||
|
||||
setDebugLine(why, selectedFrame, selectedSource) {
|
||||
if (!isDocumentReady(selectedSource, selectedFrame)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceId = selectedFrame.location.sourceId;
|
||||
const doc = (0, _editor.getDocument)(sourceId);
|
||||
let {
|
||||
line,
|
||||
column
|
||||
} = (0, _editor.toEditorPosition)(selectedFrame.location);
|
||||
const {
|
||||
markTextClass,
|
||||
lineClass
|
||||
} = this.getTextClasses(why);
|
||||
doc.addLineClass(line, "line", lineClass);
|
||||
const lineText = doc.getLine(line);
|
||||
column = Math.max(column, (0, _indentation.getIndentation)(lineText));
|
||||
this.debugExpression = doc.markText({
|
||||
ch: column,
|
||||
line
|
||||
}, {
|
||||
ch: null,
|
||||
line
|
||||
}, {
|
||||
className: markTextClass
|
||||
});
|
||||
}
|
||||
|
||||
clearDebugLine(selectedFrame, selectedSource, why) {
|
||||
if (!isDocumentReady(selectedSource, selectedFrame)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.debugExpression) {
|
||||
this.debugExpression.clear();
|
||||
}
|
||||
|
||||
const sourceId = selectedFrame.location.sourceId;
|
||||
const {
|
||||
line
|
||||
} = (0, _editor.toEditorPosition)(selectedFrame.location);
|
||||
const doc = (0, _editor.getDocument)(sourceId);
|
||||
const {
|
||||
lineClass
|
||||
} = this.getTextClasses(why);
|
||||
doc.removeLineClass(line, "line", lineClass);
|
||||
}
|
||||
|
||||
getTextClasses(why) {
|
||||
if ((0, _pause.isException)(why)) {
|
||||
return {
|
||||
markTextClass: "debug-expression-error",
|
||||
lineClass: "new-debug-line-error"
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
markTextClass: "debug-expression",
|
||||
lineClass: "new-debug-line"
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.DebugLine = DebugLine;
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
selectedFrame: (0, _selectors.getVisibleSelectedFrame)(state),
|
||||
selectedSource: (0, _selectors.getSelectedSource)(state),
|
||||
why: (0, _selectors.getPauseReason)(state)
|
||||
});
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps)(DebugLine);
|
|
@ -0,0 +1,242 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"];
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _clipboard = require("../../utils/clipboard");
|
||||
|
||||
var _function = require("../../utils/function");
|
||||
|
||||
var _ast = require("../../utils/ast");
|
||||
|
||||
var _editor = require("../../utils/editor/index");
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _actions = require("../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
||||
|
||||
function getMenuItems(event, {
|
||||
addExpression,
|
||||
editor,
|
||||
evaluateInConsole,
|
||||
flashLineRange,
|
||||
getFunctionLocation,
|
||||
getFunctionText,
|
||||
hasPrettyPrint,
|
||||
jumpToMappedLocation,
|
||||
onGutterContextMenu,
|
||||
selectedLocation,
|
||||
selectedSource,
|
||||
showSource,
|
||||
toggleBlackBox
|
||||
}) {
|
||||
// variables
|
||||
const hasSourceMap = !!selectedSource.get("sourceMapURL");
|
||||
const isOriginal = (0, _devtoolsSourceMap.isOriginalId)(selectedLocation.sourceId);
|
||||
const isPrettyPrinted = (0, _source.isPretty)(selectedSource);
|
||||
const isPrettified = isPrettyPrinted || hasPrettyPrint;
|
||||
const isMapped = isOriginal || hasSourceMap;
|
||||
const {
|
||||
line
|
||||
} = editor.codeMirror.coordsChar({
|
||||
left: event.clientX,
|
||||
top: event.clientY
|
||||
});
|
||||
const selectionText = editor.codeMirror.getSelection().trim();
|
||||
const sourceLocation = (0, _editor.getSourceLocationFromMouseEvent)(editor, selectedLocation, event);
|
||||
const isTextSelected = editor.codeMirror.somethingSelected(); // localizations
|
||||
|
||||
const blackboxKey = L10N.getStr("sourceFooter.blackbox.accesskey");
|
||||
const blackboxLabel = L10N.getStr("sourceFooter.blackbox");
|
||||
const unblackboxLabel = L10N.getStr("sourceFooter.unblackbox");
|
||||
const toggleBlackBoxLabel = selectedSource.isBlackBoxed ? unblackboxLabel : blackboxLabel;
|
||||
const copyFunctionKey = L10N.getStr("copyFunction.accesskey");
|
||||
const copyFunctionLabel = L10N.getStr("copyFunction.label");
|
||||
const copySourceKey = L10N.getStr("copySource.accesskey");
|
||||
const copySourceLabel = L10N.getStr("copySource");
|
||||
const copyToClipboardKey = L10N.getStr("copyToClipboard.accesskey");
|
||||
const copyToClipboardLabel = L10N.getStr("copyToClipboard.label");
|
||||
const copySourceUri2Key = L10N.getStr("copySourceUri2.accesskey");
|
||||
const copySourceUri2Label = L10N.getStr("copySourceUri2");
|
||||
const evaluateInConsoleLabel = L10N.getStr("evaluateInConsole.label");
|
||||
const jumpToMappedLocKey = L10N.getStr("editor.jumpToMappedLocation1.accesskey");
|
||||
const jumpToMappedLocLabel = L10N.getFormatStr("editor.jumpToMappedLocation1", isOriginal ? L10N.getStr("generated") : L10N.getStr("original"));
|
||||
const revealInTreeKey = L10N.getStr("sourceTabs.revealInTree.accesskey");
|
||||
const revealInTreeLabel = L10N.getStr("sourceTabs.revealInTree");
|
||||
const watchExpressionKey = L10N.getStr("expressions.accesskey");
|
||||
const watchExpressionLabel = L10N.getStr("expressions.label"); // menu items
|
||||
|
||||
const copyToClipboardItem = {
|
||||
id: "node-menu-copy-to-clipboard",
|
||||
label: copyToClipboardLabel,
|
||||
accesskey: copyToClipboardKey,
|
||||
disabled: false,
|
||||
click: () => (0, _clipboard.copyToTheClipboard)(selectedSource.text)
|
||||
};
|
||||
const copySourceItem = {
|
||||
id: "node-menu-copy-source",
|
||||
label: copySourceLabel,
|
||||
accesskey: copySourceKey,
|
||||
disabled: selectionText.length === 0,
|
||||
click: () => (0, _clipboard.copyToTheClipboard)(selectionText)
|
||||
};
|
||||
const copySourceUri2Item = {
|
||||
id: "node-menu-copy-source-url",
|
||||
label: copySourceUri2Label,
|
||||
accesskey: copySourceUri2Key,
|
||||
disabled: false,
|
||||
click: () => (0, _clipboard.copyToTheClipboard)((0, _source.getRawSourceURL)(selectedSource.url))
|
||||
};
|
||||
const sourceId = selectedSource.get("id");
|
||||
const sourceLine = (0, _editor.toSourceLine)(sourceId, line);
|
||||
const functionText = getFunctionText(sourceLine);
|
||||
const copyFunctionItem = {
|
||||
id: "node-menu-copy-function",
|
||||
label: copyFunctionLabel,
|
||||
accesskey: copyFunctionKey,
|
||||
disabled: !functionText,
|
||||
click: () => {
|
||||
const {
|
||||
location: {
|
||||
start,
|
||||
end
|
||||
}
|
||||
} = getFunctionLocation(sourceLine);
|
||||
flashLineRange({
|
||||
start: start.line,
|
||||
end: end.line,
|
||||
sourceId: selectedLocation.sourceId
|
||||
});
|
||||
return (0, _clipboard.copyToTheClipboard)(functionText);
|
||||
}
|
||||
};
|
||||
const jumpToMappedLocationItem = {
|
||||
id: "node-menu-jump",
|
||||
label: jumpToMappedLocLabel,
|
||||
accesskey: jumpToMappedLocKey,
|
||||
disabled: !isMapped && !isPrettified,
|
||||
click: () => jumpToMappedLocation(sourceLocation)
|
||||
};
|
||||
const showSourceMenuItem = {
|
||||
id: "node-menu-show-source",
|
||||
label: revealInTreeLabel,
|
||||
accesskey: revealInTreeKey,
|
||||
disabled: false,
|
||||
click: () => showSource(sourceId)
|
||||
};
|
||||
const blackBoxMenuItem = {
|
||||
id: "node-menu-blackbox",
|
||||
label: toggleBlackBoxLabel,
|
||||
accesskey: blackboxKey,
|
||||
disabled: isOriginal || isPrettyPrinted || hasSourceMap,
|
||||
click: () => toggleBlackBox(selectedSource.toJS())
|
||||
};
|
||||
const watchExpressionItem = {
|
||||
id: "node-menu-add-watch-expression",
|
||||
label: watchExpressionLabel,
|
||||
accesskey: watchExpressionKey,
|
||||
click: () => addExpression(editor.codeMirror.getSelection())
|
||||
};
|
||||
const evaluateInConsoleItem = {
|
||||
id: "node-menu-evaluate-in-console",
|
||||
label: evaluateInConsoleLabel,
|
||||
click: () => evaluateInConsole(selectionText)
|
||||
}; // construct menu
|
||||
|
||||
const menuItems = [copyToClipboardItem, copySourceItem, copySourceUri2Item, copyFunctionItem, {
|
||||
type: "separator"
|
||||
}, jumpToMappedLocationItem, showSourceMenuItem, blackBoxMenuItem]; // conditionally added items
|
||||
// TODO: Find a new way to only add this for mapped sources?
|
||||
|
||||
if (isTextSelected) {
|
||||
menuItems.push(watchExpressionItem, evaluateInConsoleItem);
|
||||
}
|
||||
|
||||
return menuItems;
|
||||
}
|
||||
|
||||
class EditorMenu extends _react.Component {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return nextProps.contextMenu.type === "Editor";
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps) {
|
||||
// clear the context menu since it is open
|
||||
this.props.setContextMenu("", null);
|
||||
return this.showMenu(nextProps);
|
||||
}
|
||||
|
||||
showMenu(nextProps) {
|
||||
const {
|
||||
contextMenu
|
||||
} = nextProps,
|
||||
options = _objectWithoutProperties(nextProps, ["contextMenu"]);
|
||||
|
||||
const {
|
||||
event
|
||||
} = contextMenu;
|
||||
(0, _devtoolsContextmenu.showMenu)(event, getMenuItems(event, options));
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(state);
|
||||
const symbols = (0, _selectors.getSymbols)(state, selectedSource);
|
||||
return {
|
||||
selectedLocation: (0, _selectors.getSelectedLocation)(state),
|
||||
selectedSource,
|
||||
hasPrettyPrint: !!(0, _selectors.getPrettySource)(state, selectedSource.get("id")),
|
||||
contextMenu: (0, _selectors.getContextMenu)(state),
|
||||
getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource.toJS(), symbols),
|
||||
getFunctionLocation: line => (0, _ast.findClosestFunction)(symbols, {
|
||||
line,
|
||||
column: Infinity
|
||||
})
|
||||
};
|
||||
};
|
||||
|
||||
const {
|
||||
addExpression,
|
||||
evaluateInConsole,
|
||||
flashLineRange,
|
||||
jumpToMappedLocation,
|
||||
setContextMenu,
|
||||
showSource,
|
||||
toggleBlackBox
|
||||
} = _actions2.default;
|
||||
const mapDispatchToProps = {
|
||||
addExpression,
|
||||
evaluateInConsole,
|
||||
flashLineRange,
|
||||
jumpToMappedLocation,
|
||||
setContextMenu,
|
||||
showSource,
|
||||
toggleBlackBox
|
||||
};
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(EditorMenu);
|
|
@ -0,0 +1,80 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _editor = require("../../utils/editor/index");
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
class EmptyLines extends _react.Component {
|
||||
componentDidMount() {
|
||||
this.disableEmptyLines();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.disableEmptyLines();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const {
|
||||
emptyLines,
|
||||
selectedSource,
|
||||
editor
|
||||
} = this.props;
|
||||
|
||||
if (!emptyLines) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.codeMirror.operation(() => {
|
||||
emptyLines.forEach(emptyLine => {
|
||||
const line = (0, _editor.toEditorLine)(selectedSource.get("id"), emptyLine);
|
||||
editor.codeMirror.removeLineClass(line, "line", "empty-line");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
disableEmptyLines() {
|
||||
const {
|
||||
emptyLines,
|
||||
selectedSource,
|
||||
editor
|
||||
} = this.props;
|
||||
|
||||
if (!emptyLines) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.codeMirror.operation(() => {
|
||||
emptyLines.forEach(emptyLine => {
|
||||
const line = (0, _editor.toEditorLine)(selectedSource.get("id"), emptyLine);
|
||||
editor.codeMirror.addLineClass(line, "line", "empty-line");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(state);
|
||||
const foundEmptyLines = (0, _selectors.getEmptyLines)(state, selectedSource.toJS());
|
||||
return {
|
||||
selectedSource,
|
||||
emptyLines: selectedSource ? foundEmptyLines : []
|
||||
};
|
||||
};
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps)(EmptyLines);
|
|
@ -0,0 +1,202 @@
|
|||
"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 _actions = require("../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
|
||||
|
||||
var _classnames2 = _interopRequireDefault(_classnames);
|
||||
|
||||
var _prefs = require("../../utils/prefs");
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _sources = require("../../reducers/sources");
|
||||
|
||||
var _editor = require("../../utils/editor/index");
|
||||
|
||||
var _PaneToggle = require("../shared/Button/PaneToggle");
|
||||
|
||||
var _PaneToggle2 = _interopRequireDefault(_PaneToggle);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
class SourceFooter extends _react.PureComponent {
|
||||
prettyPrintButton() {
|
||||
const {
|
||||
selectedSource,
|
||||
togglePrettyPrint
|
||||
} = this.props;
|
||||
const sourceLoaded = selectedSource && (0, _source.isLoaded)(selectedSource);
|
||||
|
||||
if (!(0, _editor.shouldShowPrettyPrint)(selectedSource)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tooltip = L10N.getStr("sourceTabs.prettyPrint");
|
||||
const type = "prettyPrint";
|
||||
return _react2.default.createElement("button", {
|
||||
onClick: () => togglePrettyPrint(selectedSource.get("id")),
|
||||
className: (0, _classnames2.default)("action", type, {
|
||||
active: sourceLoaded,
|
||||
pretty: (0, _source.isPretty)(selectedSource)
|
||||
}),
|
||||
key: type,
|
||||
title: tooltip,
|
||||
"aria-label": tooltip
|
||||
}, _react2.default.createElement("img", {
|
||||
className: type
|
||||
}));
|
||||
}
|
||||
|
||||
blackBoxButton() {
|
||||
const {
|
||||
selectedSource,
|
||||
toggleBlackBox
|
||||
} = this.props;
|
||||
const sourceLoaded = selectedSource && (0, _source.isLoaded)(selectedSource);
|
||||
|
||||
if (!sourceLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
const blackboxed = selectedSource.isBlackBoxed;
|
||||
const tooltip = L10N.getStr("sourceFooter.blackbox");
|
||||
const type = "black-box";
|
||||
return _react2.default.createElement("button", {
|
||||
onClick: () => toggleBlackBox(selectedSource.toJS()),
|
||||
className: (0, _classnames2.default)("action", type, {
|
||||
active: sourceLoaded,
|
||||
blackboxed: blackboxed
|
||||
}),
|
||||
key: type,
|
||||
title: tooltip,
|
||||
"aria-label": tooltip
|
||||
}, _react2.default.createElement("img", {
|
||||
className: "blackBox"
|
||||
}));
|
||||
}
|
||||
|
||||
blackBoxSummary() {
|
||||
const {
|
||||
selectedSource
|
||||
} = this.props;
|
||||
|
||||
if (!selectedSource || !selectedSource.isBlackBoxed) {
|
||||
return;
|
||||
}
|
||||
|
||||
return _react2.default.createElement("span", {
|
||||
className: "blackbox-summary"
|
||||
}, L10N.getStr("sourceFooter.blackboxed"));
|
||||
}
|
||||
|
||||
coverageButton() {
|
||||
const {
|
||||
recordCoverage
|
||||
} = this.props;
|
||||
|
||||
if (!_prefs.features.codeCoverage) {
|
||||
return;
|
||||
}
|
||||
|
||||
return _react2.default.createElement("button", {
|
||||
className: "coverage action",
|
||||
title: L10N.getStr("sourceFooter.codeCoverage"),
|
||||
onClick: () => recordCoverage(),
|
||||
"aria-label": L10N.getStr("sourceFooter.codeCoverage")
|
||||
}, "C");
|
||||
}
|
||||
|
||||
renderToggleButton() {
|
||||
if (this.props.horizontal) {
|
||||
return;
|
||||
}
|
||||
|
||||
return _react2.default.createElement(_PaneToggle2.default, {
|
||||
position: "end",
|
||||
collapsed: !this.props.endPanelCollapsed,
|
||||
horizontal: this.props.horizontal,
|
||||
handleClick: this.props.togglePaneCollapse
|
||||
});
|
||||
}
|
||||
|
||||
renderCommands() {
|
||||
return _react2.default.createElement("div", {
|
||||
className: "commands"
|
||||
}, this.prettyPrintButton(), this.blackBoxButton(), this.blackBoxSummary(), this.coverageButton());
|
||||
}
|
||||
|
||||
renderSourceSummary() {
|
||||
const {
|
||||
mappedSource,
|
||||
jumpToMappedLocation,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
|
||||
if (mappedSource) {
|
||||
const bundleSource = mappedSource.toJS();
|
||||
const filename = (0, _source.getFilename)(bundleSource);
|
||||
const tooltip = L10N.getFormatStr("sourceFooter.mappedSourceTooltip", filename);
|
||||
const title = L10N.getFormatStr("sourceFooter.mappedSource", filename);
|
||||
const mappedSourceLocation = {
|
||||
sourceId: selectedSource.get("id"),
|
||||
line: 1,
|
||||
column: 1
|
||||
};
|
||||
return _react2.default.createElement("button", {
|
||||
className: "mapped-source",
|
||||
onClick: () => jumpToMappedLocation(mappedSourceLocation),
|
||||
title: tooltip
|
||||
}, _react2.default.createElement("span", null, title));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
selectedSource,
|
||||
horizontal
|
||||
} = this.props;
|
||||
|
||||
if (!(0, _editor.shouldShowFooter)(selectedSource, horizontal)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return _react2.default.createElement("div", {
|
||||
className: "source-footer"
|
||||
}, this.renderCommands(), this.renderSourceSummary(), this.renderToggleButton());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(state);
|
||||
const selectedId = selectedSource.get("id");
|
||||
const source = selectedSource.toJS();
|
||||
return {
|
||||
selectedSource,
|
||||
mappedSource: (0, _sources.getGeneratedSource)(state, source),
|
||||
prettySource: (0, _selectors.getPrettySource)(state, selectedId),
|
||||
endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end")
|
||||
};
|
||||
};
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(SourceFooter);
|
|
@ -0,0 +1,176 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.gutterMenu = gutterMenu;
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"];
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _editor = require("../../utils/editor/index");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _actions = require("../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
||||
|
||||
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 gutterMenu({
|
||||
breakpoint,
|
||||
line,
|
||||
event,
|
||||
isPaused,
|
||||
toggleBreakpoint,
|
||||
openConditionalPanel,
|
||||
toggleDisabledBreakpoint,
|
||||
isCbPanelOpen,
|
||||
closeConditionalPanel,
|
||||
continueToHere
|
||||
}) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
const gutterItems = {
|
||||
addBreakpoint: {
|
||||
id: "node-menu-add-breakpoint",
|
||||
label: L10N.getStr("editor.addBreakpoint")
|
||||
},
|
||||
addConditional: {
|
||||
id: "node-menu-add-conditional-breakpoint",
|
||||
label: L10N.getStr("editor.addConditionalBreakpoint")
|
||||
},
|
||||
removeBreakpoint: {
|
||||
id: "node-menu-remove-breakpoint",
|
||||
label: L10N.getStr("editor.removeBreakpoint")
|
||||
},
|
||||
editConditional: {
|
||||
id: "node-menu-edit-conditional-breakpoint",
|
||||
label: L10N.getStr("editor.editBreakpoint")
|
||||
},
|
||||
enableBreakpoint: {
|
||||
id: "node-menu-enable-breakpoint",
|
||||
label: L10N.getStr("editor.enableBreakpoint")
|
||||
},
|
||||
disableBreakpoint: {
|
||||
id: "node-menu-disable-breakpoint",
|
||||
label: L10N.getStr("editor.disableBreakpoint")
|
||||
},
|
||||
continueToHere: {
|
||||
id: "node-menu-continue-to-here",
|
||||
label: L10N.getStr("editor.continueToHere.label")
|
||||
}
|
||||
};
|
||||
|
||||
const toggleBreakpointItem = _objectSpread({
|
||||
accesskey: L10N.getStr("shortcuts.toggleBreakpoint.accesskey"),
|
||||
disabled: false,
|
||||
click: () => {
|
||||
toggleBreakpoint(line);
|
||||
|
||||
if (isCbPanelOpen) {
|
||||
closeConditionalPanel();
|
||||
}
|
||||
}
|
||||
}, breakpoint ? gutterItems.removeBreakpoint : gutterItems.addBreakpoint);
|
||||
|
||||
const conditionalBreakpoint = _objectSpread({
|
||||
accesskey: L10N.getStr("editor.addConditionalBreakpoint.accesskey"),
|
||||
disabled: false,
|
||||
click: () => openConditionalPanel(line)
|
||||
}, breakpoint && breakpoint.condition ? gutterItems.editConditional : gutterItems.addConditional);
|
||||
|
||||
const items = [toggleBreakpointItem, conditionalBreakpoint];
|
||||
|
||||
if (isPaused) {
|
||||
const continueToHereItem = _objectSpread({
|
||||
accesskey: L10N.getStr("editor.continueToHere.accesskey"),
|
||||
disabled: false,
|
||||
click: () => continueToHere(line)
|
||||
}, gutterItems.continueToHere);
|
||||
|
||||
items.push(continueToHereItem);
|
||||
}
|
||||
|
||||
if (breakpoint) {
|
||||
const disableBreakpoint = _objectSpread({
|
||||
accesskey: L10N.getStr("editor.disableBreakpoint.accesskey"),
|
||||
disabled: false,
|
||||
click: () => toggleDisabledBreakpoint(line)
|
||||
}, breakpoint.disabled ? gutterItems.enableBreakpoint : gutterItems.disableBreakpoint);
|
||||
|
||||
items.push(disableBreakpoint);
|
||||
}
|
||||
|
||||
(0, _devtoolsContextmenu.showMenu)(event, items);
|
||||
}
|
||||
|
||||
class GutterContextMenuComponent extends _react.Component {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return nextProps.contextMenu.type === "Gutter";
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps) {
|
||||
// clear the context menu since it is open
|
||||
this.props.setContextMenu("", null);
|
||||
return this.showMenu(nextProps);
|
||||
}
|
||||
|
||||
showMenu(nextProps) {
|
||||
const {
|
||||
contextMenu
|
||||
} = nextProps,
|
||||
props = _objectWithoutProperties(nextProps, ["contextMenu"]);
|
||||
|
||||
const {
|
||||
event
|
||||
} = contextMenu;
|
||||
const sourceId = props.selectedSource ? props.selectedSource.get("id") : "";
|
||||
const line = (0, _editor.lineAtHeight)(props.editor, sourceId, event);
|
||||
const breakpoint = nextProps.breakpoints.find(bp => bp.location.line === line);
|
||||
|
||||
if (props.emptyLines && props.emptyLines.includes(line)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gutterMenu(_objectSpread({
|
||||
event,
|
||||
sourceId,
|
||||
line,
|
||||
breakpoint
|
||||
}, props));
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(state);
|
||||
return {
|
||||
selectedLocation: (0, _selectors.getSelectedLocation)(state),
|
||||
selectedSource: selectedSource,
|
||||
breakpoints: (0, _selectors.getVisibleBreakpoints)(state),
|
||||
isPaused: (0, _selectors.isPaused)(state),
|
||||
contextMenu: (0, _selectors.getContextMenu)(state),
|
||||
emptyLines: (0, _selectors.getEmptyLines)(state, selectedSource.toJS())
|
||||
};
|
||||
};
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(GutterContextMenuComponent);
|
|
@ -0,0 +1,132 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.HighlightLine = undefined;
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _editor = require("../../utils/editor/index");
|
||||
|
||||
var _sourceDocuments = require("../../utils/editor/source-documents");
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
/* 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 isDebugLine(selectedFrame, selectedLocation) {
|
||||
if (!selectedFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
return selectedFrame.location.sourceId == selectedLocation.sourceId && selectedFrame.location.line == selectedLocation.line;
|
||||
}
|
||||
|
||||
function isDocumentReady(selectedSource, selectedLocation) {
|
||||
return selectedLocation && (0, _source.isLoaded)(selectedSource) && (0, _sourceDocuments.hasDocument)(selectedLocation.sourceId);
|
||||
}
|
||||
|
||||
class HighlightLine extends _react.Component {
|
||||
constructor(...args) {
|
||||
var _temp;
|
||||
|
||||
return _temp = super(...args), this.isStepping = false, this.previousEditorLine = null, _temp;
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const {
|
||||
selectedLocation,
|
||||
selectedSource
|
||||
} = nextProps;
|
||||
return this.shouldSetHighlightLine(selectedLocation, selectedSource);
|
||||
}
|
||||
|
||||
shouldSetHighlightLine(selectedLocation, selectedSource) {
|
||||
const {
|
||||
sourceId,
|
||||
line
|
||||
} = selectedLocation;
|
||||
const editorLine = (0, _editor.toEditorLine)(sourceId, line);
|
||||
|
||||
if (!isDocumentReady(selectedSource, selectedLocation)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.isStepping && editorLine === this.previousEditorLine) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const {
|
||||
pauseCommand,
|
||||
selectedLocation,
|
||||
selectedFrame,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
|
||||
if (pauseCommand) {
|
||||
this.isStepping = true;
|
||||
}
|
||||
|
||||
this.clearHighlightLine(prevProps.selectedLocation, prevProps.selectedSource);
|
||||
this.setHighlightLine(selectedLocation, selectedFrame, selectedSource);
|
||||
}
|
||||
|
||||
setHighlightLine(selectedLocation, selectedFrame, selectedSource) {
|
||||
const {
|
||||
sourceId,
|
||||
line
|
||||
} = selectedLocation;
|
||||
|
||||
if (!this.shouldSetHighlightLine(selectedLocation, selectedSource)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isStepping = false;
|
||||
const editorLine = (0, _editor.toEditorLine)(sourceId, line);
|
||||
this.previousEditorLine = editorLine;
|
||||
|
||||
if (!line || isDebugLine(selectedFrame, selectedLocation)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const doc = (0, _sourceDocuments.getDocument)(sourceId);
|
||||
doc.addLineClass(editorLine, "line", "highlight-line");
|
||||
}
|
||||
|
||||
clearHighlightLine(selectedLocation, selectedSource) {
|
||||
if (!isDocumentReady(selectedSource, selectedLocation)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
line,
|
||||
sourceId
|
||||
} = selectedLocation;
|
||||
const editorLine = (0, _editor.toEditorLine)(sourceId, line);
|
||||
const doc = (0, _sourceDocuments.getDocument)(sourceId);
|
||||
doc.removeLineClass(editorLine, "line", "highlight-line");
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.HighlightLine = HighlightLine;
|
||||
exports.default = (0, _reactRedux.connect)(state => ({
|
||||
pauseCommand: (0, _selectors.getPauseCommand)(state),
|
||||
selectedFrame: (0, _selectors.getVisibleSelectedFrame)(state),
|
||||
selectedLocation: (0, _selectors.getSelectedLocation)(state),
|
||||
selectedSource: (0, _selectors.getSelectedSource)(state)
|
||||
}))(HighlightLine);
|
|
@ -0,0 +1,96 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
class HighlightLines extends _react.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.highlightLineRange = () => {
|
||||
const {
|
||||
highlightedLineRange,
|
||||
editor
|
||||
} = this.props;
|
||||
const {
|
||||
codeMirror
|
||||
} = editor;
|
||||
|
||||
if ((0, _lodash.isEmpty)(highlightedLineRange) || !codeMirror) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
start,
|
||||
end
|
||||
} = highlightedLineRange;
|
||||
codeMirror.operation(() => {
|
||||
editor.alignLine(start);
|
||||
(0, _lodash.range)(start - 1, end).forEach(line => {
|
||||
codeMirror.addLineClass(line, "line", "highlight-lines");
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.highlightLineRange();
|
||||
}
|
||||
|
||||
componentWillUpdate() {
|
||||
this.clearHighlightRange();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.highlightLineRange();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.clearHighlightRange();
|
||||
}
|
||||
|
||||
clearHighlightRange() {
|
||||
const {
|
||||
highlightedLineRange,
|
||||
editor
|
||||
} = this.props;
|
||||
const {
|
||||
codeMirror
|
||||
} = editor;
|
||||
|
||||
if ((0, _lodash.isEmpty)(highlightedLineRange) || !codeMirror) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
start,
|
||||
end
|
||||
} = highlightedLineRange;
|
||||
codeMirror.operation(() => {
|
||||
(0, _lodash.range)(start - 1, end).forEach(line => {
|
||||
codeMirror.removeLineClass(line, "line", "highlight-lines");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(state => ({
|
||||
highlightedLineRange: (0, _selectors.getHighlightedLineRange)(state)
|
||||
}))(HighlightLines);
|
|
@ -0,0 +1,53 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
const markerEl = document.createElement("div");
|
||||
|
||||
function makeMarker() {
|
||||
const marker = markerEl.cloneNode(true);
|
||||
marker.className = "editor hit-marker";
|
||||
return marker;
|
||||
}
|
||||
|
||||
class HitMarker extends _react.Component {
|
||||
addMarker() {
|
||||
const hitData = this.props.hitData;
|
||||
const line = hitData.line - 1;
|
||||
this.props.editor.setGutterMarker(line, "hit-markers", makeMarker());
|
||||
this.props.editor.addLineClass(line, "line", "hit-marker");
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return this.props.editor !== nextProps.editor || this.props.hitData !== nextProps.hitData;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.addMarker();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.addMarker();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const hitData = this.props.hitData;
|
||||
const line = hitData.line - 1;
|
||||
this.props.editor.setGutterMarker(line, "hit-markers", null);
|
||||
this.props.editor.removeLineClass(line, "line", "hit-marker");
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.default = HitMarker;
|
|
@ -0,0 +1,336 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.Popup = undefined;
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _devtoolsReps = require("devtools/client/shared/components/reps/reps.js");
|
||||
|
||||
var _devtoolsReps2 = _interopRequireDefault(_devtoolsReps);
|
||||
|
||||
var _actions = require("../../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _selectors = require("../../../selectors/index");
|
||||
|
||||
var _Popover = require("../../shared/Popover");
|
||||
|
||||
var _Popover2 = _interopRequireDefault(_Popover);
|
||||
|
||||
var _PreviewFunction = require("../../shared/PreviewFunction");
|
||||
|
||||
var _PreviewFunction2 = _interopRequireDefault(_PreviewFunction);
|
||||
|
||||
var _editor = require("../../../utils/editor/index");
|
||||
|
||||
var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"];
|
||||
|
||||
var _Svg2 = _interopRequireDefault(_Svg);
|
||||
|
||||
var _firefox = require("../../../client/firefox");
|
||||
|
||||
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/>. */
|
||||
const {
|
||||
REPS: {
|
||||
Rep
|
||||
},
|
||||
MODE,
|
||||
ObjectInspector,
|
||||
ObjectInspectorUtils
|
||||
} = _devtoolsReps2.default;
|
||||
const {
|
||||
createNode,
|
||||
getChildren,
|
||||
getValue,
|
||||
nodeIsPrimitive,
|
||||
NODE_TYPES
|
||||
} = ObjectInspectorUtils.node;
|
||||
const {
|
||||
loadItemProperties
|
||||
} = ObjectInspectorUtils.loadProperties;
|
||||
|
||||
class Popup extends _react.Component {
|
||||
constructor(...args) {
|
||||
var _temp;
|
||||
|
||||
return _temp = super(...args), this.onMouseLeave = e => {
|
||||
const relatedTarget = e.relatedTarget;
|
||||
|
||||
if (relatedTarget && (relatedTarget.classList.contains("popover") || relatedTarget.classList.contains("debug-expression") || relatedTarget.classList.contains("editor-mount"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.onClose();
|
||||
}, _temp;
|
||||
}
|
||||
|
||||
async componentWillMount() {
|
||||
const {
|
||||
value,
|
||||
setPopupObjectProperties,
|
||||
popupObjectProperties
|
||||
} = this.props;
|
||||
const root = this.getRoot();
|
||||
|
||||
if (!nodeIsPrimitive(root) && value && value.actor && !popupObjectProperties[value.actor]) {
|
||||
const onLoadItemProperties = loadItemProperties(root, _firefox.createObjectClient);
|
||||
|
||||
if (onLoadItemProperties !== null) {
|
||||
const properties = await onLoadItemProperties;
|
||||
setPopupObjectProperties(root.contents.value, properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
value,
|
||||
editor,
|
||||
range
|
||||
} = this.props;
|
||||
|
||||
if (!value || !value.type == "object") {
|
||||
return;
|
||||
}
|
||||
|
||||
this.marker = (0, _editor.markText)(editor, "preview-selection", range);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.marker) {
|
||||
this.marker.clear();
|
||||
}
|
||||
}
|
||||
|
||||
getRoot() {
|
||||
const {
|
||||
expression,
|
||||
value,
|
||||
extra
|
||||
} = this.props;
|
||||
let rootValue = value;
|
||||
|
||||
if (extra.immutable) {
|
||||
rootValue = extra.immutable.entries;
|
||||
}
|
||||
|
||||
return createNode({
|
||||
name: expression,
|
||||
path: expression,
|
||||
contents: {
|
||||
value: rootValue
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getChildren() {
|
||||
const {
|
||||
popupObjectProperties
|
||||
} = this.props;
|
||||
const root = this.getRoot();
|
||||
const value = getValue(root);
|
||||
const actor = value ? value.actor : null;
|
||||
const loadedRootProperties = popupObjectProperties[actor];
|
||||
|
||||
if (!loadedRootProperties) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const children = getChildren({
|
||||
item: root,
|
||||
loadedProperties: new Map([[root.path, loadedRootProperties]])
|
||||
});
|
||||
|
||||
if (children.length > 0) {
|
||||
return children;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
renderFunctionPreview() {
|
||||
const {
|
||||
selectSourceURL,
|
||||
value
|
||||
} = this.props;
|
||||
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {
|
||||
location
|
||||
} = value;
|
||||
return _react2.default.createElement("div", {
|
||||
className: "preview-popup",
|
||||
onClick: () => selectSourceURL(location.url, {
|
||||
line: location.line
|
||||
})
|
||||
}, _react2.default.createElement(_PreviewFunction2.default, {
|
||||
func: value
|
||||
}));
|
||||
}
|
||||
|
||||
renderReact(react, roots) {
|
||||
const reactHeader = react.displayName || "React Component";
|
||||
return _react2.default.createElement("div", {
|
||||
className: "header-container"
|
||||
}, _react2.default.createElement(_Svg2.default, {
|
||||
name: "react",
|
||||
className: "logo"
|
||||
}), _react2.default.createElement("h3", null, reactHeader));
|
||||
}
|
||||
|
||||
renderImmutable(immutable) {
|
||||
const immutableHeader = immutable.type || "Immutable";
|
||||
return _react2.default.createElement("div", {
|
||||
className: "header-container"
|
||||
}, _react2.default.createElement(_Svg2.default, {
|
||||
name: "immutable",
|
||||
className: "logo"
|
||||
}), _react2.default.createElement("h3", null, immutableHeader));
|
||||
}
|
||||
|
||||
renderObjectPreview() {
|
||||
const {
|
||||
extra
|
||||
} = this.props;
|
||||
const root = this.getRoot();
|
||||
|
||||
if (nodeIsPrimitive(root)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let roots = this.getChildren();
|
||||
|
||||
if (!Array.isArray(roots) || roots.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let header = null;
|
||||
|
||||
if (extra.immutable) {
|
||||
header = this.renderImmutable(extra.immutable);
|
||||
roots = roots.filter(r => r.type != NODE_TYPES.PROTOTYPE);
|
||||
}
|
||||
|
||||
if (extra.react) {
|
||||
header = this.renderReact(extra.react);
|
||||
roots = roots.filter(r => ["state", "props"].includes(r.name));
|
||||
}
|
||||
|
||||
return _react2.default.createElement("div", {
|
||||
className: "preview-popup"
|
||||
}, header, this.renderObjectInspector(roots));
|
||||
}
|
||||
|
||||
renderSimplePreview(value) {
|
||||
const {
|
||||
openLink
|
||||
} = this.props;
|
||||
return _react2.default.createElement("div", {
|
||||
className: "preview-popup"
|
||||
}, Rep({
|
||||
object: value,
|
||||
mode: MODE.LONG,
|
||||
openLink
|
||||
}));
|
||||
}
|
||||
|
||||
renderObjectInspector(roots) {
|
||||
const {
|
||||
openLink
|
||||
} = this.props;
|
||||
return _react2.default.createElement(ObjectInspector, {
|
||||
roots: roots,
|
||||
autoExpandDepth: 0,
|
||||
disableWrap: true,
|
||||
focusable: false,
|
||||
openLink: openLink,
|
||||
createObjectClient: grip => (0, _firefox.createObjectClient)(grip)
|
||||
});
|
||||
}
|
||||
|
||||
renderPreview() {
|
||||
const {
|
||||
value
|
||||
} = this.props;
|
||||
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value.class === "Function") {
|
||||
return this.renderFunctionPreview();
|
||||
}
|
||||
|
||||
if (value.type === "object") {
|
||||
return _react2.default.createElement("div", null, this.renderObjectPreview());
|
||||
}
|
||||
|
||||
return this.renderSimplePreview(value);
|
||||
}
|
||||
|
||||
getPreviewType(value) {
|
||||
if (typeof value == "number" || typeof value == "boolean" || typeof value == "string" && value.length < 10 || typeof value == "number" && value.toString().length < 10 || value.type == "null" || value.type == "undefined" || value.class === "Function") {
|
||||
return "tooltip";
|
||||
}
|
||||
|
||||
return "popover";
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
popoverPos,
|
||||
value,
|
||||
editorRef
|
||||
} = this.props;
|
||||
const type = this.getPreviewType(value);
|
||||
|
||||
if (value && value.type === "object" && !this.getChildren()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return _react2.default.createElement(_Popover2.default, {
|
||||
targetPosition: popoverPos,
|
||||
onMouseLeave: this.onMouseLeave,
|
||||
type: type,
|
||||
editorRef: editorRef
|
||||
}, this.renderPreview());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.Popup = Popup;
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
popupObjectProperties: (0, _selectors.getAllPopupObjectProperties)(state)
|
||||
});
|
||||
|
||||
const {
|
||||
addExpression,
|
||||
selectSourceURL,
|
||||
selectLocation,
|
||||
setPopupObjectProperties,
|
||||
openLink
|
||||
} = _actions2.default;
|
||||
const mapDispatchToProps = {
|
||||
addExpression,
|
||||
selectSourceURL,
|
||||
selectLocation,
|
||||
setPopupObjectProperties,
|
||||
openLink
|
||||
};
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(Popup);
|
|
@ -0,0 +1,161 @@
|
|||
"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 _Popup = require("./Popup");
|
||||
|
||||
var _Popup2 = _interopRequireDefault(_Popup);
|
||||
|
||||
var _selectors = require("../../../selectors/index");
|
||||
|
||||
var _actions = require("../../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _editor = require("../../../utils/editor/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/>. */
|
||||
class Preview extends _react.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onMouseOver = e => {
|
||||
const {
|
||||
target
|
||||
} = e;
|
||||
this.props.updatePreview(target, this.props.editor);
|
||||
};
|
||||
|
||||
this.onMouseUp = () => {
|
||||
this.setState({
|
||||
selecting: false
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
this.onMouseDown = () => {
|
||||
this.setState({
|
||||
selecting: true
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
this.onMouseLeave = e => {
|
||||
const target = e.target;
|
||||
|
||||
if (target.classList.contains("CodeMirror")) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.clearPreview();
|
||||
};
|
||||
|
||||
this.onClose = () => {
|
||||
this.props.clearPreview();
|
||||
};
|
||||
|
||||
this.state = {
|
||||
selecting: false
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
codeMirror
|
||||
} = this.props.editor;
|
||||
const codeMirrorWrapper = codeMirror.getWrapperElement();
|
||||
codeMirrorWrapper.addEventListener("mouseover", this.onMouseOver);
|
||||
codeMirrorWrapper.addEventListener("mouseup", this.onMouseUp);
|
||||
codeMirrorWrapper.addEventListener("mousedown", this.onMouseDown);
|
||||
codeMirrorWrapper.addEventListener("mouseleave", this.onMouseLeave);
|
||||
|
||||
if (document.body) {
|
||||
document.body.addEventListener("mouseleave", this.onMouseLeave);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const codeMirror = this.props.editor.codeMirror;
|
||||
const codeMirrorWrapper = codeMirror.getWrapperElement();
|
||||
codeMirrorWrapper.removeEventListener("mouseover", this.onMouseOver);
|
||||
codeMirrorWrapper.removeEventListener("mouseup", this.onMouseUp);
|
||||
codeMirrorWrapper.removeEventListener("mousedown", this.onMouseDown);
|
||||
codeMirrorWrapper.removeEventListener("mouseleave", this.onMouseLeave);
|
||||
|
||||
if (document.body) {
|
||||
document.body.removeEventListener("mouseleave", this.onMouseLeave);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
selectedSource,
|
||||
preview
|
||||
} = this.props;
|
||||
|
||||
if (!this.props.editor || !selectedSource || this.state.selecting) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!preview || preview.updating) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {
|
||||
result,
|
||||
expression,
|
||||
location,
|
||||
cursorPos,
|
||||
extra
|
||||
} = preview;
|
||||
const value = result;
|
||||
|
||||
if (typeof value == "undefined" || value.optimizedOut) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const editorRange = (0, _editor.toEditorRange)(selectedSource.get("id"), location);
|
||||
return _react2.default.createElement(_Popup2.default, {
|
||||
value: value,
|
||||
editor: this.props.editor,
|
||||
editorRef: this.props.editorRef,
|
||||
range: editorRange,
|
||||
expression: expression,
|
||||
popoverPos: cursorPos,
|
||||
extra: extra,
|
||||
onClose: this.onClose
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
preview: (0, _selectors.getPreview)(state),
|
||||
selectedSource: (0, _selectors.getSelectedSource)(state)
|
||||
});
|
||||
|
||||
const {
|
||||
addExpression,
|
||||
setPopupObjectProperties,
|
||||
updatePreview,
|
||||
clearPreview
|
||||
} = _actions2.default;
|
||||
const mapDispatchToProps = {
|
||||
addExpression,
|
||||
setPopupObjectProperties,
|
||||
updatePreview,
|
||||
clearPreview
|
||||
};
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(Preview);
|
|
@ -0,0 +1,13 @@
|
|||
# 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(
|
||||
'index.js',
|
||||
'Popup.js',
|
||||
)
|
|
@ -0,0 +1,368 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _propTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
var _propTypes2 = _interopRequireDefault(_propTypes);
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"];
|
||||
|
||||
var _Svg2 = _interopRequireDefault(_Svg);
|
||||
|
||||
var _actions = require("../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _editor = require("../../utils/editor/index");
|
||||
|
||||
var _resultList = require("../../utils/result-list");
|
||||
|
||||
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
|
||||
|
||||
var _classnames2 = _interopRequireDefault(_classnames);
|
||||
|
||||
var _SearchInput = require("../shared/SearchInput");
|
||||
|
||||
var _SearchInput2 = _interopRequireDefault(_SearchInput);
|
||||
|
||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
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 getShortcuts() {
|
||||
const searchAgainKey = L10N.getStr("sourceSearch.search.again.key2");
|
||||
const searchAgainPrevKey = L10N.getStr("sourceSearch.search.againPrev.key2");
|
||||
const searchKey = L10N.getStr("sourceSearch.search.key2");
|
||||
return {
|
||||
shiftSearchAgainShortcut: searchAgainPrevKey,
|
||||
searchAgainShortcut: searchAgainKey,
|
||||
searchShortcut: searchKey
|
||||
};
|
||||
}
|
||||
|
||||
class SearchBar extends _react.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onEscape = e => {
|
||||
this.closeSearch(e);
|
||||
};
|
||||
|
||||
this.clearSearch = () => {
|
||||
const {
|
||||
editor: ed,
|
||||
query
|
||||
} = this.props;
|
||||
|
||||
if (ed) {
|
||||
const ctx = {
|
||||
ed,
|
||||
cm: ed.codeMirror
|
||||
};
|
||||
(0, _editor.removeOverlay)(ctx, query);
|
||||
}
|
||||
};
|
||||
|
||||
this.closeSearch = e => {
|
||||
const {
|
||||
closeFileSearch,
|
||||
editor,
|
||||
searchOn
|
||||
} = this.props;
|
||||
|
||||
if (editor && searchOn) {
|
||||
this.clearSearch();
|
||||
closeFileSearch(editor);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
this.setState({
|
||||
query: "",
|
||||
inputFocused: false
|
||||
});
|
||||
};
|
||||
|
||||
this.toggleSearch = e => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
const {
|
||||
editor,
|
||||
searchOn,
|
||||
setActiveSearch
|
||||
} = this.props;
|
||||
|
||||
if (!searchOn) {
|
||||
setActiveSearch("file");
|
||||
}
|
||||
|
||||
if (searchOn && editor) {
|
||||
const query = editor.codeMirror.getSelection() || this.state.query;
|
||||
|
||||
if (query !== "") {
|
||||
this.setState({
|
||||
query,
|
||||
inputFocused: true
|
||||
});
|
||||
this.doSearch(query);
|
||||
} else {
|
||||
this.setState({
|
||||
query: "",
|
||||
inputFocused: true
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.doSearch = query => {
|
||||
const {
|
||||
selectedSource
|
||||
} = this.props;
|
||||
|
||||
if (!selectedSource || !selectedSource.get("text")) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.doSearch(query, this.props.editor);
|
||||
};
|
||||
|
||||
this.updateSearchResults = (characterIndex, line, matches) => {
|
||||
const matchIndex = matches.findIndex(elm => elm.line === line && elm.ch === characterIndex);
|
||||
this.props.updateSearchResults({
|
||||
matches,
|
||||
matchIndex,
|
||||
count: matches.length,
|
||||
index: characterIndex
|
||||
});
|
||||
};
|
||||
|
||||
this.traverseResults = (e, rev) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
const editor = this.props.editor;
|
||||
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.traverseResults(rev, editor);
|
||||
};
|
||||
|
||||
this.onChange = e => {
|
||||
this.setState({
|
||||
query: e.target.value
|
||||
});
|
||||
return this.doSearch(e.target.value);
|
||||
};
|
||||
|
||||
this.onBlur = e => {
|
||||
this.setState({
|
||||
inputFocused: false
|
||||
});
|
||||
};
|
||||
|
||||
this.onKeyDown = e => {
|
||||
if (e.key !== "Enter" && e.key !== "F3") {
|
||||
return;
|
||||
}
|
||||
|
||||
this.traverseResults(e, e.shiftKey);
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
this.renderSearchModifiers = () => {
|
||||
const {
|
||||
modifiers,
|
||||
toggleFileSearchModifier,
|
||||
query
|
||||
} = this.props;
|
||||
const {
|
||||
doSearch
|
||||
} = this;
|
||||
|
||||
function SearchModBtn({
|
||||
modVal,
|
||||
className,
|
||||
svgName,
|
||||
tooltip
|
||||
}) {
|
||||
const preppedClass = (0, _classnames2.default)(className, {
|
||||
active: modifiers && modifiers.get(modVal)
|
||||
});
|
||||
return _react2.default.createElement("button", {
|
||||
className: preppedClass,
|
||||
onClick: () => {
|
||||
toggleFileSearchModifier(modVal);
|
||||
doSearch(query);
|
||||
},
|
||||
title: tooltip
|
||||
}, _react2.default.createElement(_Svg2.default, {
|
||||
name: svgName
|
||||
}));
|
||||
}
|
||||
|
||||
return _react2.default.createElement("div", {
|
||||
className: "search-modifiers"
|
||||
}, _react2.default.createElement("span", {
|
||||
className: "search-type-name"
|
||||
}, L10N.getStr("symbolSearch.searchModifier.modifiersLabel")), _react2.default.createElement(SearchModBtn, {
|
||||
modVal: "regexMatch",
|
||||
className: "regex-match-btn",
|
||||
svgName: "regex-match",
|
||||
tooltip: L10N.getStr("symbolSearch.searchModifier.regex")
|
||||
}), _react2.default.createElement(SearchModBtn, {
|
||||
modVal: "caseSensitive",
|
||||
className: "case-sensitive-btn",
|
||||
svgName: "case-match",
|
||||
tooltip: L10N.getStr("symbolSearch.searchModifier.caseSensitive")
|
||||
}), _react2.default.createElement(SearchModBtn, {
|
||||
modVal: "wholeWord",
|
||||
className: "whole-word-btn",
|
||||
svgName: "whole-word-match",
|
||||
tooltip: L10N.getStr("symbolSearch.searchModifier.wholeWord")
|
||||
}));
|
||||
};
|
||||
|
||||
this.state = {
|
||||
query: props.query,
|
||||
selectedResultIndex: 0,
|
||||
count: 0,
|
||||
index: -1,
|
||||
inputFocused: false
|
||||
};
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const shortcuts = this.context.shortcuts;
|
||||
const {
|
||||
searchShortcut,
|
||||
searchAgainShortcut,
|
||||
shiftSearchAgainShortcut
|
||||
} = getShortcuts();
|
||||
shortcuts.off(searchShortcut);
|
||||
shortcuts.off("Escape");
|
||||
shortcuts.off(searchAgainShortcut);
|
||||
shortcuts.off(shiftSearchAgainShortcut);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// overwrite this.doSearch with debounced version to
|
||||
// reduce frequency of queries
|
||||
this.doSearch = (0, _lodash.debounce)(this.doSearch, 100);
|
||||
const shortcuts = this.context.shortcuts;
|
||||
const {
|
||||
searchShortcut,
|
||||
searchAgainShortcut,
|
||||
shiftSearchAgainShortcut
|
||||
} = getShortcuts();
|
||||
shortcuts.on(searchShortcut, (_, e) => this.toggleSearch(e));
|
||||
shortcuts.on("Escape", (_, e) => this.onEscape(e));
|
||||
shortcuts.on(shiftSearchAgainShortcut, (_, e) => this.traverseResults(e, true));
|
||||
shortcuts.on(searchAgainShortcut, (_, e) => this.traverseResults(e, false));
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (this.refs.resultList && this.refs.resultList.refs) {
|
||||
(0, _resultList.scrollList)(this.refs.resultList.refs, this.state.selectedResultIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Renderers
|
||||
buildSummaryMsg() {
|
||||
const {
|
||||
searchResults: {
|
||||
matchIndex,
|
||||
count,
|
||||
index
|
||||
},
|
||||
query
|
||||
} = this.props;
|
||||
|
||||
if (query.trim() == "") {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
return L10N.getStr("editor.noResults");
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
return L10N.getFormatStr("sourceSearch.resultsSummary1", count);
|
||||
}
|
||||
|
||||
return L10N.getFormatStr("editor.searchResults", matchIndex + 1, count);
|
||||
}
|
||||
|
||||
shouldShowErrorEmoji() {
|
||||
const {
|
||||
query,
|
||||
searchResults: {
|
||||
count
|
||||
}
|
||||
} = this.props;
|
||||
return !!query && !count;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
searchResults: {
|
||||
count
|
||||
},
|
||||
searchOn
|
||||
} = this.props;
|
||||
|
||||
if (!searchOn) {
|
||||
return _react2.default.createElement("div", null);
|
||||
}
|
||||
|
||||
return _react2.default.createElement("div", {
|
||||
className: "search-bar"
|
||||
}, _react2.default.createElement(_SearchInput2.default, {
|
||||
query: this.state.query,
|
||||
count: count,
|
||||
placeholder: L10N.getStr("sourceSearch.search.placeholder"),
|
||||
summaryMsg: this.buildSummaryMsg(),
|
||||
onChange: this.onChange,
|
||||
onBlur: this.onBlur,
|
||||
showErrorEmoji: this.shouldShowErrorEmoji(),
|
||||
onKeyDown: this.onKeyDown,
|
||||
handleNext: e => this.traverseResults(e, false),
|
||||
handlePrev: e => this.traverseResults(e, true),
|
||||
handleClose: this.closeSearch,
|
||||
shouldFocus: this.state.inputFocused
|
||||
}), _react2.default.createElement("div", {
|
||||
className: "search-bottom-bar"
|
||||
}, this.renderSearchModifiers()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SearchBar.contextTypes = {
|
||||
shortcuts: _propTypes2.default.object
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
searchOn: (0, _selectors.getActiveSearch)(state) === "file",
|
||||
selectedSource: (0, _selectors.getSelectedSource)(state),
|
||||
selectedLocation: (0, _selectors.getSelectedLocation)(state),
|
||||
query: (0, _selectors.getFileSearchQuery)(state),
|
||||
modifiers: (0, _selectors.getFileSearchModifiers)(state),
|
||||
highlightedLineRange: (0, _selectors.getHighlightedLineRange)(state),
|
||||
searchResults: (0, _selectors.getFileSearchResults)(state)
|
||||
});
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(SearchBar);
|
|
@ -0,0 +1,194 @@
|
|||
"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 _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"];
|
||||
|
||||
var _Close = require("../shared/Button/Close");
|
||||
|
||||
var _Close2 = _interopRequireDefault(_Close);
|
||||
|
||||
var _actions = require("../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _clipboard = require("../../utils/clipboard");
|
||||
|
||||
var _tabs = require("../../utils/tabs");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
|
||||
|
||||
var _classnames2 = _interopRequireDefault(_classnames);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
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; }
|
||||
|
||||
class Tab extends _react.PureComponent {
|
||||
constructor(...args) {
|
||||
var _temp;
|
||||
|
||||
return _temp = super(...args), this.onTabContextMenu = (event, tab) => {
|
||||
event.preventDefault();
|
||||
this.showContextMenu(event, tab);
|
||||
}, _temp;
|
||||
}
|
||||
|
||||
showContextMenu(e, tab) {
|
||||
const {
|
||||
closeTab,
|
||||
closeTabs,
|
||||
tabSources,
|
||||
showSource,
|
||||
togglePrettyPrint,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
const otherTabs = tabSources.filter(t => t.get("id") !== tab);
|
||||
const sourceTab = tabSources.find(t => t.get("id") == tab);
|
||||
const tabURLs = tabSources.map(t => t.get("url"));
|
||||
const otherTabURLs = otherTabs.map(t => t.get("url"));
|
||||
|
||||
if (!sourceTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isPrettySource = (0, _source.isPretty)(sourceTab);
|
||||
const tabMenuItems = (0, _tabs.getTabMenuItems)();
|
||||
const items = [{
|
||||
item: _objectSpread({}, tabMenuItems.closeTab, {
|
||||
click: () => closeTab(sourceTab.get("url"))
|
||||
})
|
||||
}, {
|
||||
item: _objectSpread({}, tabMenuItems.closeOtherTabs, {
|
||||
click: () => closeTabs(otherTabURLs)
|
||||
}),
|
||||
hidden: () => tabSources.size === 1
|
||||
}, {
|
||||
item: _objectSpread({}, tabMenuItems.closeTabsToEnd, {
|
||||
click: () => {
|
||||
const tabIndex = tabSources.findIndex(t => t.get("id") == tab);
|
||||
closeTabs(tabURLs.filter((t, i) => i > tabIndex));
|
||||
}
|
||||
}),
|
||||
hidden: () => tabSources.size === 1 || tabSources.some((t, i) => t === tab && tabSources.size - 1 === i)
|
||||
}, {
|
||||
item: _objectSpread({}, tabMenuItems.closeAllTabs, {
|
||||
click: () => closeTabs(tabURLs)
|
||||
})
|
||||
}, {
|
||||
item: {
|
||||
type: "separator"
|
||||
}
|
||||
}, {
|
||||
item: _objectSpread({}, tabMenuItems.copyToClipboard, {
|
||||
disabled: selectedSource.get("id") !== tab,
|
||||
click: () => (0, _clipboard.copyToTheClipboard)(sourceTab.text)
|
||||
})
|
||||
}, {
|
||||
item: _objectSpread({}, tabMenuItems.copySourceUri2, {
|
||||
click: () => (0, _clipboard.copyToTheClipboard)((0, _source.getRawSourceURL)(sourceTab.get("url")))
|
||||
})
|
||||
}];
|
||||
items.push({
|
||||
item: _objectSpread({}, tabMenuItems.showSource, {
|
||||
click: () => showSource(tab)
|
||||
})
|
||||
});
|
||||
|
||||
if (!isPrettySource) {
|
||||
items.push({
|
||||
item: _objectSpread({}, tabMenuItems.prettyPrint, {
|
||||
click: () => togglePrettyPrint(tab)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
(0, _devtoolsContextmenu.showMenu)(e, (0, _devtoolsContextmenu.buildMenu)(items));
|
||||
}
|
||||
|
||||
isProjectSearchEnabled() {
|
||||
return this.props.activeSearch === "project";
|
||||
}
|
||||
|
||||
isSourceSearchEnabled() {
|
||||
return this.props.activeSearch === "source";
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
selectedSource,
|
||||
selectSpecificSource,
|
||||
closeTab,
|
||||
source,
|
||||
sourceMetaData
|
||||
} = this.props;
|
||||
const src = source.toJS();
|
||||
const filename = (0, _source.getFilename)(src);
|
||||
const sourceId = source.id;
|
||||
const active = selectedSource && sourceId == selectedSource.get("id") && !this.isProjectSearchEnabled() && !this.isSourceSearchEnabled();
|
||||
const isPrettyCode = (0, _source.isPretty)(source);
|
||||
const sourceAnnotation = (0, _tabs.getSourceAnnotation)(source, sourceMetaData);
|
||||
|
||||
function onClickClose(e) {
|
||||
e.stopPropagation();
|
||||
closeTab(source.url);
|
||||
}
|
||||
|
||||
function handleTabClick(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation(); // Accommodate middle click to close tab
|
||||
|
||||
if (e.button === 1) {
|
||||
return closeTab(source.url);
|
||||
}
|
||||
|
||||
return selectSpecificSource(sourceId);
|
||||
}
|
||||
|
||||
const className = (0, _classnames2.default)("source-tab", {
|
||||
active,
|
||||
pretty: isPrettyCode
|
||||
});
|
||||
return _react2.default.createElement("div", {
|
||||
className: className,
|
||||
key: sourceId,
|
||||
onMouseUp: handleTabClick,
|
||||
onContextMenu: e => this.onTabContextMenu(e, sourceId),
|
||||
title: (0, _source.getFileURL)(src)
|
||||
}, sourceAnnotation, _react2.default.createElement("div", {
|
||||
className: "filename"
|
||||
}, filename), _react2.default.createElement(_Close2.default, {
|
||||
handleClick: onClickClose,
|
||||
tooltip: L10N.getStr("sourceTabs.closeTabButtonTooltip")
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, {
|
||||
source
|
||||
}) => {
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(state);
|
||||
return {
|
||||
tabSources: (0, _selectors.getSourcesForTabs)(state),
|
||||
selectedSource: selectedSource,
|
||||
sourceMetaData: (0, _selectors.getSourceMetaData)(state, source.id),
|
||||
activeSearch: (0, _selectors.getActiveSearch)(state)
|
||||
};
|
||||
};
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Tab);
|
|
@ -0,0 +1,216 @@
|
|||
"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 _immutable = require("devtools/client/shared/vendor/immutable");
|
||||
|
||||
var I = _interopRequireWildcard(_immutable);
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _ui = require("../../utils/ui");
|
||||
|
||||
var _tabs = require("../../utils/tabs");
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _actions = require("../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
var _Tab = require("./Tab");
|
||||
|
||||
var _Tab2 = _interopRequireDefault(_Tab);
|
||||
|
||||
var _PaneToggle = require("../shared/Button/PaneToggle");
|
||||
|
||||
var _PaneToggle2 = _interopRequireDefault(_PaneToggle);
|
||||
|
||||
var _Dropdown = require("../shared/Dropdown");
|
||||
|
||||
var _Dropdown2 = _interopRequireDefault(_Dropdown);
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
class Tabs extends _react.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.updateHiddenTabs = () => {
|
||||
if (!this.refs.sourceTabs) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
selectedSource,
|
||||
tabSources,
|
||||
moveTab
|
||||
} = this.props;
|
||||
const sourceTabEls = this.refs.sourceTabs.children;
|
||||
const hiddenTabs = (0, _tabs.getHiddenTabs)(tabSources, sourceTabEls);
|
||||
|
||||
if ((0, _ui.isVisible)() && hiddenTabs.indexOf(selectedSource) !== -1) {
|
||||
return moveTab(selectedSource.url, 0);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
hiddenTabs
|
||||
});
|
||||
};
|
||||
|
||||
this.renderDropdownSource = source => {
|
||||
const {
|
||||
selectSpecificSource
|
||||
} = this.props;
|
||||
const filename = (0, _source.getFilename)(source.toJS());
|
||||
|
||||
const onClick = () => selectSpecificSource(source.id);
|
||||
|
||||
return _react2.default.createElement("li", {
|
||||
key: source.id,
|
||||
onClick: onClick
|
||||
}, _react2.default.createElement("img", {
|
||||
className: `dropdown-icon ${this.getIconClass(source)}`
|
||||
}), filename);
|
||||
};
|
||||
|
||||
this.state = {
|
||||
dropdownShown: false,
|
||||
hiddenTabs: I.List()
|
||||
};
|
||||
this.onResize = (0, _lodash.debounce)(() => {
|
||||
this.updateHiddenTabs();
|
||||
});
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (!(prevProps === this.props)) {
|
||||
this.updateHiddenTabs();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.requestIdleCallback(this.updateHiddenTabs);
|
||||
window.addEventListener("resize", this.onResize);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener("resize", this.onResize);
|
||||
}
|
||||
/*
|
||||
* Updates the hiddenSourceTabs state, by
|
||||
* finding the source tabs which are wrapped and are not on the top row.
|
||||
*/
|
||||
|
||||
|
||||
toggleSourcesDropdown(e) {
|
||||
this.setState(prevState => ({
|
||||
dropdownShown: !prevState.dropdownShown
|
||||
}));
|
||||
}
|
||||
|
||||
getIconClass(source) {
|
||||
if ((0, _source.isPretty)(source)) {
|
||||
return "prettyPrint";
|
||||
}
|
||||
|
||||
if (source.isBlackBoxed) {
|
||||
return "blackBox";
|
||||
}
|
||||
|
||||
return "file";
|
||||
}
|
||||
|
||||
renderTabs() {
|
||||
const {
|
||||
tabSources
|
||||
} = this.props;
|
||||
|
||||
if (!tabSources) {
|
||||
return;
|
||||
}
|
||||
|
||||
return _react2.default.createElement("div", {
|
||||
className: "source-tabs",
|
||||
ref: "sourceTabs"
|
||||
}, tabSources.map((source, index) => _react2.default.createElement(_Tab2.default, {
|
||||
key: index,
|
||||
source: source
|
||||
})));
|
||||
}
|
||||
|
||||
renderDropdown() {
|
||||
const hiddenTabs = this.state.hiddenTabs;
|
||||
|
||||
if (!hiddenTabs || hiddenTabs.size == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const Panel = _react2.default.createElement("ul", null, hiddenTabs.map(this.renderDropdownSource));
|
||||
|
||||
const icon = _react2.default.createElement("img", {
|
||||
className: "moreTabs"
|
||||
});
|
||||
|
||||
return _react2.default.createElement(_Dropdown2.default, {
|
||||
panel: Panel,
|
||||
icon: icon
|
||||
});
|
||||
}
|
||||
|
||||
renderStartPanelToggleButton() {
|
||||
return _react2.default.createElement(_PaneToggle2.default, {
|
||||
position: "start",
|
||||
collapsed: !this.props.startPanelCollapsed,
|
||||
handleClick: this.props.togglePaneCollapse
|
||||
});
|
||||
}
|
||||
|
||||
renderEndPanelToggleButton() {
|
||||
const {
|
||||
horizontal,
|
||||
endPanelCollapsed,
|
||||
togglePaneCollapse
|
||||
} = this.props;
|
||||
|
||||
if (!horizontal) {
|
||||
return;
|
||||
}
|
||||
|
||||
return _react2.default.createElement(_PaneToggle2.default, {
|
||||
position: "end",
|
||||
collapsed: !endPanelCollapsed,
|
||||
handleClick: togglePaneCollapse,
|
||||
horizontal: horizontal
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return _react2.default.createElement("div", {
|
||||
className: "source-header"
|
||||
}, this.renderStartPanelToggleButton(), this.renderTabs(), this.renderDropdown(), this.renderEndPanelToggleButton());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
selectedSource: (0, _selectors.getSelectedSource)(state),
|
||||
tabSources: (0, _selectors.getSourcesForTabs)(state)
|
||||
});
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Tabs);
|
|
@ -0,0 +1,638 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _propTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
var _propTypes2 = _interopRequireDefault(_propTypes);
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _reactDom = require("devtools/client/shared/vendor/react-dom");
|
||||
|
||||
var _reactDom2 = _interopRequireDefault(_reactDom);
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
|
||||
|
||||
var _classnames2 = _interopRequireDefault(_classnames);
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"];
|
||||
|
||||
var _prefs = require("../../utils/prefs");
|
||||
|
||||
var _indentation = require("../../utils/indentation");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _actions = require("../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _Footer = require("./Footer");
|
||||
|
||||
var _Footer2 = _interopRequireDefault(_Footer);
|
||||
|
||||
var _SearchBar = require("./SearchBar");
|
||||
|
||||
var _SearchBar2 = _interopRequireDefault(_SearchBar);
|
||||
|
||||
var _HighlightLines = require("./HighlightLines");
|
||||
|
||||
var _HighlightLines2 = _interopRequireDefault(_HighlightLines);
|
||||
|
||||
var _Preview = require("./Preview/index");
|
||||
|
||||
var _Preview2 = _interopRequireDefault(_Preview);
|
||||
|
||||
var _Breakpoints = require("./Breakpoints");
|
||||
|
||||
var _Breakpoints2 = _interopRequireDefault(_Breakpoints);
|
||||
|
||||
var _HitMarker = require("./HitMarker");
|
||||
|
||||
var _HitMarker2 = _interopRequireDefault(_HitMarker);
|
||||
|
||||
var _CallSites = require("./CallSites");
|
||||
|
||||
var _CallSites2 = _interopRequireDefault(_CallSites);
|
||||
|
||||
var _DebugLine = require("./DebugLine");
|
||||
|
||||
var _DebugLine2 = _interopRequireDefault(_DebugLine);
|
||||
|
||||
var _HighlightLine = require("./HighlightLine");
|
||||
|
||||
var _HighlightLine2 = _interopRequireDefault(_HighlightLine);
|
||||
|
||||
var _EmptyLines = require("./EmptyLines");
|
||||
|
||||
var _EmptyLines2 = _interopRequireDefault(_EmptyLines);
|
||||
|
||||
var _GutterMenu = require("./GutterMenu");
|
||||
|
||||
var _GutterMenu2 = _interopRequireDefault(_GutterMenu);
|
||||
|
||||
var _EditorMenu = require("./EditorMenu");
|
||||
|
||||
var _EditorMenu2 = _interopRequireDefault(_EditorMenu);
|
||||
|
||||
var _ConditionalPanel = require("./ConditionalPanel");
|
||||
|
||||
var _ConditionalPanel2 = _interopRequireDefault(_ConditionalPanel);
|
||||
|
||||
var _editor = require("../../utils/editor/index");
|
||||
|
||||
var _ui = require("../../utils/ui");
|
||||
|
||||
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/>. */
|
||||
// Redux actions
|
||||
const cssVars = {
|
||||
searchbarHeight: "var(--editor-searchbar-height)",
|
||||
secondSearchbarHeight: "var(--editor-second-searchbar-height)",
|
||||
footerHeight: "var(--editor-footer-height)"
|
||||
};
|
||||
|
||||
class Editor extends _react.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onToggleBreakpoint = (key, e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const {
|
||||
selectedSource,
|
||||
conditionalPanelLine
|
||||
} = this.props;
|
||||
|
||||
if (!selectedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const line = this.getCurrentLine();
|
||||
|
||||
if (e.shiftKey) {
|
||||
this.toggleConditionalPanel(line);
|
||||
} else if (!conditionalPanelLine) {
|
||||
this.props.toggleBreakpoint(line);
|
||||
} else {
|
||||
this.toggleConditionalPanel(line);
|
||||
this.props.toggleBreakpoint(line);
|
||||
}
|
||||
};
|
||||
|
||||
this.onToggleConditionalPanel = (key, e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
const line = this.getCurrentLine();
|
||||
this.toggleConditionalPanel(line);
|
||||
};
|
||||
|
||||
this.onEscape = (key, e) => {
|
||||
if (!this.state.editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
codeMirror
|
||||
} = this.state.editor;
|
||||
|
||||
if (codeMirror.listSelections().length > 1) {
|
||||
codeMirror.execCommand("singleSelection");
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
this.onSearchAgain = (_, e) => {
|
||||
this.props.traverseResults(e.shiftKey, this.state.editor);
|
||||
};
|
||||
|
||||
this.onGutterClick = (cm, line, gutter, ev) => {
|
||||
const {
|
||||
selectedSource,
|
||||
conditionalPanelLine,
|
||||
closeConditionalPanel,
|
||||
addOrToggleDisabledBreakpoint,
|
||||
toggleBreakpoint,
|
||||
continueToHere
|
||||
} = this.props; // ignore right clicks in the gutter
|
||||
|
||||
if (ev.ctrlKey && ev.button === 0 || ev.which === 3 || selectedSource && selectedSource.isBlackBoxed || !selectedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (conditionalPanelLine) {
|
||||
return closeConditionalPanel();
|
||||
}
|
||||
|
||||
if (gutter === "CodeMirror-foldgutter") {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceLine = (0, _editor.toSourceLine)(selectedSource.get("id"), line);
|
||||
|
||||
if (ev.altKey) {
|
||||
return continueToHere(sourceLine);
|
||||
}
|
||||
|
||||
if (ev.shiftKey) {
|
||||
return addOrToggleDisabledBreakpoint(sourceLine);
|
||||
}
|
||||
|
||||
return toggleBreakpoint(sourceLine);
|
||||
};
|
||||
|
||||
this.onGutterContextMenu = event => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
return this.props.setContextMenu("Gutter", event);
|
||||
};
|
||||
|
||||
this.toggleConditionalPanel = line => {
|
||||
const {
|
||||
conditionalPanelLine,
|
||||
closeConditionalPanel,
|
||||
openConditionalPanel
|
||||
} = this.props;
|
||||
|
||||
if (conditionalPanelLine) {
|
||||
return closeConditionalPanel();
|
||||
}
|
||||
|
||||
return openConditionalPanel(line);
|
||||
};
|
||||
|
||||
this.closeConditionalPanel = () => {
|
||||
return this.props.closeConditionalPanel();
|
||||
};
|
||||
|
||||
this.state = {
|
||||
highlightedLineRange: null,
|
||||
editor: null
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (!this.state.editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
(0, _ui.resizeBreakpointGutter)(this.state.editor.codeMirror);
|
||||
(0, _ui.resizeToggleButton)(this.state.editor.codeMirror);
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps) {
|
||||
this.setText(nextProps);
|
||||
this.setSize(nextProps);
|
||||
this.scrollToLocation(nextProps);
|
||||
}
|
||||
|
||||
setupEditor() {
|
||||
const editor = (0, _editor.createEditor)(); // disables the default search shortcuts
|
||||
// $FlowIgnore
|
||||
|
||||
editor._initShortcuts = () => {};
|
||||
|
||||
const node = _reactDom2.default.findDOMNode(this);
|
||||
|
||||
if (node instanceof HTMLElement) {
|
||||
editor.appendToLocalElement(node.querySelector(".editor-mount"));
|
||||
}
|
||||
|
||||
const {
|
||||
codeMirror
|
||||
} = editor;
|
||||
const codeMirrorWrapper = codeMirror.getWrapperElement();
|
||||
(0, _ui.resizeBreakpointGutter)(codeMirror);
|
||||
(0, _ui.resizeToggleButton)(codeMirror);
|
||||
codeMirror.on("gutterClick", this.onGutterClick); // Set code editor wrapper to be focusable
|
||||
|
||||
codeMirrorWrapper.tabIndex = 0;
|
||||
codeMirrorWrapper.addEventListener("keydown", e => this.onKeyDown(e));
|
||||
codeMirrorWrapper.addEventListener("click", e => this.onClick(e));
|
||||
|
||||
const toggleFoldMarkerVisibility = e => {
|
||||
if (node instanceof HTMLElement) {
|
||||
node.querySelectorAll(".CodeMirror-guttermarker-subtle").forEach(elem => {
|
||||
elem.classList.toggle("visible");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const codeMirrorGutter = codeMirror.getGutterElement();
|
||||
codeMirrorGutter.addEventListener("mouseleave", toggleFoldMarkerVisibility);
|
||||
codeMirrorGutter.addEventListener("mouseenter", toggleFoldMarkerVisibility);
|
||||
|
||||
if (!(0, _devtoolsEnvironment.isFirefox)()) {
|
||||
codeMirror.on("gutterContextMenu", (cm, line, eventName, event) => this.onGutterContextMenu(event));
|
||||
codeMirror.on("contextmenu", (cm, event) => this.openMenu(event));
|
||||
} else {
|
||||
codeMirrorWrapper.addEventListener("contextmenu", event => this.openMenu(event));
|
||||
}
|
||||
|
||||
this.setState({
|
||||
editor
|
||||
});
|
||||
(0, _editor.setEditor)(editor);
|
||||
return editor;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
shortcuts
|
||||
} = this.context;
|
||||
const searchAgainKey = L10N.getStr("sourceSearch.search.again.key2");
|
||||
const searchAgainPrevKey = L10N.getStr("sourceSearch.search.againPrev.key2");
|
||||
shortcuts.on(L10N.getStr("toggleBreakpoint.key"), this.onToggleBreakpoint);
|
||||
shortcuts.on(L10N.getStr("toggleCondPanel.key"), this.onToggleConditionalPanel);
|
||||
shortcuts.on("Esc", this.onEscape);
|
||||
shortcuts.on(searchAgainPrevKey, this.onSearchAgain);
|
||||
shortcuts.on(searchAgainKey, this.onSearchAgain);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.state.editor) {
|
||||
this.state.editor.destroy();
|
||||
this.setState({
|
||||
editor: null
|
||||
});
|
||||
}
|
||||
|
||||
const searchAgainKey = L10N.getStr("sourceSearch.search.again.key2");
|
||||
const searchAgainPrevKey = L10N.getStr("sourceSearch.search.againPrev.key2");
|
||||
const shortcuts = this.context.shortcuts;
|
||||
shortcuts.off(L10N.getStr("toggleBreakpoint.key"));
|
||||
shortcuts.off(L10N.getStr("toggleCondPanel.key"));
|
||||
shortcuts.off(searchAgainPrevKey);
|
||||
shortcuts.off(searchAgainKey);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const {
|
||||
selectedSource
|
||||
} = this.props; // NOTE: when devtools are opened, the editor is not set when
|
||||
// the source loads so we need to wait until the editor is
|
||||
// set to update the text and size.
|
||||
|
||||
if (!prevState.editor && selectedSource) {
|
||||
if (!this.state.editor) {
|
||||
const editor = this.setupEditor();
|
||||
(0, _editor.updateDocument)(editor, selectedSource);
|
||||
} else {
|
||||
this.setText(this.props);
|
||||
this.setSize(this.props);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getCurrentLine() {
|
||||
const {
|
||||
codeMirror
|
||||
} = this.state.editor;
|
||||
const {
|
||||
selectedSource
|
||||
} = this.props;
|
||||
const line = (0, _editor.getCursorLine)(codeMirror);
|
||||
return (0, _editor.toSourceLine)(selectedSource.get("id"), line);
|
||||
}
|
||||
|
||||
onKeyDown(e) {
|
||||
const {
|
||||
codeMirror
|
||||
} = this.state.editor;
|
||||
const {
|
||||
key,
|
||||
target
|
||||
} = e;
|
||||
const codeWrapper = codeMirror.getWrapperElement();
|
||||
const textArea = codeWrapper.querySelector("textArea");
|
||||
|
||||
if (key === "Escape" && target == textArea) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
codeWrapper.focus();
|
||||
} else if (key === "Enter" && target == codeWrapper) {
|
||||
e.preventDefault(); // Focus into editor's text area
|
||||
|
||||
textArea.focus();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The default Esc command is overridden in the CodeMirror keymap to allow
|
||||
* the Esc keypress event to be catched by the toolbox and trigger the
|
||||
* split console. Restore it here, but preventDefault if and only if there
|
||||
* is a multiselection.
|
||||
*/
|
||||
|
||||
|
||||
openMenu(event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
const {
|
||||
setContextMenu
|
||||
} = this.props;
|
||||
|
||||
if (event.target.classList.contains("CodeMirror-linenumber")) {
|
||||
return setContextMenu("Gutter", event);
|
||||
}
|
||||
|
||||
return setContextMenu("Editor", event);
|
||||
}
|
||||
|
||||
onClick(e) {
|
||||
const {
|
||||
selectedLocation,
|
||||
jumpToMappedLocation
|
||||
} = this.props;
|
||||
|
||||
if (e.metaKey && e.altKey) {
|
||||
const sourceLocation = (0, _editor.getSourceLocationFromMouseEvent)(this.state.editor, selectedLocation, e);
|
||||
jumpToMappedLocation(sourceLocation);
|
||||
}
|
||||
}
|
||||
|
||||
shouldScrollToLocation(nextProps) {
|
||||
const {
|
||||
selectedLocation,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
const {
|
||||
editor
|
||||
} = this.state;
|
||||
|
||||
if (!nextProps.selectedSource || !editor || !nextProps.selectedLocation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(0, _source.isLoaded)(nextProps.selectedSource)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!nextProps.selectedLocation.line) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const isFirstLoad = (!selectedSource || !(0, _source.isLoaded)(selectedSource)) && (0, _source.isLoaded)(nextProps.selectedSource);
|
||||
const locationChanged = selectedLocation !== nextProps.selectedLocation;
|
||||
return isFirstLoad || locationChanged;
|
||||
}
|
||||
|
||||
scrollToLocation(nextProps) {
|
||||
const {
|
||||
editor
|
||||
} = this.state;
|
||||
|
||||
if (this.shouldScrollToLocation(nextProps)) {
|
||||
let {
|
||||
line,
|
||||
column
|
||||
} = (0, _editor.toEditorPosition)(nextProps.selectedLocation);
|
||||
|
||||
if ((0, _editor.hasDocument)(nextProps.selectedSource.get("id"))) {
|
||||
const doc = (0, _editor.getDocument)(nextProps.selectedSource.get("id"));
|
||||
const lineText = doc.getLine(line);
|
||||
column = Math.max(column, (0, _indentation.getIndentation)(lineText));
|
||||
}
|
||||
|
||||
(0, _editor.scrollToColumn)(editor.codeMirror, line, column);
|
||||
}
|
||||
}
|
||||
|
||||
setSize(nextProps) {
|
||||
if (!this.state.editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextProps.startPanelSize !== this.props.startPanelSize || nextProps.endPanelSize !== this.props.endPanelSize) {
|
||||
this.state.editor.codeMirror.setSize();
|
||||
}
|
||||
}
|
||||
|
||||
setText(props) {
|
||||
const {
|
||||
selectedSource,
|
||||
symbols
|
||||
} = props;
|
||||
|
||||
if (!this.state.editor) {
|
||||
return;
|
||||
} // check if we previously had a selected source
|
||||
|
||||
|
||||
if (!selectedSource) {
|
||||
return this.clearEditor();
|
||||
}
|
||||
|
||||
if (!(0, _source.isLoaded)(selectedSource)) {
|
||||
return (0, _editor.showLoading)(this.state.editor);
|
||||
}
|
||||
|
||||
if (selectedSource.get("error")) {
|
||||
return this.showErrorMessage(selectedSource.get("error"));
|
||||
}
|
||||
|
||||
if (selectedSource) {
|
||||
return (0, _editor.showSourceText)(this.state.editor, selectedSource.toJS(), symbols);
|
||||
}
|
||||
}
|
||||
|
||||
clearEditor() {
|
||||
const {
|
||||
editor
|
||||
} = this.state;
|
||||
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
(0, _editor.clearEditor)(editor);
|
||||
}
|
||||
|
||||
showErrorMessage(msg) {
|
||||
const {
|
||||
editor
|
||||
} = this.state;
|
||||
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
(0, _editor.showErrorMessage)(editor, msg);
|
||||
}
|
||||
|
||||
getInlineEditorStyles() {
|
||||
const {
|
||||
selectedSource,
|
||||
horizontal,
|
||||
searchOn
|
||||
} = this.props;
|
||||
const subtractions = [];
|
||||
|
||||
if ((0, _editor.shouldShowFooter)(selectedSource, horizontal)) {
|
||||
subtractions.push(cssVars.footerHeight);
|
||||
}
|
||||
|
||||
if (searchOn) {
|
||||
subtractions.push(cssVars.searchbarHeight);
|
||||
subtractions.push(cssVars.secondSearchbarHeight);
|
||||
}
|
||||
|
||||
return {
|
||||
height: subtractions.length === 0 ? "100%" : `calc(100% - ${subtractions.join(" - ")})`
|
||||
};
|
||||
}
|
||||
|
||||
renderHitCounts() {
|
||||
const {
|
||||
hitCount,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
|
||||
if (!selectedSource || !(0, _source.isLoaded)(selectedSource) || !hitCount || !this.state.editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
return hitCount.filter(marker => marker.get("count") > 0).map(marker => _react2.default.createElement(_HitMarker2.default, {
|
||||
key: marker.get("line"),
|
||||
hitData: marker.toJS(),
|
||||
editor: this.state.editor.codeMirror
|
||||
}));
|
||||
}
|
||||
|
||||
renderItems() {
|
||||
const {
|
||||
horizontal,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
const {
|
||||
editor
|
||||
} = this.state;
|
||||
|
||||
if (!editor || !selectedSource) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return _react2.default.createElement("div", null, _react2.default.createElement(_DebugLine2.default, null), _react2.default.createElement(_HighlightLine2.default, null), _react2.default.createElement(_EmptyLines2.default, {
|
||||
editor: editor
|
||||
}), _react2.default.createElement(_Breakpoints2.default, {
|
||||
editor: editor
|
||||
}), _react2.default.createElement(_Preview2.default, {
|
||||
editor: editor,
|
||||
editorRef: this.$editorWrapper
|
||||
}), ";", _react2.default.createElement(_Footer2.default, {
|
||||
editor: editor,
|
||||
horizontal: horizontal
|
||||
}), _react2.default.createElement(_HighlightLines2.default, {
|
||||
editor: editor
|
||||
}), _react2.default.createElement(_EditorMenu2.default, {
|
||||
editor: editor
|
||||
}), _react2.default.createElement(_GutterMenu2.default, {
|
||||
editor: editor
|
||||
}), _react2.default.createElement(_ConditionalPanel2.default, {
|
||||
editor: editor
|
||||
}), _prefs.features.columnBreakpoints ? _react2.default.createElement(_CallSites2.default, {
|
||||
editor: editor
|
||||
}) : null, this.renderHitCounts());
|
||||
}
|
||||
|
||||
renderSearchBar() {
|
||||
const {
|
||||
editor
|
||||
} = this.state;
|
||||
|
||||
if (!editor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return _react2.default.createElement(_SearchBar2.default, {
|
||||
editor: editor
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
coverageOn
|
||||
} = this.props;
|
||||
return _react2.default.createElement("div", {
|
||||
className: (0, _classnames2.default)("editor-wrapper", {
|
||||
"coverage-on": coverageOn
|
||||
}),
|
||||
ref: c => this.$editorWrapper = c
|
||||
}, this.renderSearchBar(), _react2.default.createElement("div", {
|
||||
className: "editor-mount devtools-monospace",
|
||||
style: this.getInlineEditorStyles()
|
||||
}), this.renderItems());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Editor.contextTypes = {
|
||||
shortcuts: _propTypes2.default.object
|
||||
};
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(state);
|
||||
const sourceId = selectedSource ? selectedSource.get("id") : "";
|
||||
return {
|
||||
selectedLocation: (0, _selectors.getSelectedLocation)(state),
|
||||
selectedSource,
|
||||
searchOn: (0, _selectors.getActiveSearch)(state) === "file",
|
||||
hitCount: (0, _selectors.getHitCountForSource)(state, sourceId),
|
||||
coverageOn: (0, _selectors.getCoverageEnabled)(state),
|
||||
conditionalPanelLine: (0, _selectors.getConditionalPanelLine)(state),
|
||||
symbols: (0, _selectors.getSymbols)(state, selectedSource && selectedSource.toJS())
|
||||
};
|
||||
};
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Editor);
|
|
@ -0,0 +1,28 @@
|
|||
# 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 += [
|
||||
'Preview',
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'Breakpoint.js',
|
||||
'Breakpoints.js',
|
||||
'CallSite.js',
|
||||
'CallSites.js',
|
||||
'ConditionalPanel.js',
|
||||
'DebugLine.js',
|
||||
'EditorMenu.js',
|
||||
'EmptyLines.js',
|
||||
'Footer.js',
|
||||
'GutterMenu.js',
|
||||
'HighlightLine.js',
|
||||
'HighlightLines.js',
|
||||
'HitMarker.js',
|
||||
'index.js',
|
||||
'SearchBar.js',
|
||||
'Tab.js',
|
||||
'Tabs.js',
|
||||
)
|
|
@ -0,0 +1,205 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.Outline = undefined;
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"];
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _clipboard = require("../../utils/clipboard");
|
||||
|
||||
var _function = require("../../utils/function");
|
||||
|
||||
var _actions = require("../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _PreviewFunction = require("../shared/PreviewFunction");
|
||||
|
||||
var _PreviewFunction2 = _interopRequireDefault(_PreviewFunction);
|
||||
|
||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
class Outline extends _react.Component {
|
||||
selectItem(location) {
|
||||
const {
|
||||
selectedSource,
|
||||
selectLocation
|
||||
} = this.props;
|
||||
|
||||
if (!selectedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedSourceId = selectedSource.get("id");
|
||||
const startLine = location.start.line;
|
||||
selectLocation({
|
||||
sourceId: selectedSourceId,
|
||||
line: startLine
|
||||
});
|
||||
}
|
||||
|
||||
onContextMenu(event, func) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
const {
|
||||
selectedSource,
|
||||
getFunctionText,
|
||||
flashLineRange,
|
||||
selectedLocation
|
||||
} = this.props;
|
||||
const copyFunctionKey = L10N.getStr("copyFunction.accesskey");
|
||||
const copyFunctionLabel = L10N.getStr("copyFunction.label");
|
||||
|
||||
if (!selectedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceLine = func.location.start.line;
|
||||
const functionText = getFunctionText(sourceLine);
|
||||
const copyFunctionItem = {
|
||||
id: "node-menu-copy-function",
|
||||
label: copyFunctionLabel,
|
||||
accesskey: copyFunctionKey,
|
||||
disabled: !functionText,
|
||||
click: () => {
|
||||
flashLineRange({
|
||||
start: func.location.start.line,
|
||||
end: func.location.end.line,
|
||||
sourceId: selectedLocation.sourceId
|
||||
});
|
||||
return (0, _clipboard.copyToTheClipboard)(functionText);
|
||||
}
|
||||
};
|
||||
const menuOptions = [copyFunctionItem];
|
||||
(0, _devtoolsContextmenu.showMenu)(event, menuOptions);
|
||||
}
|
||||
|
||||
renderPlaceholder() {
|
||||
const placeholderMessage = this.props.selectedSource ? L10N.getStr("outline.noFunctions") : L10N.getStr("outline.noFileSelected");
|
||||
return _react2.default.createElement("div", {
|
||||
className: "outline-pane-info"
|
||||
}, placeholderMessage);
|
||||
}
|
||||
|
||||
renderLoading() {
|
||||
return _react2.default.createElement("div", {
|
||||
className: "outline-pane-info"
|
||||
}, L10N.getStr("loadingText"));
|
||||
}
|
||||
|
||||
renderFunction(func) {
|
||||
const {
|
||||
name,
|
||||
location,
|
||||
parameterNames
|
||||
} = func;
|
||||
return _react2.default.createElement("li", {
|
||||
key: `${name}:${location.start.line}:${location.start.column}`,
|
||||
className: "outline-list__element",
|
||||
onClick: () => this.selectItem(location),
|
||||
onContextMenu: e => this.onContextMenu(e, func)
|
||||
}, _react2.default.createElement("span", {
|
||||
className: "outline-list__element-icon"
|
||||
}, "\u03BB"), _react2.default.createElement(_PreviewFunction2.default, {
|
||||
func: {
|
||||
name,
|
||||
parameterNames
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
renderClassFunctions(klass, functions) {
|
||||
if (klass == null || functions.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const classFunc = functions.find(func => func.name === klass);
|
||||
const classFunctions = functions.filter(func => func.klass === klass);
|
||||
const classInfo = this.props.symbols.classes.find(c => c.name === klass);
|
||||
const heading = classFunc ? _react2.default.createElement("h2", null, this.renderFunction(classFunc)) : _react2.default.createElement("h2", {
|
||||
onClick: classInfo ? () => this.selectItem(classInfo.location) : null
|
||||
}, _react2.default.createElement("span", {
|
||||
className: "keyword"
|
||||
}, "class"), " ", klass);
|
||||
return _react2.default.createElement("div", {
|
||||
className: "outline-list__class",
|
||||
key: klass
|
||||
}, heading, _react2.default.createElement("ul", {
|
||||
className: "outline-list__class-list"
|
||||
}, classFunctions.map(func => this.renderFunction(func))));
|
||||
}
|
||||
|
||||
renderFunctions(functions) {
|
||||
let classes = (0, _lodash.uniq)(functions.map(func => func.klass));
|
||||
let namedFunctions = functions.filter(func => func.name != "anonymous" && !func.klass && !classes.includes(func.name));
|
||||
let classFunctions = functions.filter(func => func.name != "anonymous" && !!func.klass);
|
||||
|
||||
if (this.props.alphabetizeOutline) {
|
||||
namedFunctions = (0, _lodash.sortBy)(namedFunctions, "name");
|
||||
classes = (0, _lodash.sortBy)(classes, "klass");
|
||||
classFunctions = (0, _lodash.sortBy)(classFunctions, "name");
|
||||
}
|
||||
|
||||
return _react2.default.createElement("div", null, _react2.default.createElement("ul", {
|
||||
className: "outline-list"
|
||||
}, namedFunctions.map(func => this.renderFunction(func)), classes.map(klass => this.renderClassFunctions(klass, classFunctions))), _react2.default.createElement("div", {
|
||||
className: "outline-footer bottom"
|
||||
}, _react2.default.createElement("button", {
|
||||
onClick: () => {
|
||||
this.props.onAlphabetizeClick();
|
||||
},
|
||||
className: this.props.alphabetizeOutline ? "active" : ""
|
||||
}, L10N.getStr("outline.sortLabel"))));
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
symbols,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
|
||||
if (!selectedSource) {
|
||||
return this.renderPlaceholder();
|
||||
}
|
||||
|
||||
if (!symbols || symbols.loading) {
|
||||
return this.renderLoading();
|
||||
}
|
||||
|
||||
const symbolsToDisplay = symbols.functions.filter(func => func.name != "anonymous");
|
||||
return _react2.default.createElement("div", {
|
||||
className: "outline"
|
||||
}, symbolsToDisplay.length > 0 ? this.renderFunctions(symbols.functions) : this.renderPlaceholder());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.Outline = Outline;
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(state);
|
||||
const symbols = (0, _selectors.getSymbols)(state, selectedSource);
|
||||
return {
|
||||
symbols,
|
||||
selectedSource,
|
||||
selectedLocation: (0, _selectors.getSelectedLocation)(state),
|
||||
getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource, symbols)
|
||||
};
|
||||
};
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Outline);
|
|
@ -0,0 +1,415 @@
|
|||
"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 _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"];
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _sourceTree = require("../../actions/source-tree");
|
||||
|
||||
var _sources = require("../../actions/sources/index");
|
||||
|
||||
var _ui = require("../../actions/ui");
|
||||
|
||||
var _ManagedTree = require("../shared/ManagedTree");
|
||||
|
||||
var _ManagedTree2 = _interopRequireDefault(_ManagedTree);
|
||||
|
||||
var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"];
|
||||
|
||||
var _Svg2 = _interopRequireDefault(_Svg);
|
||||
|
||||
var _sourcesTree = require("../../utils/sources-tree/index");
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _clipboard = require("../../utils/clipboard");
|
||||
|
||||
var _prefs = require("../../utils/prefs");
|
||||
|
||||
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/>. */
|
||||
// Dependencies
|
||||
// Selectors
|
||||
// Actions
|
||||
// Components
|
||||
// Utils
|
||||
class SourcesTree extends _react.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
_initialiseProps.call(this);
|
||||
|
||||
const {
|
||||
debuggeeUrl,
|
||||
sources,
|
||||
projectRoot
|
||||
} = this.props;
|
||||
this.state = (0, _sourcesTree.createTree)({
|
||||
projectRoot,
|
||||
debuggeeUrl,
|
||||
sources
|
||||
});
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const {
|
||||
projectRoot,
|
||||
debuggeeUrl,
|
||||
sources,
|
||||
shownSource,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
const {
|
||||
uncollapsedTree,
|
||||
sourceTree
|
||||
} = this.state;
|
||||
|
||||
if (projectRoot != nextProps.projectRoot || debuggeeUrl != nextProps.debuggeeUrl || nextProps.sources.size === 0) {
|
||||
// early recreate tree because of changes
|
||||
// to project root, debugee url or lack of sources
|
||||
return this.setState((0, _sourcesTree.createTree)({
|
||||
sources: nextProps.sources,
|
||||
debuggeeUrl: nextProps.debuggeeUrl,
|
||||
projectRoot: nextProps.projectRoot
|
||||
}));
|
||||
}
|
||||
|
||||
if (nextProps.shownSource && nextProps.shownSource != shownSource) {
|
||||
const listItems = (0, _sourcesTree.getDirectories)(nextProps.shownSource, sourceTree);
|
||||
|
||||
if (listItems && listItems[0]) {
|
||||
this.selectItem(listItems[0]);
|
||||
}
|
||||
|
||||
return this.setState({
|
||||
listItems
|
||||
});
|
||||
}
|
||||
|
||||
if (nextProps.selectedSource && nextProps.selectedSource != selectedSource) {
|
||||
const highlightItems = (0, _sourcesTree.getDirectories)((0, _source.getRawSourceURL)(nextProps.selectedSource.get("url")), sourceTree);
|
||||
return this.setState({
|
||||
highlightItems
|
||||
});
|
||||
} // NOTE: do not run this every time a source is clicked,
|
||||
// only when a new source is added
|
||||
|
||||
|
||||
if (nextProps.sources != this.props.sources) {
|
||||
this.setState((0, _sourcesTree.updateTree)({
|
||||
newSources: nextProps.sources,
|
||||
prevSources: sources,
|
||||
debuggeeUrl,
|
||||
projectRoot,
|
||||
uncollapsedTree,
|
||||
sourceTree
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
renderItemName(name) {
|
||||
const hosts = {
|
||||
"ng://": "Angular",
|
||||
"webpack://": "Webpack",
|
||||
"moz-extension://": L10N.getStr("extensionsText")
|
||||
};
|
||||
return hosts[name] || name;
|
||||
}
|
||||
|
||||
renderEmptyElement(message) {
|
||||
return _react2.default.createElement("div", {
|
||||
className: "no-sources-message"
|
||||
}, message);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
expanded,
|
||||
projectRoot
|
||||
} = this.props;
|
||||
const {
|
||||
focusedItem,
|
||||
highlightItems,
|
||||
listItems,
|
||||
parentMap,
|
||||
sourceTree
|
||||
} = this.state;
|
||||
|
||||
const onExpand = (item, expandedState) => {
|
||||
this.props.setExpandedState(expandedState);
|
||||
};
|
||||
|
||||
const onCollapse = (item, expandedState) => {
|
||||
this.props.setExpandedState(expandedState);
|
||||
};
|
||||
|
||||
const isEmpty = sourceTree.contents.length === 0;
|
||||
const isCustomRoot = projectRoot !== "";
|
||||
|
||||
let roots = () => sourceTree.contents;
|
||||
|
||||
let clearProjectRootButton = null; // The "sourceTree.contents[0]" check ensures that there are contents
|
||||
// A custom root with no existing sources will be ignored
|
||||
|
||||
if (isCustomRoot) {
|
||||
const sourceContents = sourceTree.contents[0];
|
||||
let rootLabel = projectRoot.split("/").pop();
|
||||
|
||||
roots = () => sourceContents.contents;
|
||||
|
||||
if (sourceContents && sourceContents.name !== rootLabel) {
|
||||
rootLabel = sourceContents.contents[0].name;
|
||||
|
||||
roots = () => sourceContents.contents[0].contents;
|
||||
}
|
||||
|
||||
clearProjectRootButton = _react2.default.createElement("button", {
|
||||
className: "sources-clear-root",
|
||||
onClick: () => this.props.clearProjectDirectoryRoot(),
|
||||
title: L10N.getStr("removeDirectoryRoot.label")
|
||||
}, _react2.default.createElement(_Svg2.default, {
|
||||
name: "home"
|
||||
}), _react2.default.createElement(_Svg2.default, {
|
||||
name: "breadcrumb",
|
||||
"class": true
|
||||
}), _react2.default.createElement("span", {
|
||||
className: "sources-clear-root-label"
|
||||
}, rootLabel));
|
||||
}
|
||||
|
||||
if (isEmpty && !isCustomRoot) {
|
||||
return this.renderEmptyElement(L10N.getStr("sources.noSourcesAvailable"));
|
||||
}
|
||||
|
||||
const treeProps = {
|
||||
autoExpandAll: false,
|
||||
autoExpandDepth: expanded ? 0 : 1,
|
||||
expanded,
|
||||
getChildren: item => (0, _sourcesTree.nodeHasChildren)(item) ? item.contents : [],
|
||||
getParent: item => parentMap.get(item),
|
||||
getPath: this.getPath,
|
||||
getRoots: roots,
|
||||
highlightItems,
|
||||
itemHeight: 21,
|
||||
key: isEmpty ? "empty" : "full",
|
||||
listItems,
|
||||
onCollapse,
|
||||
onExpand,
|
||||
onFocus: this.focusItem,
|
||||
renderItem: this.renderItem
|
||||
};
|
||||
|
||||
const tree = _react2.default.createElement(_ManagedTree2.default, treeProps);
|
||||
|
||||
const onKeyDown = e => {
|
||||
if (e.keyCode === 13 && focusedItem) {
|
||||
this.selectItem(focusedItem);
|
||||
}
|
||||
};
|
||||
|
||||
return _react2.default.createElement("div", {
|
||||
className: (0, _classnames2.default)("sources-pane", {
|
||||
"sources-list-custom-root": isCustomRoot
|
||||
})
|
||||
}, isCustomRoot ? _react2.default.createElement("div", {
|
||||
className: "sources-clear-root-container"
|
||||
}, clearProjectRootButton) : null, isEmpty ? this.renderEmptyElement(L10N.getStr("sources.noSourcesAvailableRoot")) : _react2.default.createElement("div", {
|
||||
className: "sources-list",
|
||||
onKeyDown: onKeyDown
|
||||
}, tree));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var _initialiseProps = function () {
|
||||
this.focusItem = item => {
|
||||
this.setState({
|
||||
focusedItem: item
|
||||
});
|
||||
};
|
||||
|
||||
this.selectItem = item => {
|
||||
if (!(0, _sourcesTree.nodeHasChildren)(item)) {
|
||||
this.props.selectLocation({
|
||||
sourceId: item.contents.get("id")
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.getPath = item => {
|
||||
const {
|
||||
sources
|
||||
} = this.props;
|
||||
const obj = item.contents.get && item.contents.get("id");
|
||||
let blackBoxedPart = "";
|
||||
|
||||
if (typeof obj !== "undefined" && sources.has(obj) && sources.get(obj).get("isBlackBoxed")) {
|
||||
blackBoxedPart = "update";
|
||||
}
|
||||
|
||||
return `${item.path}/${item.name}/${blackBoxedPart}`;
|
||||
};
|
||||
|
||||
this.getIcon = (sources, item, depth) => {
|
||||
const {
|
||||
debuggeeUrl,
|
||||
projectRoot
|
||||
} = this.props;
|
||||
|
||||
if (item.path === "webpack://") {
|
||||
return _react2.default.createElement(_Svg2.default, {
|
||||
name: "webpack"
|
||||
});
|
||||
} else if (item.path === "ng://") {
|
||||
return _react2.default.createElement(_Svg2.default, {
|
||||
name: "angular"
|
||||
});
|
||||
} else if (item.path === "moz-extension://") {
|
||||
return _react2.default.createElement("img", {
|
||||
className: "extension"
|
||||
});
|
||||
}
|
||||
|
||||
if (depth === 0 && projectRoot === "") {
|
||||
return _react2.default.createElement("img", {
|
||||
className: (0, _classnames2.default)("domain", {
|
||||
debuggee: debuggeeUrl && debuggeeUrl.includes(item.name)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (!(0, _sourcesTree.nodeHasChildren)(item)) {
|
||||
const obj = item.contents.get("id");
|
||||
const source = sources.get(obj);
|
||||
const className = (0, _classnames2.default)((0, _source.getSourceClassnames)(source), "source-icon");
|
||||
return _react2.default.createElement("img", {
|
||||
className: className
|
||||
});
|
||||
}
|
||||
|
||||
return _react2.default.createElement("img", {
|
||||
className: "folder"
|
||||
});
|
||||
};
|
||||
|
||||
this.onContextMenu = (event, item) => {
|
||||
const copySourceUri2Label = L10N.getStr("copySourceUri2");
|
||||
const copySourceUri2Key = L10N.getStr("copySourceUri2.accesskey");
|
||||
const setDirectoryRootLabel = L10N.getStr("setDirectoryRoot.label");
|
||||
const setDirectoryRootKey = L10N.getStr("setDirectoryRoot.accesskey");
|
||||
const removeDirectoryRootLabel = L10N.getStr("removeDirectoryRoot.label");
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
const menuOptions = [];
|
||||
|
||||
if (!(0, _sourcesTree.isDirectory)(item)) {
|
||||
const source = item.contents.get("url");
|
||||
const copySourceUri2 = {
|
||||
id: "node-menu-copy-source",
|
||||
label: copySourceUri2Label,
|
||||
accesskey: copySourceUri2Key,
|
||||
disabled: false,
|
||||
click: () => (0, _clipboard.copyToTheClipboard)(source)
|
||||
};
|
||||
menuOptions.push(copySourceUri2);
|
||||
}
|
||||
|
||||
if ((0, _sourcesTree.isDirectory)(item) && _prefs.features.root) {
|
||||
const {
|
||||
path
|
||||
} = item;
|
||||
const {
|
||||
projectRoot
|
||||
} = this.props;
|
||||
|
||||
if (projectRoot.endsWith(path)) {
|
||||
menuOptions.push({
|
||||
id: "node-remove-directory-root",
|
||||
label: removeDirectoryRootLabel,
|
||||
disabled: false,
|
||||
click: () => this.props.clearProjectDirectoryRoot()
|
||||
});
|
||||
} else {
|
||||
menuOptions.push({
|
||||
id: "node-set-directory-root",
|
||||
label: setDirectoryRootLabel,
|
||||
accesskey: setDirectoryRootKey,
|
||||
disabled: false,
|
||||
click: () => this.props.setProjectDirectoryRoot(path)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
(0, _devtoolsContextmenu.showMenu)(event, menuOptions);
|
||||
};
|
||||
|
||||
this.renderItem = (item, depth, focused, _, expanded, {
|
||||
setExpanded
|
||||
}) => {
|
||||
const arrow = (0, _sourcesTree.nodeHasChildren)(item) ? _react2.default.createElement("img", {
|
||||
className: (0, _classnames2.default)("arrow", {
|
||||
expanded: expanded
|
||||
})
|
||||
}) : _react2.default.createElement("i", {
|
||||
className: "no-arrow"
|
||||
});
|
||||
const {
|
||||
sources
|
||||
} = this.props;
|
||||
const icon = this.getIcon(sources, item, depth);
|
||||
return _react2.default.createElement("div", {
|
||||
className: (0, _classnames2.default)("node", {
|
||||
focused
|
||||
}),
|
||||
key: item.path,
|
||||
onClick: e => {
|
||||
this.focusItem(item);
|
||||
|
||||
if ((0, _sourcesTree.isDirectory)(item)) {
|
||||
setExpanded(item, !!expanded, e.altKey);
|
||||
} else {
|
||||
this.selectItem(item);
|
||||
}
|
||||
},
|
||||
onContextMenu: e => this.onContextMenu(e, item)
|
||||
}, arrow, icon, _react2.default.createElement("span", {
|
||||
className: "label"
|
||||
}, " ", this.renderItemName(item.name), " "));
|
||||
};
|
||||
};
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
shownSource: (0, _selectors.getShownSource)(state),
|
||||
selectedSource: (0, _selectors.getSelectedSource)(state),
|
||||
debuggeeUrl: (0, _selectors.getDebuggeeUrl)(state),
|
||||
expanded: (0, _selectors.getExpandedState)(state),
|
||||
projectRoot: (0, _selectors.getProjectDirectoryRoot)(state),
|
||||
sources: (0, _selectors.getSources)(state)
|
||||
};
|
||||
};
|
||||
|
||||
const actionCreators = {
|
||||
setExpandedState: _sourceTree.setExpandedState,
|
||||
selectLocation: _sources.selectLocation,
|
||||
setProjectDirectoryRoot: _ui.setProjectDirectoryRoot,
|
||||
clearProjectDirectoryRoot: _ui.clearProjectDirectoryRoot
|
||||
};
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, actionCreators)(SourcesTree);
|
|
@ -0,0 +1,127 @@
|
|||
"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 _text = require("../../utils/text");
|
||||
|
||||
var _actions = require("../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _prefs = require("../../utils/prefs");
|
||||
|
||||
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
|
||||
|
||||
var _classnames2 = _interopRequireDefault(_classnames);
|
||||
|
||||
var _Outline = require("./Outline");
|
||||
|
||||
var _Outline2 = _interopRequireDefault(_Outline);
|
||||
|
||||
var _SourcesTree = require("./SourcesTree");
|
||||
|
||||
var _SourcesTree2 = _interopRequireDefault(_SourcesTree);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
class PrimaryPanes extends _react.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.showPane = selectedPane => {
|
||||
this.props.setPrimaryPaneTab(selectedPane);
|
||||
};
|
||||
|
||||
this.onAlphabetizeClick = () => {
|
||||
const alphabetizeOutline = !_prefs.prefs.alphabetizeOutline;
|
||||
_prefs.prefs.alphabetizeOutline = alphabetizeOutline;
|
||||
this.setState({
|
||||
alphabetizeOutline
|
||||
});
|
||||
};
|
||||
|
||||
this.renderTabs = () => {
|
||||
return _react2.default.createElement("div", {
|
||||
className: "source-outline-tabs"
|
||||
}, this.renderOutlineTabs());
|
||||
};
|
||||
|
||||
this.renderShortcut = () => {
|
||||
if (this.props.horizontal) {
|
||||
const onClick = () => {
|
||||
if (this.props.sourceSearchOn) {
|
||||
return this.props.closeActiveSearch();
|
||||
}
|
||||
|
||||
this.props.setActiveSearch("source");
|
||||
};
|
||||
|
||||
return _react2.default.createElement("span", {
|
||||
className: "sources-header-info",
|
||||
dir: "ltr",
|
||||
onClick: onClick
|
||||
}, L10N.getFormatStr("sources.search", (0, _text.formatKeyShortcut)(L10N.getStr("sources.search.key2"))));
|
||||
}
|
||||
};
|
||||
|
||||
this.state = {
|
||||
alphabetizeOutline: _prefs.prefs.alphabetizeOutline
|
||||
};
|
||||
}
|
||||
|
||||
renderOutlineTabs() {
|
||||
if (!_prefs.features.outline) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sources = (0, _text.formatKeyShortcut)(L10N.getStr("sources.header"));
|
||||
const outline = (0, _text.formatKeyShortcut)(L10N.getStr("outline.header"));
|
||||
return [_react2.default.createElement("div", {
|
||||
className: (0, _classnames2.default)("tab sources-tab", {
|
||||
active: this.props.selectedTab === "sources"
|
||||
}),
|
||||
onClick: () => this.showPane("sources"),
|
||||
key: "sources-tab"
|
||||
}, sources), _react2.default.createElement("div", {
|
||||
className: (0, _classnames2.default)("tab outline-tab", {
|
||||
active: this.props.selectedTab === "outline"
|
||||
}),
|
||||
onClick: () => this.showPane("outline"),
|
||||
key: "outline-tab"
|
||||
}, outline)];
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
selectedTab
|
||||
} = this.props;
|
||||
return _react2.default.createElement("div", {
|
||||
className: "sources-panel"
|
||||
}, this.renderTabs(), selectedTab === "sources" ? _react2.default.createElement(_SourcesTree2.default, null) : _react2.default.createElement(_Outline2.default, {
|
||||
alphabetizeOutline: this.state.alphabetizeOutline,
|
||||
onAlphabetizeClick: this.onAlphabetizeClick
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
selectedTab: (0, _selectors.getSelectedPrimaryPaneTab)(state),
|
||||
sources: (0, _selectors.getSources)(state),
|
||||
sourceSearchOn: (0, _selectors.getActiveSearch)(state) === "source"
|
||||
});
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(PrimaryPanes);
|
|
@ -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(
|
||||
'index.js',
|
||||
'Outline.js',
|
||||
'SourcesTree.js',
|
||||
)
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче