Bug 1532162 - Map Scopes should be opt-in. r=loganfsmyth

Differential Revision: https://phabricator.services.mozilla.com/D21870

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jason Laster 2019-03-07 13:50:36 +00:00
Родитель 17ca504ef6
Коммит fb790261c6
13 изменённых файлов: 224 добавлений и 38 удалений

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

@ -4017,6 +4017,42 @@ html[dir="rtl"] .event-listeners-content .arrow.expanded {
* 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/>. */
.scopes-content .toggle-map-scopes {
border-bottom: 1px solid var(--theme-splitter-color);
margin-bottom: 3px;
margin-left: 10px;
padding: 0.5em 0;
}
.scopes-content .toggle-map-scopes input {
padding-inline-start: 2px;
margin-inline-start: 0;
vertical-align: text-bottom;
}
.scopes-content .toggle-map-scopes-label {
padding-inline-start: 2px;
padding-inline-end: 8px;
cursor: default;
flex-grow: 1;
-moz-user-select: none;
}
.scopes-content .toggle-map-scopes a.mdn {
padding-inline-end: 10px;
}
.scopes-content .toggle-map-scopes .img.shortcuts {
background: var(--theme-comment);
}
.scopes-content .toggle-map-scopes {
display: flex;
align-items: center;
}
.object-node.default-property {
opacity: 0.6;
}

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

@ -30,3 +30,4 @@ export { setPopupObjectProperties } from "./setPopupObjectProperties";
export { pauseOnExceptions } from "./pauseOnExceptions";
export { selectFrame } from "./selectFrame";
export { toggleSkipPausing } from "./skipPausing";
export { toggleMapScopes } from "./mapScopes";

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

@ -4,7 +4,14 @@
// @flow
import { getCurrentThread, getSource } from "../../selectors";
import {
getCurrentThread,
getSource,
getMapScopes,
getSelectedFrame,
getSelectedGeneratedScope,
getSelectedOriginalScope
} from "../../selectors";
import { loadSourceText } from "../sources/loadSourceText";
import { PROMISE } from "../utils/middleware/promise";
@ -17,6 +24,28 @@ import type { ThunkArgs } from "../types";
import { buildMappedScopes } from "../../utils/pause/mapScopes";
export function toggleMapScopes() {
return async function({ dispatch, getState, client, sourceMaps }: ThunkArgs) {
if (getMapScopes(getState())) {
return dispatch({ type: "TOGGLE_MAP_SCOPES", mapScopes: false });
}
dispatch({ type: "TOGGLE_MAP_SCOPES", mapScopes: true });
if (getSelectedOriginalScope(getState())) {
return;
}
const scopes = getSelectedGeneratedScope(getState());
const frame = getSelectedFrame(getState());
if (!scopes || !frame) {
return;
}
dispatch(mapScopes(Promise.resolve(scopes.scope), frame));
};
}
export function mapScopes(scopes: Promise<Scope>, frame: Frame) {
return async function({ dispatch, getState, client, sourceMaps }: ThunkArgs) {
const generatedSource = getSource(

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

@ -15,8 +15,8 @@ import { simpleMockThreadClient } from "./helpers/threadClient.js";
import { asyncStore } from "../../utils/prefs";
function loadInitialState(opts = {}) {
const mockedPendingBreakpoint = mockPendingBreakpoint({...opts, column: 2});
const id = makePendingLocationId(mockedPendingBreakpoint.location)
const mockedPendingBreakpoint = mockPendingBreakpoint({ ...opts, column: 2 });
const id = makePendingLocationId(mockedPendingBreakpoint.location);
asyncStore.pendingBreakpoints = { [id]: mockedPendingBreakpoint };
return { pendingBreakpoints: asyncStore.pendingBreakpoints };
@ -61,7 +61,11 @@ function mockClient(bpPos = {}) {
function mockSourceMaps() {
return {
...sourceMaps,
getOriginalSourceText: async (source) => ({id: source.id, text: "", contentType: "text/javascript"}),
getOriginalSourceText: async source => ({
id: source.id,
text: "",
contentType: "text/javascript"
}),
getGeneratedRangesForOriginal: async () => [
{ start: { line: 0, column: 0 }, end: { line: 10, column: 10 } }
]
@ -364,23 +368,19 @@ describe("adding sources", () => {
it("corresponding breakpoints are added to the original source", async () => {
const source = makeOriginalSource("bar.js", { sourceMapURL: "foo" });
const store = createStore(
mockClient({ "5": [2] }),
loadInitialState(),
{
getOriginalURLs: async () => [source.url],
getOriginalSourceText: async () => ({ source: "" }),
getGeneratedLocation: async (location, _source) => ({
line: location.line,
column: location.column,
sourceId: _source.id
}),
getOriginalLocation: async location => location,
getGeneratedRangesForOriginal: async () => [
{ start: { line: 0, column: 0 }, end: { line: 10, column: 10 } }
]
}
);
const store = createStore(mockClient({ "5": [2] }), loadInitialState(), {
getOriginalURLs: async () => [source.url],
getOriginalSourceText: async () => ({ source: "" }),
getGeneratedLocation: async (location, _source) => ({
line: location.line,
column: location.column,
sourceId: _source.id
}),
getOriginalLocation: async location => location,
getGeneratedRangesForOriginal: async () => [
{ start: { line: 0, column: 0 }, end: { line: 10, column: 10 } }
]
});
const { getState, dispatch } = store;

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

@ -130,4 +130,8 @@ export type PauseAction =
+type: "TOGGLE_SKIP_PAUSING",
+thread: string,
skipPausing: boolean
|}
| {|
+type: "TOGGLE_MAP_SCOPES",
+mapScopes: boolean
|};

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

@ -2,6 +2,42 @@
* 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/>. */
.scopes-content .toggle-map-scopes {
border-bottom: 1px solid var(--theme-splitter-color);
margin-bottom: 3px;
margin-left: 10px;
padding: 0.5em 0;
}
.scopes-content .toggle-map-scopes input {
padding-inline-start: 2px;
margin-inline-start: 0;
vertical-align: text-bottom;
}
.scopes-content .toggle-map-scopes-label {
padding-inline-start: 2px;
padding-inline-end: 8px;
cursor: default;
flex-grow: 1;
-moz-user-select: none;
}
.scopes-content .toggle-map-scopes a.mdn {
padding-inline-end: 10px;
}
.scopes-content .toggle-map-scopes .img.shortcuts {
background: var(--theme-comment);
}
.scopes-content .toggle-map-scopes {
display: flex;
align-items: center;
}
.object-node.default-property {
opacity: 0.6;
}

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

@ -4,7 +4,9 @@
// @flow
import React, { PureComponent } from "react";
import { isGeneratedId } from "devtools-source-map";
import { connect } from "../../utils/connect";
import { features } from "../../utils/prefs";
import actions from "../../actions";
import { createObjectClient } from "../../client/firefox";
@ -14,17 +16,21 @@ import {
getGeneratedFrameScope,
getOriginalFrameScope,
isPaused as getIsPaused,
getPauseReason
getPauseReason,
getMapScopes
} from "../../selectors";
import { getScopes } from "../../utils/pause/scopes";
import { objectInspector } from "devtools-reps";
import AccessibleImage from "../shared/AccessibleImage";
import type { Why } from "../../types";
import type { NamedValue } from "../../utils/pause/scopes/types";
import "./Scopes.css";
const mdnLink = "https://developer.mozilla.org/en-US/docs/Tools/Debugger";
const { ObjectInspector } = objectInspector;
type Props = {
@ -34,8 +40,10 @@ type Props = {
originalFrameScopes: Object | null,
isLoading: boolean,
why: Why,
shouldMapScopes: boolean,
openLink: typeof actions.openLink,
openElementInInspector: typeof actions.openElementInInspectorCommand
openElementInInspector: typeof actions.openElementInInspectorCommand,
toggleMapScopes: typeof actions.toggleMapScopes
};
type State = {
@ -97,16 +105,46 @@ class Scopes extends PureComponent<Props, State> {
}
}
render() {
onToggleMapScopes = () => {
this.props.toggleMapScopes();
};
renderMapScopes() {
const { selectedFrame, shouldMapScopes } = this.props;
if (!features.mapScopes || isGeneratedId(selectedFrame.location.sourceId)) {
return null;
}
return (
<div className="toggle-map-scopes" onClick={this.onToggleMapScopes}>
<input
type="checkbox"
checked={shouldMapScopes ? "checked" : ""}
onChange={e => e.stopPropagation() && this.onToggleMapScopes()}
/>
<div className="toggle-map-scopes-label">
<span>{L10N.getStr("scopes.mapScopes")}</span>
</div>
<a className="mdn" target="_blank" href={mdnLink}>
<AccessibleImage className="shortcuts" />
</a>
</div>
);
}
renderScopesList() {
const {
isPaused,
isLoading,
openLink,
openElementInInspector
openElementInInspector,
shouldMapScopes
} = this.props;
const { originalScopes, generatedScopes, showOriginal } = this.state;
const scopes = (showOriginal && originalScopes) || generatedScopes;
const scopes =
(showOriginal && shouldMapScopes && originalScopes) || generatedScopes;
if (scopes && !isLoading) {
return (
@ -122,7 +160,7 @@ class Scopes extends PureComponent<Props, State> {
onDOMNodeClick={grip => openElementInInspector(grip)}
onInspectIconClick={grip => openElementInInspector(grip)}
/>
{originalScopes ? (
{originalScopes && shouldMapScopes ? (
<div className="scope-type-toggle">
<button
onClick={e => {
@ -155,6 +193,15 @@ class Scopes extends PureComponent<Props, State> {
</div>
);
}
render() {
return (
<div className="scopes-content">
{this.renderMapScopes()}
{this.renderScopesList()}
</div>
);
}
}
const mapStateToProps = state => {
@ -180,6 +227,7 @@ const mapStateToProps = state => {
return {
selectedFrame,
shouldMapScopes: getMapScopes(state),
isPaused: getIsPaused(state),
isLoading: generatedPending || originalPending,
why: getPauseReason(state),
@ -192,6 +240,7 @@ export default connect(
mapStateToProps,
{
openLink: actions.openLink,
openElementInInspector: actions.openElementInInspectorCommand
openElementInInspector: actions.openElementInInspectorCommand,
toggleMapScopes: actions.toggleMapScopes
}
)(Scopes);

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

@ -13,7 +13,7 @@
import { createSelector } from "reselect";
import { isGeneratedId } from "devtools-source-map";
import { prefs } from "../utils/prefs";
import { getSelectedSource } from "./sources";
import { getSelectedSourceId } from "./sources";
import type { OriginalScope } from "../utils/pause/mapScopes";
import type { Action } from "../actions/types";
@ -78,14 +78,16 @@ export type PauseState = {
currentThread: string,
canRewind: boolean,
threads: { [string]: ThreadPauseState },
skipPausing: boolean
skipPausing: boolean,
mapScopes: boolean
};
export const createPauseState = (): PauseState => ({
currentThread: "UnknownThread",
threads: {},
canRewind: false,
skipPausing: prefs.skipPausing
skipPausing: prefs.skipPausing,
mapScopes: prefs.mapScopes
});
const resumedPauseState = {
@ -306,6 +308,12 @@ function update(
return { ...state, skipPausing };
}
case "TOGGLE_MAP_SCOPES": {
const { mapScopes } = action;
prefs.mapScopes = mapScopes;
return { ...state, mapScopes };
}
}
return state;
@ -503,14 +511,10 @@ export function getFrameScope(
}
export function getSelectedScope(state: OuterState) {
const source = getSelectedSource(state);
const sourceId = getSelectedSourceId(state);
const frameId = getSelectedFrameId(state);
if (!source) {
return null;
}
const frameScope = getFrameScope(state, source.id, frameId);
const frameScope = getFrameScope(state, sourceId, frameId);
if (!frameScope) {
return null;
}
@ -518,6 +522,17 @@ export function getSelectedScope(state: OuterState) {
return frameScope.scope || null;
}
export function getSelectedOriginalScope(state: OuterState) {
const sourceId = getSelectedSourceId(state);
const frameId = getSelectedFrameId(state);
return getOriginalFrameScope(state, sourceId, frameId);
}
export function getSelectedGeneratedScope(state: OuterState) {
const frameId = getSelectedFrameId(state);
return getGeneratedFrameScope(state, frameId);
}
export function getSelectedScopeMappings(
state: OuterState
): {
@ -556,6 +571,10 @@ export function getSkipPausing(state: OuterState) {
return state.pause.skipPausing;
}
export function getMapScopes(state: OuterState) {
return state.pause.mapScopes;
}
// NOTE: currently only used for chrome
export function getChromeScopes(state: OuterState) {
const frame: ?ChromeFrame = (getSelectedFrame(state): any);

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

@ -539,6 +539,11 @@ export const getSelectedSource: Selector<?Source> = createSelector(
}
);
export function getSelectedSourceId(state: OuterState) {
const source = getSelectedSource((state: any));
return source && source.id;
}
export function getProjectDirectoryRoot(state: OuterState): string {
return state.sources.projectDirectoryRoot;
}

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

@ -42,6 +42,7 @@ if (isDevelopment()) {
pref("devtools.debugger.file-search-whole-word", false);
pref("devtools.debugger.file-search-regex-match", false);
pref("devtools.debugger.project-directory-root", "");
pref("devtools.debugger.map-scopes-enabled", false);
pref("devtools.debugger.prefs-schema-version", "1.0.1");
pref("devtools.debugger.skip-pausing", false);
pref("devtools.debugger.features.workers", true);
@ -97,7 +98,8 @@ export const prefs = new PrefsHelper("devtools", {
fileSearchRegexMatch: ["Bool", "debugger.file-search-regex-match"],
debuggerPrefsSchemaVersion: ["Char", "debugger.prefs-schema-version"],
projectDirectoryRoot: ["Char", "debugger.project-directory-root", ""],
skipPausing: ["Bool", "debugger.skip-pausing"]
skipPausing: ["Bool", "debugger.skip-pausing"],
mapScopes: ["Bool", "debugger.map-scopes-enabled"]
});
export const features = new PrefsHelper("devtools.debugger.features", {

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

@ -515,6 +515,7 @@ function clearDebuggerPreferences() {
Services.prefs.clearUserPref("devtools.debugger.call-stack-visible");
Services.prefs.clearUserPref("devtools.debugger.scopes-visible");
Services.prefs.clearUserPref("devtools.debugger.skip-pausing");
pushPref("devtools.debugger.map-scopes-enabled", true);
}
/**

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

@ -713,6 +713,9 @@ sources.header=Sources
# LOCALIZATION NOTE (outline.header): Outline left sidebar header
outline.header=Outline
# LOCALIZATION NOTE (scopes.mapScopes): Label for toggling scope mappings
scopes.mapScopes=Map Scopes
# LOCALIZATION NOTE (outline.placeholder): Placeholder text for the filter input
# element
outline.placeholder=Filter functions

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

@ -52,6 +52,7 @@ pref("devtools.debugger.file-search-regex-match", false);
pref("devtools.debugger.project-directory-root", "");
pref("devtools.debugger.skip-pausing", false);
pref("devtools.debugger.logging", false);
pref("devtools.debugger.map-scopes-enabled", false);
pref("devtools.debugger.features.wasm", true);
pref("devtools.debugger.features.shortcuts", true);