diff options
Diffstat (limited to 'devtools/client/debugger/src')
112 files changed, 1213 insertions, 788 deletions
diff --git a/devtools/client/debugger/src/.eslintrc.js b/devtools/client/debugger/src/.eslintrc.js index b71126767c..ec6d77b504 100644 --- a/devtools/client/debugger/src/.eslintrc.js +++ b/devtools/client/debugger/src/.eslintrc.js @@ -108,9 +108,6 @@ module.exports = { "global-strict": 0, // Only useful in a node environment. "handle-callback-err": 0, - // Don't enforce the maximum depth that blocks can be nested. The complexity - // rule is a better rule to check this. - "max-depth": 0, // Maximum depth callbacks can be nested. "max-nested-callbacks": [2, 4], // Don't limit the number of parameters that can be used in a function. @@ -133,10 +130,6 @@ module.exports = { "no-catch-shadow": 2, // Disallow assignment in conditional expressions. "no-cond-assign": 2, - // Allow using the console API. - "no-console": 0, - // Allow using constant expressions in conditions like while (true) - "no-constant-condition": 0, // Allow use of the continue statement. "no-continue": 0, // Disallow control characters in regular expressions. @@ -267,10 +260,6 @@ module.exports = { "no-var": 0, // Allow using TODO/FIXME comments. "no-warning-comments": 0, - // Dont require method and property shorthand syntax for object literals. - // We use this in the code a lot, but not consistently, and this seems more - // like something to check at code review time. - "object-shorthand": 0, // Allow more than one variable declaration per function. "one-var": 0, // Require use of the second argument for parseInt(). diff --git a/devtools/client/debugger/src/actions/ast/setInScopeLines.js b/devtools/client/debugger/src/actions/ast/setInScopeLines.js index 72bd33b59f..5a76ab7f65 100644 --- a/devtools/client/debugger/src/actions/ast/setInScopeLines.js +++ b/devtools/client/debugger/src/actions/ast/setInScopeLines.js @@ -27,11 +27,7 @@ function getOutOfScopeLines(outOfScopeLocations) { return uniqueLines; } -async function getInScopeLines( - location, - sourceTextContent, - { dispatch, getState, parserWorker } -) { +async function getInScopeLines(location, sourceTextContent, { parserWorker }) { let locations = null; if (location.line && parserWorker.isLocationSupported(location)) { locations = await parserWorker.findOutOfScopeLocations(location); diff --git a/devtools/client/debugger/src/actions/breakpoints/index.js b/devtools/client/debugger/src/actions/breakpoints/index.js index 2125ec9ec7..94e9028a1b 100644 --- a/devtools/client/debugger/src/actions/breakpoints/index.js +++ b/devtools/client/debugger/src/actions/breakpoints/index.js @@ -44,7 +44,7 @@ export function addHiddenBreakpoint(location) { * @static */ export function disableBreakpointsInSource(source) { - return async ({ dispatch, getState, client }) => { + return async ({ dispatch, getState }) => { const breakpoints = getBreakpointsForSource(getState(), source); for (const breakpoint of breakpoints) { if (!breakpoint.disabled) { @@ -61,7 +61,7 @@ export function disableBreakpointsInSource(source) { * @static */ export function enableBreakpointsInSource(source) { - return async ({ dispatch, getState, client }) => { + return async ({ dispatch, getState }) => { const breakpoints = getBreakpointsForSource(getState(), source); for (const breakpoint of breakpoints) { if (breakpoint.disabled) { @@ -78,7 +78,7 @@ export function enableBreakpointsInSource(source) { * @static */ export function toggleAllBreakpoints(shouldDisableBreakpoints) { - return async ({ dispatch, getState, client }) => { + return async ({ dispatch, getState }) => { const breakpoints = getBreakpointsList(getState()); for (const breakpoint of breakpoints) { @@ -149,7 +149,7 @@ export function removeBreakpoints(breakpoints) { * @static */ export function removeBreakpointsInSource(source) { - return async ({ dispatch, getState, client }) => { + return async ({ dispatch, getState }) => { const breakpoints = getBreakpointsForSource(getState(), source); for (const breakpoint of breakpoints) { dispatch(removeBreakpoint(breakpoint)); @@ -271,7 +271,7 @@ export function enableBreakpointsAtLine(source, line) { } export function toggleDisabledBreakpoint(breakpoint) { - return ({ dispatch, getState }) => { + return ({ dispatch }) => { if (!breakpoint.disabled) { return dispatch(disableBreakpoint(breakpoint)); } @@ -356,7 +356,7 @@ export function togglePauseOnAny() { } export function setXHRBreakpoint(path, method) { - return ({ dispatch, getState, client }) => { + return ({ dispatch, client }) => { const breakpoint = createXHRBreakpoint(path, method); return dispatch({ diff --git a/devtools/client/debugger/src/actions/breakpoints/syncBreakpoint.js b/devtools/client/debugger/src/actions/breakpoints/syncBreakpoint.js index b24912de58..aec56664d0 100644 --- a/devtools/client/debugger/src/actions/breakpoints/syncBreakpoint.js +++ b/devtools/client/debugger/src/actions/breakpoints/syncBreakpoint.js @@ -14,7 +14,7 @@ import { originalToGeneratedId } from "devtools/client/shared/source-map-loader/ import { getSource } from "../../selectors/index"; import { addBreakpoint, removeBreakpointAtGeneratedLocation } from "./modify"; -async function findBreakpointPosition({ getState, dispatch }, location) { +async function findBreakpointPosition({ dispatch }, location) { const positions = await dispatch(setBreakpointPositions(location)); const position = findPosition(positions, location); diff --git a/devtools/client/debugger/src/actions/breakpoints/tests/__snapshots__/breakpoints.spec.js.snap b/devtools/client/debugger/src/actions/breakpoints/tests/__snapshots__/breakpoints.spec.js.snap index e6abad25d5..69bc4a08b4 100644 --- a/devtools/client/debugger/src/actions/breakpoints/tests/__snapshots__/breakpoints.spec.js.snap +++ b/devtools/client/debugger/src/actions/breakpoints/tests/__snapshots__/breakpoints.spec.js.snap @@ -24,6 +24,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "a", + "shortName": "a", "url": "http://localhost:8000/examples/a", }, "sourceActor": null, @@ -48,6 +50,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "a", + "shortName": "a", "url": "http://localhost:8000/examples/a", }, "sourceActor": null, @@ -59,7 +63,6 @@ Array [ "thread": undefined, }, ], - "filename": "a", "source": Object { "displayURL": Object { "fileExtension": "", @@ -75,6 +78,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "a", + "shortName": "a", "url": "http://localhost:8000/examples/a", }, }, @@ -107,6 +112,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "a", + "shortName": "a", "url": "http://localhost:8000/examples/a", }, "sourceActor": null, @@ -131,6 +138,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "a", + "shortName": "a", "url": "http://localhost:8000/examples/a", }, "sourceActor": null, @@ -142,7 +151,6 @@ Array [ "thread": undefined, }, ], - "filename": "a", "source": Object { "displayURL": Object { "fileExtension": "", @@ -158,6 +166,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "a", + "shortName": "a", "url": "http://localhost:8000/examples/a", }, }, diff --git a/devtools/client/debugger/src/actions/context-menus/editor-breakpoint.js b/devtools/client/debugger/src/actions/context-menus/editor-breakpoint.js index 39ec2f1589..999912966b 100644 --- a/devtools/client/debugger/src/actions/context-menus/editor-breakpoint.js +++ b/devtools/client/debugger/src/actions/context-menus/editor-breakpoint.js @@ -85,7 +85,7 @@ export function showEditorCreateBreakpointContextMenu( location, lineText ) { - return async ({ dispatch, getState }) => { + return async ({ dispatch }) => { const items = createBreakpointItems(location, lineText, dispatch); showMenu(event, items); diff --git a/devtools/client/debugger/src/actions/context-menus/editor.js b/devtools/client/debugger/src/actions/context-menus/editor.js index 1125790a9b..1cad1e2131 100644 --- a/devtools/client/debugger/src/actions/context-menus/editor.js +++ b/devtools/client/debugger/src/actions/context-menus/editor.js @@ -8,7 +8,6 @@ import { copyToTheClipboard } from "../../utils/clipboard"; import { isPretty, getRawSourceURL, - getFilename, shouldBlackbox, findBlackBoxRange, } from "../../utils/source"; @@ -255,7 +254,7 @@ const blackBoxLinesMenuItem = ( editor, blackboxedRanges, isSourceOnIgnoreList, - clickedLine = null, + clickedLine, dispatch ) => { const { codeMirror } = editor; @@ -321,7 +320,7 @@ const downloadFileItem = (selectedSource, selectedContent) => ({ id: "node-menu-download-file", label: L10N.getStr("downloadFile.label"), accesskey: L10N.getStr("downloadFile.accesskey"), - click: () => downloadFile(selectedContent, getFilename(selectedSource)), + click: () => downloadFile(selectedContent, selectedSource.shortName), }); const inlinePreviewItem = dispatch => ({ diff --git a/devtools/client/debugger/src/actions/context-menus/frame.js b/devtools/client/debugger/src/actions/context-menus/frame.js index 1d287b1028..a517b55e07 100644 --- a/devtools/client/debugger/src/actions/context-menus/frame.js +++ b/devtools/client/debugger/src/actions/context-menus/frame.js @@ -26,7 +26,7 @@ function formatMenuElement(labelString, click, disabled = false) { }; } -function isValidRestartFrame(frame, callbacks) { +function isValidRestartFrame(frame) { // Any frame state than 'on-stack' is either dismissed by the server // or can potentially cause unexpected errors. // Global frame has frame.callee equal to null and can't be restarted. @@ -34,7 +34,7 @@ function isValidRestartFrame(frame, callbacks) { } function copyStackTrace() { - return async ({ dispatch, getState }) => { + return async ({ getState }) => { const frames = getCurrentThreadFrames(getState()); const shouldDisplayOriginalLocation = getShouldSelectOriginalLocation( getState() diff --git a/devtools/client/debugger/src/actions/expressions.js b/devtools/client/debugger/src/actions/expressions.js index 8ccb6013ba..383f191506 100644 --- a/devtools/client/debugger/src/actions/expressions.js +++ b/devtools/client/debugger/src/actions/expressions.js @@ -23,7 +23,7 @@ import { features } from "../utils/prefs"; * @param {string} input */ export function addExpression(input) { - return async ({ dispatch, getState, parserWorker }) => { + return async ({ dispatch, getState }) => { if (!input) { return null; } @@ -64,7 +64,7 @@ export function clearAutocomplete() { } export function updateExpression(input, expression) { - return async ({ getState, dispatch, parserWorker }) => { + return async ({ dispatch }) => { if (!input) { return; } diff --git a/devtools/client/debugger/src/actions/file-search.js b/devtools/client/debugger/src/actions/file-search.js index cc5794d7ab..fb8cfe8475 100644 --- a/devtools/client/debugger/src/actions/file-search.js +++ b/devtools/client/debugger/src/actions/file-search.js @@ -30,7 +30,7 @@ export function querySearchWorker(query, text, modifiers) { } export function searchContentsForHighlight(query, editor, line, ch) { - return async ({ getState, dispatch }) => { + return async ({ getState }) => { const modifiers = getSearchOptions(getState(), "file-search"); const sourceTextContent = getSelectedSourceTextContent(getState()); diff --git a/devtools/client/debugger/src/actions/navigation.js b/devtools/client/debugger/src/actions/navigation.js index 1b437837c2..839d67a31a 100644 --- a/devtools/client/debugger/src/actions/navigation.js +++ b/devtools/client/debugger/src/actions/navigation.js @@ -18,13 +18,7 @@ import { evaluateExpressionsForCurrentContext } from "../actions/expressions"; * @static */ export function willNavigate(event) { - return async function ({ - dispatch, - getState, - client, - sourceMapLoader, - parserWorker, - }) { + return async function ({ dispatch, getState, sourceMapLoader }) { sourceQueue.clear(); sourceMapLoader.clearSourceMaps(); clearWasmStates(); @@ -42,7 +36,7 @@ export function willNavigate(event) { * @static */ export function navigated() { - return async function ({ getState, dispatch, panel }) { + return async function ({ dispatch, panel }) { try { // Update the watched expressions once the page is fully loaded await dispatch(evaluateExpressionsForCurrentContext()); diff --git a/devtools/client/debugger/src/actions/pause/commands.js b/devtools/client/debugger/src/actions/pause/commands.js index 0bb371bf6e..1623add274 100644 --- a/devtools/client/debugger/src/actions/pause/commands.js +++ b/devtools/client/debugger/src/actions/pause/commands.js @@ -17,7 +17,7 @@ import { recordEvent } from "../../utils/telemetry"; import { validateFrame } from "../../utils/context"; export function selectThread(thread) { - return async ({ dispatch, getState, client }) => { + return async ({ dispatch, getState }) => { if (getCurrentThread(getState()) === thread) { return; } diff --git a/devtools/client/debugger/src/actions/pause/expandScopes.js b/devtools/client/debugger/src/actions/pause/expandScopes.js index af95f16fea..1f7b7caac1 100644 --- a/devtools/client/debugger/src/actions/pause/expandScopes.js +++ b/devtools/client/debugger/src/actions/pause/expandScopes.js @@ -5,7 +5,7 @@ import { getScopeItemPath } from "../../utils/pause/scopes"; export function setExpandedScope(selectedFrame, item, expanded) { - return function ({ dispatch, getState }) { + return function ({ dispatch }) { return dispatch({ type: "SET_EXPANDED_SCOPE", selectedFrame, diff --git a/devtools/client/debugger/src/actions/pause/pauseOnDebuggerStatement.js b/devtools/client/debugger/src/actions/pause/pauseOnDebuggerStatement.js index 7b2b1d70cb..7d82fd44a8 100644 --- a/devtools/client/debugger/src/actions/pause/pauseOnDebuggerStatement.js +++ b/devtools/client/debugger/src/actions/pause/pauseOnDebuggerStatement.js @@ -5,7 +5,7 @@ import { PROMISE } from "../utils/middleware/promise"; export function pauseOnDebuggerStatement(shouldPauseOnDebuggerStatement) { - return ({ dispatch, getState, client }) => { + return ({ dispatch, client }) => { return dispatch({ type: "PAUSE_ON_DEBUGGER_STATEMENT", shouldPauseOnDebuggerStatement, diff --git a/devtools/client/debugger/src/actions/pause/pauseOnExceptions.js b/devtools/client/debugger/src/actions/pause/pauseOnExceptions.js index e7c04ded61..fe2f3e882a 100644 --- a/devtools/client/debugger/src/actions/pause/pauseOnExceptions.js +++ b/devtools/client/debugger/src/actions/pause/pauseOnExceptions.js @@ -14,7 +14,7 @@ export function pauseOnExceptions( shouldPauseOnExceptions, shouldPauseOnCaughtExceptions ) { - return ({ dispatch, getState, client }) => { + return ({ dispatch, client }) => { recordEvent("pause_on_exceptions", { exceptions: shouldPauseOnExceptions, // There's no "n" in the key below (#1463117) diff --git a/devtools/client/debugger/src/actions/pause/resumed.js b/devtools/client/debugger/src/actions/pause/resumed.js index 47d55f84ca..2095bacc3b 100644 --- a/devtools/client/debugger/src/actions/pause/resumed.js +++ b/devtools/client/debugger/src/actions/pause/resumed.js @@ -14,7 +14,7 @@ import { inDebuggerEval } from "../../utils/pause/index"; * Debugger has just resumed. */ export function resumed(thread) { - return async ({ dispatch, client, getState }) => { + return async ({ dispatch, getState }) => { const why = getPauseReason(getState(), thread); const wasPausedInEval = inDebuggerEval(why); const wasStepping = isStepping(getState(), thread); diff --git a/devtools/client/debugger/src/actions/pause/tests/pause.spec.js b/devtools/client/debugger/src/actions/pause/tests/pause.spec.js index f8bd87375a..6c69ac4661 100644 --- a/devtools/client/debugger/src/actions/pause/tests/pause.spec.js +++ b/devtools/client/debugger/src/actions/pause/tests/pause.spec.js @@ -25,7 +25,7 @@ const mockCommandClient = { getFrames: async () => [], setBreakpoint: () => new Promise(_resolve => {}), sourceContents: ({ source }) => { - return new Promise((resolve, reject) => { + return new Promise(resolve => { switch (source) { case "foo1": return resolve({ @@ -184,7 +184,7 @@ describe("pause", () => { it("maps frame to original frames", async () => { const sourceMapLoaderMock = { - getOriginalStackFrames: loc => Promise.resolve(originStackFrames), + getOriginalStackFrames: () => Promise.resolve(originStackFrames), getOriginalLocation: () => Promise.resolve(debuggerToSourceMapLocation(originalLocation)), getOriginalLocations: async items => diff --git a/devtools/client/debugger/src/actions/preview.js b/devtools/client/debugger/src/actions/preview.js index c3bc8dbffd..3b3637e2c0 100644 --- a/devtools/client/debugger/src/actions/preview.js +++ b/devtools/client/debugger/src/actions/preview.js @@ -128,7 +128,7 @@ export function getPreview(target, tokenPos, codeMirror) { } export function getExceptionPreview(target, tokenPos, codeMirror) { - return async ({ dispatch, getState, parserWorker }) => { + return async ({ getState, parserWorker }) => { const match = await findExpressionMatch( getState(), parserWorker, diff --git a/devtools/client/debugger/src/actions/sources/loadSourceText.js b/devtools/client/debugger/src/actions/sources/loadSourceText.js index d3bbd53871..b523b1984a 100644 --- a/devtools/client/debugger/src/actions/sources/loadSourceText.js +++ b/devtools/client/debugger/src/actions/sources/loadSourceText.js @@ -43,7 +43,7 @@ async function loadGeneratedSource(sourceActor, { client }) { async function loadOriginalSource( source, - { getState, client, sourceMapLoader, prettyPrintWorker } + { getState, sourceMapLoader, prettyPrintWorker } ) { if (isPretty(source)) { const generatedSource = getGeneratedSource(getState(), source); diff --git a/devtools/client/debugger/src/actions/sources/newSources.js b/devtools/client/debugger/src/actions/sources/newSources.js index 4d9c2cd5f7..44e8595c42 100644 --- a/devtools/client/debugger/src/actions/sources/newSources.js +++ b/devtools/client/debugger/src/actions/sources/newSources.js @@ -36,30 +36,22 @@ import { prefs } from "../../utils/prefs"; import sourceQueue from "../../utils/source-queue"; import { validateSourceActor, ContextError } from "../../utils/context"; -function loadSourceMaps(sources) { +function loadSourceMapsForSourceActors(sourceActors) { return async function ({ dispatch }) { try { - const sourceList = await Promise.all( - sources.map(async sourceActor => { - const originalSourcesInfo = await dispatch( - loadSourceMap(sourceActor) - ); - originalSourcesInfo.forEach( - sourcesInfo => (sourcesInfo.sourceActor = sourceActor) - ); - sourceQueue.queueOriginalSources(originalSourcesInfo); - return originalSourcesInfo; - }) + await Promise.all( + sourceActors.map(sourceActor => dispatch(loadSourceMap(sourceActor))) ); - - await sourceQueue.flush(); - return sourceList.flat(); } catch (error) { + // This may throw a context error if we navigated while processing the source maps if (!(error instanceof ContextError)) { throw error; } } - return []; + + // Once all the source maps, of all the bulk of new source actors are processed, + // flush the SourceQueue. This help aggregate all the original sources in one action. + await sourceQueue.flush(); }; } @@ -70,7 +62,7 @@ function loadSourceMaps(sources) { function loadSourceMap(sourceActor) { return async function ({ dispatch, getState, sourceMapLoader, panel }) { if (!prefs.clientSourceMapsEnabled || !sourceActor.sourceMapURL) { - return []; + return; } let sources, ignoreListUrls, resolvedSourceMapURL, exception; @@ -135,12 +127,20 @@ function loadSourceMap(sourceActor) { type: "CLEAR_SOURCE_ACTOR_MAP_URL", sourceActor, }); - return []; + return; } // Before dispatching this action, ensure that the related sourceActor is still registered validateSourceActor(getState(), sourceActor); - return sources; + + for (const originalSource of sources) { + // The Source Map worker doesn't set the `sourceActor` attribute, + // which is handy to know what is the related bundle. + originalSource.sourceActor = sourceActor; + } + + // Register all the new reported original sources in the queue to be flushed once all new bundles are processed. + sourceQueue.queueOriginalSources(sources); }; } @@ -294,7 +294,7 @@ export function newGeneratedSource(sourceInfo) { } export function newGeneratedSources(sourceResources) { - return async ({ dispatch, getState, client }) => { + return async ({ dispatch, getState }) => { if (!sourceResources.length) { return []; } @@ -341,7 +341,7 @@ export function newGeneratedSources(sourceResources) { await dispatch(checkNewSources(newSources)); (async () => { - await dispatch(loadSourceMaps(newSourceActors)); + await dispatch(loadSourceMapsForSourceActors(newSourceActors)); // We would like to sync breakpoints after we are done // loading source maps as sometimes generated and original @@ -370,7 +370,7 @@ export function newGeneratedSources(sourceResources) { } function checkNewSources(sources) { - return async ({ dispatch, getState }) => { + return async ({ dispatch }) => { for (const source of sources) { dispatch(checkSelectedSource(source.id)); } diff --git a/devtools/client/debugger/src/actions/sources/prettyPrint.js b/devtools/client/debugger/src/actions/sources/prettyPrint.js index 6a12a34240..d1e46ac949 100644 --- a/devtools/client/debugger/src/actions/sources/prettyPrint.js +++ b/devtools/client/debugger/src/actions/sources/prettyPrint.js @@ -224,7 +224,7 @@ async function prettyPrintHtmlFile({ } function createPrettySource(source, sourceActor) { - return async ({ dispatch, sourceMapLoader, getState }) => { + return async ({ dispatch }) => { const url = getPrettyOriginalSourceURL(source); const id = generatedToOriginalId(source.id, url); const prettySource = createPrettyPrintOriginalSource(id, url); @@ -336,7 +336,7 @@ const memoizedPrettyPrintSource = memoizeableAction("setSymbols", { }); export function prettyPrintAndSelectSource(source) { - return async ({ dispatch, sourceMapLoader, getState }) => { + return async ({ dispatch }) => { const prettySource = await dispatch(memoizedPrettyPrintSource(source)); // Select the pretty/original source based on the location we may diff --git a/devtools/client/debugger/src/actions/sources/select.js b/devtools/client/debugger/src/actions/sources/select.js index 63200a398a..f25267374b 100644 --- a/devtools/client/debugger/src/actions/sources/select.js +++ b/devtools/client/debugger/src/actions/sources/select.js @@ -63,6 +63,11 @@ export const clearSelectedLocation = () => ({ type: "CLEAR_SELECTED_LOCATION", }); +export const setDefaultSelectedLocation = shouldSelectOriginalLocation => ({ + type: "SET_DEFAULT_SELECTED_LOCATION", + shouldSelectOriginalLocation, +}); + /** * Deterministically select a source that has a given URL. This will * work regardless of the connection status or if the source exists @@ -105,6 +110,76 @@ export function selectSource(source, sourceActor) { } /** + * Helper for `selectLocation`. + * Based on `keepContext` argument passed to `selectLocation`, + * this will automatically select the related mapped source (original or generated). + * + * @param {Object} location + * The location to select. + * @param {Boolean} keepContext + * If true, will try to select a mapped source. + * @param {Object} thunkArgs + * @return {Object} + * Object with two attributes: + * - `shouldSelectOriginalLocation`, to know if we should keep trying to select the original location + * - `newLocation`, for the final location to select + */ +async function mayBeSelectMappedSource(location, keepContext, thunkArgs) { + const { getState, dispatch } = thunkArgs; + // Preserve the current source map context (original / generated) + // when navigating to a new location. + // i.e. if keepContext isn't manually overriden to false, + // we will convert the source we want to select to either + // original/generated in order to match the currently selected one. + // If the currently selected source is original, we will + // automatically map `location` to refer to the original source, + // even if that used to refer only to the generated source. + let shouldSelectOriginalLocation = getShouldSelectOriginalLocation( + getState() + ); + if (keepContext) { + // Pretty print source may not be registered yet and getRelatedMapLocation may not return it. + // Wait for the pretty print source to be fully processed. + if ( + !location.source.isOriginal && + shouldSelectOriginalLocation && + hasPrettyTab(getState(), location.source) + ) { + // Note that prettyPrintAndSelectSource has already been called a bit before when this generated source has been added + // but it is a slow operation and is most likely not resolved yet. + // prettyPrintAndSelectSource uses memoization to avoid doing the operation more than once, while waiting from both callsites. + await dispatch(prettyPrintAndSelectSource(location.source)); + } + if (shouldSelectOriginalLocation != location.source.isOriginal) { + // Only try to map if the source is mapped. i.e. is original source or a bundle with a valid source map comment + if ( + location.source.isOriginal || + isSourceActorWithSourceMap(getState(), location.sourceActor.id) + ) { + // getRelatedMapLocation will convert to the related generated/original location. + // i.e if the original location is passed, the related generated location will be returned and vice versa. + location = await getRelatedMapLocation(location, thunkArgs); + } + // Note that getRelatedMapLocation may return the exact same location. + // For example, if the source-map is half broken, it may return a generated location + // while we were selecting original locations. So we may be seeing bundles intermittently + // when stepping through broken source maps. And we will see original sources when stepping + // through functional original sources. + } + } else if ( + location.source.isOriginal || + isSourceActorWithSourceMap(getState(), location.sourceActor.id) + ) { + // Only update this setting if the source is mapped. i.e. don't update if we select a regular source. + // The source is mapped when it is either: + // - an original source, + // - a bundle with a source map comment referencing a source map URL. + shouldSelectOriginalLocation = location.source.isOriginal; + } + return { shouldSelectOriginalLocation, newLocation: location }; +} + +/** * Select a new location. * This will automatically select the source in the source tree (if visible) * and open the source (a new tab and the source editor) @@ -144,47 +219,28 @@ export function selectLocation( return; } - // Preserve the current source map context (original / generated) - // when navigating to a new location. - // i.e. if keepContext isn't manually overriden to false, - // we will convert the source we want to select to either - // original/generated in order to match the currently selected one. - // If the currently selected source is original, we will - // automatically map `location` to refer to the original source, - // even if that used to refer only to the generated source. - let shouldSelectOriginalLocation = getShouldSelectOriginalLocation( - getState() - ); - if (keepContext) { - // Pretty print source may not be registered yet and getRelatedMapLocation may not return it. - // Wait for the pretty print source to be fully processed. - if ( - !location.source.isOriginal && - shouldSelectOriginalLocation && - hasPrettyTab(getState(), location.source) - ) { - // Note that prettyPrintAndSelectSource has already been called a bit before when this generated source has been added - // but it is a slow operation and is most likely not resolved yet. - // prettyPrintAndSelectSource uses memoization to avoid doing the operation more than once, while waiting from both callsites. - await dispatch(prettyPrintAndSelectSource(location.source)); - } - if (shouldSelectOriginalLocation != location.source.isOriginal) { - // getRelatedMapLocation will convert to the related generated/original location. - // i.e if the original location is passed, the related generated location will be returned and vice versa. - location = await getRelatedMapLocation(location, thunkArgs); - // Note that getRelatedMapLocation may return the exact same location. - // For example, if the source-map is half broken, it may return a generated location - // while we were selecting original locations. So we may be seeing bundles intermittently - // when stepping through broken source maps. And we will see original sources when stepping - // through functional original sources. + let sourceActor = location.sourceActor; + if (!sourceActor) { + sourceActor = getFirstSourceActorForGeneratedSource( + getState(), + source.id + ); + location = createLocation({ ...location, sourceActor }); + } - source = location.source; - } - } else { - shouldSelectOriginalLocation = location.source.isOriginal; + const lastSelectedLocation = getSelectedLocation(getState()); + const { shouldSelectOriginalLocation, newLocation } = + await mayBeSelectMappedSource(location, keepContext, thunkArgs); + + // Ignore the request if another location was selected while we were waiting for mayBeSelectMappedSource async completion + if (getSelectedLocation(getState()) != lastSelectedLocation) { + return; } - let sourceActor = location.sourceActor; + // Update all local variables after mapping + location = newLocation; + source = location.source; + sourceActor = location.sourceActor; if (!sourceActor) { sourceActor = getFirstSourceActorForGeneratedSource( getState(), @@ -351,11 +407,16 @@ export function jumpToMappedLocation(location) { // Map to either an original or a generated source location const pairedLocation = await getRelatedMapLocation(location, thunkArgs); + // If we are on a non-mapped source, this will return the same location + // so ignore the request. + if (pairedLocation == location) { + return null; + } + return dispatch(selectSpecificLocation(pairedLocation)); }; } -// This is only used by tests export function jumpToMappedSelectedLocation() { return async function ({ dispatch, getState }) { const location = getSelectedLocation(getState()); diff --git a/devtools/client/debugger/src/actions/sources/symbols.js b/devtools/client/debugger/src/actions/sources/symbols.js index c7b9132c32..e33c3e1036 100644 --- a/devtools/client/debugger/src/actions/sources/symbols.js +++ b/devtools/client/debugger/src/actions/sources/symbols.js @@ -10,7 +10,7 @@ import { loadSourceText } from "./loadSourceText"; import { memoizeableAction } from "../../utils/memoizableAction"; import { fulfilled } from "../../utils/async-value"; -async function doSetSymbols(location, { dispatch, getState, parserWorker }) { +async function doSetSymbols(location, { dispatch, parserWorker }) { await dispatch(loadSourceText(location.source, location.sourceActor)); await dispatch({ diff --git a/devtools/client/debugger/src/actions/sources/tests/newSources.spec.js b/devtools/client/debugger/src/actions/sources/tests/newSources.spec.js index cef9eca31e..19457a4bf5 100644 --- a/devtools/client/debugger/src/actions/sources/tests/newSources.spec.js +++ b/devtools/client/debugger/src/actions/sources/tests/newSources.spec.js @@ -7,10 +7,9 @@ import { selectors, createStore, makeSource, - makeSourceURL, makeOriginalSource, } from "../../../utils/test-head"; -const { getSource, getSourceCount, getSelectedSource } = selectors; +const { getSource, getSourceCount } = selectors; import { mockCommandClient } from "../../tests/helpers/mockCommandClient"; @@ -49,20 +48,6 @@ describe("sources - new sources", () => { expect(getSourceCount(getState())).toEqual(1); }); - it("should automatically select a pending source", async () => { - const { dispatch, getState } = createStore(mockCommandClient); - const baseSourceURL = makeSourceURL("base.js"); - await dispatch(actions.selectSourceURL(baseSourceURL)); - - expect(getSelectedSource(getState())).toBe(undefined); - const baseSource = await dispatch( - actions.newGeneratedSource(makeSource("base.js")) - ); - - const selected = getSelectedSource(getState()); - expect(selected && selected.url).toBe(baseSource.url); - }); - // eslint-disable-next-line it("should not attempt to fetch original sources if it's missing a source map url", async () => { const loadSourceMap = jest.fn(); diff --git a/devtools/client/debugger/src/actions/sources/tests/select.spec.js b/devtools/client/debugger/src/actions/sources/tests/select.spec.js index 5f4feba6c0..4cf0c58c94 100644 --- a/devtools/client/debugger/src/actions/sources/tests/select.spec.js +++ b/devtools/client/debugger/src/actions/sources/tests/select.spec.js @@ -8,7 +8,6 @@ import { createStore, createSourceObject, makeSource, - makeSourceURL, waitForState, makeOriginalSource, } from "../../../utils/test-head"; @@ -23,7 +22,7 @@ import { createLocation } from "../../../utils/location"; import { mockCommandClient } from "../../tests/helpers/mockCommandClient"; -process.on("unhandledRejection", (reason, p) => {}); +process.on("unhandledRejection", () => {}); function initialLocation(sourceId) { return createLocation({ source: createSourceObject(sourceId), line: 1 }); @@ -176,20 +175,4 @@ describe("sources", () => { const selected = getSelectedLocation(getState()); expect(selected && selected.line).toBe(1); }); - - describe("selectSourceURL", () => { - it("should automatically select a pending source", async () => { - const { dispatch, getState } = createStore(mockCommandClient); - const baseSourceURL = makeSourceURL("base.js"); - await dispatch(actions.selectSourceURL(baseSourceURL)); - - expect(getSelectedSource(getState())).toBe(undefined); - const baseSource = await dispatch( - actions.newGeneratedSource(makeSource("base.js")) - ); - - const selected = getSelectedSource(getState()); - expect(selected && selected.url).toBe(baseSource.url); - }); - }); }); diff --git a/devtools/client/debugger/src/actions/tests/expressions.spec.js b/devtools/client/debugger/src/actions/tests/expressions.spec.js index c69276fa40..093f99e228 100644 --- a/devtools/client/debugger/src/actions/tests/expressions.spec.js +++ b/devtools/client/debugger/src/actions/tests/expressions.spec.js @@ -6,7 +6,7 @@ import { actions, selectors, createStore } from "../../utils/test-head"; const mockThreadFront = { evaluate: (script, { frameId }) => - new Promise((resolve, reject) => { + new Promise(resolve => { if (!frameId) { resolve("bla"); } else { @@ -16,8 +16,8 @@ const mockThreadFront = { evaluateExpressions: (inputs, { frameId }) => Promise.all( inputs.map( - input => - new Promise((resolve, reject) => { + () => + new Promise(resolve => { if (!frameId) { resolve("bla"); } else { diff --git a/devtools/client/debugger/src/actions/tests/helpers/mockCommandClient.js b/devtools/client/debugger/src/actions/tests/helpers/mockCommandClient.js index 38dd55c274..2e0333fc99 100644 --- a/devtools/client/debugger/src/actions/tests/helpers/mockCommandClient.js +++ b/devtools/client/debugger/src/actions/tests/helpers/mockCommandClient.js @@ -29,7 +29,7 @@ const sources = [ ]; export const mockCommandClient = { - sourceContents: function ({ source }) { + sourceContents({ source }) { return new Promise((resolve, reject) => { if (sources.includes(source)) { resolve(createSource(source)); diff --git a/devtools/client/debugger/src/actions/toolbox.js b/devtools/client/debugger/src/actions/toolbox.js index a343c92863..4c88ec6d24 100644 --- a/devtools/client/debugger/src/actions/toolbox.js +++ b/devtools/client/debugger/src/actions/toolbox.js @@ -12,6 +12,12 @@ export function openLink(url) { }; } +export function openSourceMap(url, line, column) { + return async function ({ panel }) { + return panel.toolbox.viewSource(url, line, column); + }; +} + export function evaluateInConsole(inputString) { return async ({ panel }) => { return panel.openConsoleAndEvaluate(inputString); @@ -24,7 +30,7 @@ export function openElementInInspectorCommand(grip) { }; } -export function openInspector(grip) { +export function openInspector() { return async ({ panel }) => { return panel.openInspector(); }; diff --git a/devtools/client/debugger/src/actions/ui.js b/devtools/client/debugger/src/actions/ui.js index 2424c658b8..8d4d62307a 100644 --- a/devtools/client/debugger/src/actions/ui.js +++ b/devtools/client/debugger/src/actions/ui.js @@ -16,7 +16,7 @@ import { selectSource } from "../actions/sources/select"; import { getEditor, getLocationsInViewport, - updateDocuments, + updateEditorLineWrapping, } from "../utils/editor/index"; import { blackboxSourceActorsForSource } from "./sources/blackbox"; import { toggleBreakpoints } from "./breakpoints/index"; @@ -66,7 +66,7 @@ export function setActiveSearch(activeSearch) { } export function toggleFrameworkGrouping(toggleValue) { - return ({ dispatch, getState }) => { + return ({ dispatch }) => { dispatch({ type: "TOGGLE_FRAMEWORK_GROUPING", value: toggleValue, @@ -75,7 +75,7 @@ export function toggleFrameworkGrouping(toggleValue) { } export function toggleInlinePreview(toggleValue) { - return ({ dispatch, getState }) => { + return ({ dispatch }) => { dispatch({ type: "TOGGLE_INLINE_PREVIEW", value: toggleValue, @@ -84,8 +84,8 @@ export function toggleInlinePreview(toggleValue) { } export function toggleEditorWrapping(toggleValue) { - return ({ dispatch, getState }) => { - updateDocuments(doc => doc.cm.setOption("lineWrapping", toggleValue)); + return ({ dispatch }) => { + updateEditorLineWrapping(toggleValue); dispatch({ type: "TOGGLE_EDITOR_WRAPPING", @@ -95,7 +95,7 @@ export function toggleEditorWrapping(toggleValue) { } export function toggleSourceMapsEnabled(toggleValue) { - return ({ dispatch, getState }) => { + return ({ dispatch }) => { dispatch({ type: "TOGGLE_SOURCE_MAPS_ENABLED", value: toggleValue, @@ -217,7 +217,7 @@ export function setSearchOptions(searchKey, searchOptions) { } export function copyToClipboard(location) { - return ({ dispatch, getState }) => { + return ({ getState }) => { const content = getSourceTextContent(getState(), location); if (content && isFulfilled(content) && content.value.type === "text") { copyToTheClipboard(content.value.value); @@ -257,7 +257,7 @@ export function toggleJavascriptTracingOnNextLoad() { } export function setHideOrShowIgnoredSources(shouldHide) { - return ({ dispatch, getState }) => { + return ({ dispatch }) => { dispatch({ type: "HIDE_IGNORED_SOURCES", shouldHide }); }; } diff --git a/devtools/client/debugger/src/actions/utils/middleware/context.js b/devtools/client/debugger/src/actions/utils/middleware/context.js index 00711a8c3f..350a90d66e 100644 --- a/devtools/client/debugger/src/actions/utils/middleware/context.js +++ b/devtools/client/debugger/src/actions/utils/middleware/context.js @@ -27,7 +27,7 @@ function validateActionContext(getState, action) { // Middleware which looks for actions that have a cx property and ignores // them if the context is no longer valid. -function context({ dispatch, getState }) { +function context({ getState }) { return next => action => { if ("cx" in action) { validateActionContext(getState, action); diff --git a/devtools/client/debugger/src/actions/utils/middleware/log.js b/devtools/client/debugger/src/actions/utils/middleware/log.js index b9592ce22c..d228669dd4 100644 --- a/devtools/client/debugger/src/actions/utils/middleware/log.js +++ b/devtools/client/debugger/src/actions/utils/middleware/log.js @@ -92,7 +92,7 @@ function serializeAction(action) { * A middleware that logs all actions coming through the system * to the console. */ -export function log({ dispatch, getState }) { +export function log() { return next => action => { const asyncMsg = !action.status ? "" : `[${action.status}]`; diff --git a/devtools/client/debugger/src/actions/utils/middleware/promise.js b/devtools/client/debugger/src/actions/utils/middleware/promise.js index 52054a1fcc..2b88bb8ca9 100644 --- a/devtools/client/debugger/src/actions/utils/middleware/promise.js +++ b/devtools/client/debugger/src/actions/utils/middleware/promise.js @@ -21,7 +21,7 @@ function seqIdGen() { return seqIdVal++; } -function promiseMiddleware({ dispatch, getState }) { +function promiseMiddleware({ dispatch }) { return next => action => { if (!(PROMISE in action)) { return next(action); @@ -42,7 +42,7 @@ function promiseMiddleware({ dispatch, getState }) { .finally(() => new Promise(resolve => executeSoon(resolve))) .then( value => { - dispatch({ ...action, status: "done", value: value }); + dispatch({ ...action, status: "done", value }); return value; }, error => { diff --git a/devtools/client/debugger/src/actions/utils/middleware/timing.js b/devtools/client/debugger/src/actions/utils/middleware/timing.js index d0bfa05977..8b6b7baf5e 100644 --- a/devtools/client/debugger/src/actions/utils/middleware/timing.js +++ b/devtools/client/debugger/src/actions/utils/middleware/timing.js @@ -9,13 +9,13 @@ const mark = window.performance?.mark ? window.performance.mark.bind(window.performance) - : a => {}; + : () => {}; const measure = window.performance?.measure ? window.performance.measure.bind(window.performance) - : (a, b, c) => {}; + : () => {}; -export function timing(store) { +export function timing() { return next => action => { mark(`${action.type}_start`); const result = next(action); diff --git a/devtools/client/debugger/src/client/firefox.js b/devtools/client/debugger/src/client/firefox.js index 6b76d6d175..8705bf3490 100644 --- a/devtools/client/debugger/src/client/firefox.js +++ b/devtools/client/debugger/src/client/firefox.js @@ -110,7 +110,7 @@ export function onDisconnect() { sourceQueue.clear(); } -async function onTargetAvailable({ targetFront, isTargetSwitching }) { +async function onTargetAvailable({ targetFront }) { const isBrowserToolbox = commands.descriptorFront.isBrowserProcessDescriptor; const isNonTopLevelFrameTarget = !targetFront.isTopLevel && diff --git a/devtools/client/debugger/src/client/firefox/commands.js b/devtools/client/debugger/src/client/firefox/commands.js index 5ef3ba27d0..3f8f62c8fb 100644 --- a/devtools/client/debugger/src/client/firefox/commands.js +++ b/devtools/client/debugger/src/client/firefox/commands.js @@ -115,7 +115,7 @@ async function toggleTracing() { return commands.tracerCommand.toggle(); } -function resume(thread, frameId) { +function resume(thread) { return lookupThreadFront(thread).resume(); } diff --git a/devtools/client/debugger/src/client/firefox/create.js b/devtools/client/debugger/src/client/firefox/create.js index 9c610a08dd..c78e0fb273 100644 --- a/devtools/client/debugger/src/client/firefox/create.js +++ b/devtools/client/debugger/src/client/firefox/create.js @@ -11,7 +11,11 @@ import { getSourceCount, } from "../../selectors/index"; import { features } from "../../utils/prefs"; -import { isUrlExtension } from "../../utils/source"; +import { + isUrlExtension, + getRawSourceURL, + getFormattedSourceId, +} from "../../utils/source"; import { createLocation } from "../../utils/location"; import { getDisplayURL } from "../../utils/sources-tree/getURL"; @@ -242,6 +246,7 @@ function createSourceObject({ isOriginal = false, isHTML = false, }) { + const displayURL = getDisplayURL(url, extensionName); return { // The ID, computed by: // * `makeSourceId` for generated, @@ -254,7 +259,23 @@ function createSourceObject({ // A (slightly tweaked) URL object to represent the source URL. // The URL object is augmented of a "group" attribute and some other standard attributes // are modified from their typical value. See getDisplayURL implementation. - displayURL: getDisplayURL(url, extensionName), + displayURL, + + // Short label for this source. + // + // * For inlined/eval sources without a URL, the name will refer to the internal source ID, + // * For pretty printed source, we take care to ignore the internal ":formatted" suffix used in the URL, + // * For index files, i.e. sources loaded without a filename, they will be named "(index)". + // * Special characters are decoded from the URL string. + // (most of this is done by getDisplayURL) + shortName: url + ? getRawSourceURL(displayURL.filename) + : getFormattedSourceId(id), + + // Same as short name, but with the query parameters. + longName: url + ? getRawSourceURL(displayURL.filename + displayURL.search) + : getFormattedSourceId(id), // Only set for generated sources that are WebExtension sources. // This is especially useful to display the extension name for content scripts diff --git a/devtools/client/debugger/src/components/App.css b/devtools/client/debugger/src/components/App.css index 796bf84574..64a899d047 100644 --- a/devtools/client/debugger/src/components/App.css +++ b/devtools/client/debugger/src/components/App.css @@ -79,6 +79,29 @@ button:hover { gap: 8px; grid-area: notification; display: flex; + /* center text within the notification */ + align-items: center; + + .info.icon { + align-self: normal; + } + + .close-button { + /* set a fixed height in order to avoid having it flexed to full height */ + height: 16px; + padding: 0; + /* put in top-right corner */ + margin-inline-start: auto; + align-self: normal; + + &::before { + display: block; + width: 16px; + height: 16px; + content: ""; + background-image: url("chrome://devtools/skin/images/close.svg"); + } + } } /* Utils */ diff --git a/devtools/client/debugger/src/components/App.js b/devtools/client/debugger/src/components/App.js index 40911e5167..1642a212ef 100644 --- a/devtools/client/debugger/src/components/App.js +++ b/devtools/client/debugger/src/components/App.js @@ -4,6 +4,7 @@ import React, { Component } from "devtools/client/shared/vendor/react"; import { + button, div, main, span, @@ -208,15 +209,23 @@ class App extends Component { } } + closeSourceMapError = () => { + this.setState({ hiddenSourceMapError: this.props.sourceMapError }); + }; + renderEditorNotificationBar() { - if (this.props.sourceMapError) { + if ( + this.props.sourceMapError && + this.state.hiddenSourceMapError != this.props.sourceMapError + ) { return div( { className: "editor-notification-footer", "aria-role": "status" }, span( { className: "info icon" }, React.createElement(AccessibleImage, { className: "sourcemap" }) ), - `Source Map Error: ${this.props.sourceMapError}` + `Source Map Error: ${this.props.sourceMapError}`, + button({ className: "close-button", onClick: this.closeSourceMapError }) ); } if (this.props.showOriginalVariableMappingWarning) { @@ -248,13 +257,13 @@ class App extends Component { className: "editor-container", }, React.createElement(EditorTabs, { - startPanelCollapsed: startPanelCollapsed, - endPanelCollapsed: endPanelCollapsed, - horizontal: horizontal, + startPanelCollapsed, + endPanelCollapsed, + horizontal, }), React.createElement(Editor, { - startPanelSize: startPanelSize, - endPanelSize: endPanelSize, + startPanelSize, + endPanelSize, }), !this.props.selectedLocation ? React.createElement(WelcomeBox, { @@ -313,7 +322,7 @@ class App extends Component { prefs.startPanelSize = num; this.triggerEditorPaneResize(); }, - startPanelCollapsed: startPanelCollapsed, + startPanelCollapsed, startPanel: React.createElement(PrimaryPanes, { horizontal, }), @@ -323,7 +332,7 @@ class App extends Component { endPanel: React.createElement(SecondaryPanes, { horizontal, }), - endPanelCollapsed: endPanelCollapsed, + endPanelCollapsed, }); }; diff --git a/devtools/client/debugger/src/components/Editor/ConditionalPanel.js b/devtools/client/debugger/src/components/Editor/ConditionalPanel.js index 8ff84c287a..97876f2f00 100644 --- a/devtools/client/debugger/src/components/Editor/ConditionalPanel.js +++ b/devtools/client/debugger/src/components/Editor/ConditionalPanel.js @@ -121,7 +121,7 @@ export class ConditionalPanel extends PureComponent { return this.clearConditionalPanel(); } - componentDidUpdate(prevProps) { + componentDidUpdate() { this.keepFocusOnInput(); } diff --git a/devtools/client/debugger/src/components/Editor/Footer.css b/devtools/client/debugger/src/components/Editor/Footer.css index 4a3272879b..f3382e94b5 100644 --- a/devtools/client/debugger/src/components/Editor/Footer.css +++ b/devtools/client/debugger/src/components/Editor/Footer.css @@ -67,6 +67,45 @@ opacity: 0.6; } +.devtools-button.debugger-source-map-button { + display: inline-flex; + align-items: center; + margin: 0; + --menuitem-icon-image: url("chrome://devtools/content/debugger/images/sourcemap.svg"); + + &.not-mapped { + --icon-color: var(--theme-icon-dimmed-color); + } + + &.original { + --icon-color: var(--theme-icon-checked-color); + --menuitem-icon-image: url("chrome://devtools/content/debugger/images/sourcemap-active.svg"); + } + + &.error { + --icon-color: var(--theme-icon-warning-color); + } + + &.disabled { + --icon-color: var(--theme-icon-dimmed-color); + --menuitem-icon-image: url("chrome://devtools/content/debugger/images/sourcemap-disabled.svg"); + } + + &.loading { + --menuitem-icon-image: url("chrome://devtools/content/debugger/images/loader.svg"); + } + + &::before { + /* override default style to have similar left and right margins */ + margin-inline-end: 3px; + color: var(--icon-color, currentColor); + } + + &.loading::before { + animation: spin 2s linear infinite; + } +} + .source-footer .mapped-source, .source-footer .cursor-position { color: var(--theme-body-color); diff --git a/devtools/client/debugger/src/components/Editor/Footer.js b/devtools/client/debugger/src/components/Editor/Footer.js index c4ff02caf4..69c7b52b68 100644 --- a/devtools/client/debugger/src/components/Editor/Footer.js +++ b/devtools/client/debugger/src/components/Editor/Footer.js @@ -7,6 +7,7 @@ import { div, button, span, + hr, } from "devtools/client/shared/vendor/react-dom-factories"; import PropTypes from "devtools/client/shared/vendor/react-prop-types"; import { connect } from "devtools/client/shared/vendor/react-redux"; @@ -23,14 +24,23 @@ import { isSourceOnSourceMapIgnoreList, isSourceMapIgnoreListEnabled, getSelectedMappedSource, + getSourceMapErrorForSourceActor, + areSourceMapsEnabled, + getShouldSelectOriginalLocation, + isSourceActorWithSourceMap, + getSourceMapResolvedURL, + isSelectedMappedSourceLoading, } from "../../selectors/index"; -import { isPretty, getFilename, shouldBlackbox } from "../../utils/source"; +import { isPretty, shouldBlackbox } from "../../utils/source"; import { PaneToggleButton } from "../shared/Button/index"; import AccessibleImage from "../shared/AccessibleImage"; const classnames = require("resource://devtools/client/shared/classnames.js"); +const MenuButton = require("resource://devtools/client/shared/components/menu/MenuButton.js"); +const MenuItem = require("resource://devtools/client/shared/components/menu/MenuItem.js"); +const MenuList = require("resource://devtools/client/shared/components/menu/MenuList.js"); class SourceFooter extends PureComponent { static get propTypes() { @@ -155,9 +165,11 @@ class SourceFooter extends PureComponent { } renderCommands() { - const commands = [this.blackBoxButton(), this.prettyPrintButton()].filter( - Boolean - ); + const commands = [ + this.blackBoxButton(), + this.prettyPrintButton(), + this.renderSourceMapButton(), + ].filter(Boolean); return commands.length ? div( @@ -169,7 +181,7 @@ class SourceFooter extends PureComponent { : null; } - renderSourceSummary() { + renderMappedSource() { const { mappedSource, jumpToMappedLocation, selectedLocation } = this.props; if (!mappedSource) { @@ -182,12 +194,11 @@ class SourceFooter extends PureComponent { : "sourceFooter.mappedGeneratedSource.tooltip", mappedSource.url ); - const filename = getFilename(mappedSource); const label = L10N.getFormatStr( mappedSource.isOriginal ? "sourceFooter.mappedOriginalSource.title" : "sourceFooter.mappedGeneratedSource.title", - filename + mappedSource.shortName ); return button( { @@ -227,6 +238,148 @@ class SourceFooter extends PureComponent { ); } + getSourceMapLabel() { + if (!this.props.selectedLocation) { + return undefined; + } + if (!this.props.areSourceMapsEnabled) { + return L10N.getStr("sourceFooter.sourceMapButton.disabled"); + } + if (this.props.sourceMapError) { + return undefined; + } + if (!this.props.isSourceActorWithSourceMap) { + return L10N.getStr("sourceFooter.sourceMapButton.sourceNotMapped"); + } + if (this.props.selectedLocation.source.isOriginal) { + return L10N.getStr("sourceFooter.sourceMapButton.isOriginalSource"); + } + return L10N.getStr("sourceFooter.sourceMapButton.isBundleSource"); + } + + getSourceMapTitle() { + if (this.props.sourceMapError) { + return L10N.getFormatStr( + "sourceFooter.sourceMapButton.errorTitle", + this.props.sourceMapError + ); + } + if (this.props.isSourceMapLoading) { + return L10N.getStr("sourceFooter.sourceMapButton.loadingTitle"); + } + return L10N.getStr("sourceFooter.sourceMapButton.title"); + } + + renderSourceMapButton() { + const { toolboxDoc } = this.context; + + return React.createElement( + MenuButton, + { + menuId: "debugger-source-map-button", + toolboxDoc, + className: classnames("devtools-button", "debugger-source-map-button", { + error: !!this.props.sourceMapError, + loading: this.props.isSourceMapLoading, + disabled: !this.props.areSourceMapsEnabled, + "not-mapped": + !this.props.selectedLocation?.source.isOriginal && + !this.props.isSourceActorWithSourceMap, + original: this.props.selectedLocation?.source.isOriginal, + }), + title: this.getSourceMapTitle(), + label: this.getSourceMapLabel(), + icon: true, + }, + () => this.renderSourceMapMenuItems() + ); + } + + renderSourceMapMenuItems() { + const items = [ + React.createElement(MenuItem, { + className: "menu-item debugger-source-map-enabled", + checked: this.props.areSourceMapsEnabled, + label: L10N.getStr("sourceFooter.sourceMapButton.enable"), + onClick: this.toggleSourceMaps, + }), + hr(), + React.createElement(MenuItem, { + className: "menu-item debugger-source-map-open-original", + checked: this.props.shouldSelectOriginalLocation, + label: L10N.getStr( + "sourceFooter.sourceMapButton.showOriginalSourceByDefault" + ), + onClick: this.toggleSelectOriginalByDefault, + }), + ]; + + if (this.props.mappedSource) { + items.push( + React.createElement(MenuItem, { + className: "menu-item debugger-jump-mapped-source", + label: this.props.mappedSource.isOriginal + ? L10N.getStr("sourceFooter.sourceMapButton.jumpToGeneratedSource") + : L10N.getStr("sourceFooter.sourceMapButton.jumpToOriginalSource"), + tooltip: this.props.mappedSource.url, + onClick: () => + this.props.jumpToMappedLocation(this.props.selectedLocation), + }) + ); + } + + if (this.props.resolvedSourceMapURL) { + items.push( + React.createElement(MenuItem, { + className: "menu-item debugger-source-map-link", + label: L10N.getStr( + "sourceFooter.sourceMapButton.openSourceMapInNewTab" + ), + onClick: this.openSourceMap, + }) + ); + } + return React.createElement( + MenuList, + { + id: "debugger-source-map-list", + }, + items + ); + } + + openSourceMap = () => { + let line, column; + if ( + this.props.sourceMapError && + this.props.sourceMapError.includes("JSON.parse") + ) { + const match = this.props.sourceMapError.match( + /at line (\d+) column (\d+)/ + ); + if (match) { + line = match[1]; + column = match[2]; + } + } + this.props.openSourceMap( + this.props.resolvedSourceMapURL || this.props.selectedLocation.source.url, + line, + column + ); + }; + + toggleSourceMaps = () => { + this.props.toggleSourceMapsEnabled(!this.props.areSourceMapsEnabled); + }; + + toggleSelectOriginalByDefault = () => { + this.props.setDefaultSelectedLocation( + !this.props.shouldSelectOriginalLocation + ); + this.props.jumpToMappedSelectedLocation(); + }; + render() { return div( { @@ -242,19 +395,40 @@ class SourceFooter extends PureComponent { { className: "source-footer-end", }, - this.renderSourceSummary(), + this.renderMappedSource(), this.renderCursorPosition(), this.renderToggleButton() ) ); } } +SourceFooter.contextTypes = { + toolboxDoc: PropTypes.object, +}; const mapStateToProps = state => { const selectedSource = getSelectedSource(state); const selectedLocation = getSelectedLocation(state); const sourceTextContent = getSelectedSourceTextContent(state); + const areSourceMapsEnabledProp = areSourceMapsEnabled(state); + const isSourceActorWithSourceMapProp = isSourceActorWithSourceMap( + state, + selectedLocation?.sourceActor.id + ); + const sourceMapError = selectedLocation?.sourceActor + ? getSourceMapErrorForSourceActor(state, selectedLocation.sourceActor.id) + : null; + const mappedSource = getSelectedMappedSource(state); + + const isSourceMapLoading = + areSourceMapsEnabledProp && + isSourceActorWithSourceMapProp && + // `mappedSource` will be null while loading, we need another way to know when it is done computing + !mappedSource && + isSelectedMappedSourceLoading(state) && + !sourceMapError; + return { selectedSource, selectedLocation, @@ -265,7 +439,8 @@ const mapStateToProps = state => { isSourceMapIgnoreListEnabled(state) && isSourceOnSourceMapIgnoreList(state, selectedSource), sourceLoaded: !!sourceTextContent, - mappedSource: getSelectedMappedSource(state), + mappedSource, + isSourceMapLoading, prettySource: getPrettySource( state, selectedSource ? selectedSource.id : null @@ -277,6 +452,17 @@ const mapStateToProps = state => { prettyPrintMessage: selectedLocation ? getPrettyPrintMessage(state, selectedLocation) : null, + + sourceMapError, + resolvedSourceMapURL: selectedLocation?.sourceActor + ? getSourceMapResolvedURL(state, selectedLocation.sourceActor.id) + : null, + isSourceActorWithSourceMap: isSourceActorWithSourceMapProp, + + sourceMapURL: selectedLocation?.sourceActor.sourceMapURL, + + areSourceMapsEnabled: areSourceMapsEnabledProp, + shouldSelectOriginalLocation: getShouldSelectOriginalLocation(state), }; }; @@ -285,4 +471,8 @@ export default connect(mapStateToProps, { toggleBlackBox: actions.toggleBlackBox, jumpToMappedLocation: actions.jumpToMappedLocation, togglePaneCollapse: actions.togglePaneCollapse, + toggleSourceMapsEnabled: actions.toggleSourceMapsEnabled, + setDefaultSelectedLocation: actions.setDefaultSelectedLocation, + jumpToMappedSelectedLocation: actions.jumpToMappedSelectedLocation, + openSourceMap: actions.openSourceMap, })(SourceFooter); diff --git a/devtools/client/debugger/src/components/Editor/InlinePreview.js b/devtools/client/debugger/src/components/Editor/InlinePreview.js index 552143dcf2..60303e38b5 100644 --- a/devtools/client/debugger/src/components/Editor/InlinePreview.js +++ b/devtools/client/debugger/src/components/Editor/InlinePreview.js @@ -27,7 +27,7 @@ class InlinePreview extends PureComponent { }; } - showInScopes(variable) { + showInScopes() { // TODO: focus on variable value in the scopes sidepanel // we will need more info from parent comp } diff --git a/devtools/client/debugger/src/components/Editor/InlinePreviewRow.js b/devtools/client/debugger/src/components/Editor/InlinePreviewRow.js index bc54fc5b4d..18fe98ff17 100644 --- a/devtools/client/debugger/src/components/Editor/InlinePreviewRow.js +++ b/devtools/client/debugger/src/components/Editor/InlinePreviewRow.js @@ -67,13 +67,13 @@ class InlinePreviewRow extends PureComponent { null, previews.map(preview => React.createElement(InlinePreview, { - line: line, + line, key: `${line}-${preview.name}`, variable: preview.name, value: preview.value, - openElementInInspector: openElementInInspector, - highlightDomElement: highlightDomElement, - unHighlightDomElement: unHighlightDomElement, + openElementInInspector, + highlightDomElement, + unHighlightDomElement, }) ) ), diff --git a/devtools/client/debugger/src/components/Editor/InlinePreviews.js b/devtools/client/debugger/src/components/Editor/InlinePreviews.js index 18616ae3ed..ba8b08669a 100644 --- a/devtools/client/debugger/src/components/Editor/InlinePreviews.js +++ b/devtools/client/debugger/src/components/Editor/InlinePreviews.js @@ -49,7 +49,7 @@ class InlinePreviews extends Component { inlinePreviewRows = Object.keys(previewsObj).map(line => { const lineNum = parseInt(line, 10); return React.createElement(InlinePreviewRow, { - editor: editor, + editor, key: line, line: lineNum, previews: previewsObj[line], diff --git a/devtools/client/debugger/src/components/Editor/Preview/Popup.js b/devtools/client/debugger/src/components/Editor/Preview/Popup.js index a010358dc1..431cb52729 100644 --- a/devtools/client/debugger/src/components/Editor/Preview/Popup.js +++ b/devtools/client/debugger/src/components/Editor/Preview/Popup.js @@ -100,7 +100,7 @@ export class Popup extends Component { renderExceptionPreview(exception) { return React.createElement(ExceptionPopup, { - exception: exception, + exception, clearPreview: this.props.clearPreview, }); } @@ -182,8 +182,8 @@ export class Popup extends Component { Popover, { targetPosition: cursorPos, - type: type, - editorRef: editorRef, + type, + editorRef, target: this.props.preview.target, mouseout: this.props.clearPreview, }, diff --git a/devtools/client/debugger/src/components/Editor/Preview/index.js b/devtools/client/debugger/src/components/Editor/Preview/index.js index 218d33007f..10c600670e 100644 --- a/devtools/client/debugger/src/components/Editor/Preview/index.js +++ b/devtools/client/debugger/src/components/Editor/Preview/index.js @@ -44,7 +44,7 @@ class Preview extends PureComponent { codeMirrorWrapper.removeEventListener("mousedown", this.onMouseDown); } - updateListeners(prevProps) { + updateListeners() { const { codeMirror } = this.props.editor; const codeMirrorWrapper = codeMirror.getWrapperElement(); codeMirror.on("tokenenter", this.onTokenEnter); @@ -107,7 +107,7 @@ class Preview extends PureComponent { return null; } return React.createElement(Popup, { - preview: preview, + preview, editor: this.props.editor, editorRef: this.props.editorRef, clearPreview: this.clearPreview, diff --git a/devtools/client/debugger/src/components/Editor/SearchInFileBar.js b/devtools/client/debugger/src/components/Editor/SearchInFileBar.js index a3491a3fef..26f95ce75d 100644 --- a/devtools/client/debugger/src/components/Editor/SearchInFileBar.js +++ b/devtools/client/debugger/src/components/Editor/SearchInFileBar.js @@ -97,7 +97,7 @@ class SearchInFileBar extends Component { shortcuts.on("Escape", this.onEscape); } - componentDidUpdate(prevProps, prevState) { + componentDidUpdate() { if (this.refs.resultList && this.refs.resultList.refs) { scrollList(this.refs.resultList.refs, this.state.selectedResultIndex); } @@ -111,7 +111,7 @@ class SearchInFileBar extends Component { const { editor: ed } = this.props; if (ed) { const ctx = { ed, cm: ed.codeMirror }; - removeOverlay(ctx, this.state.query); + removeOverlay(ctx); } }; @@ -165,7 +165,7 @@ class SearchInFileBar extends Component { const ctx = { ed: editor, cm: editor.codeMirror }; if (!query) { - clearSearch(ctx.cm, query); + clearSearch(ctx.cm); return; } @@ -249,11 +249,11 @@ class SearchInFileBar extends Component { return this.doSearch(e.target.value); }; - onFocus = e => { + onFocus = () => { this.setState({ inputFocused: true }); }; - onBlur = e => { + onBlur = () => { this.setState({ inputFocused: false }); }; @@ -321,7 +321,7 @@ class SearchInFileBar extends Component { }, React.createElement(SearchInput, { query: this.state.query, - count: count, + count, placeholder: L10N.getStr("sourceSearch.search.placeholder2"), summaryMsg: this.buildSummaryMsg(), isLoading: false, @@ -349,7 +349,7 @@ SearchInFileBar.contextTypes = { shortcuts: PropTypes.object, }; -const mapStateToProps = (state, p) => { +const mapStateToProps = state => { const selectedSource = getSelectedSource(state); return { diff --git a/devtools/client/debugger/src/components/Editor/Tab.js b/devtools/client/debugger/src/components/Editor/Tab.js index ba5e1c1934..98aca90cd2 100644 --- a/devtools/client/debugger/src/components/Editor/Tab.js +++ b/devtools/client/debugger/src/components/Editor/Tab.js @@ -15,7 +15,6 @@ import actions from "../../actions/index"; import { getDisplayPath, getFileURL, - getSourceQueryString, getTruncatedFileName, isPretty, } from "../../utils/source"; @@ -87,14 +86,13 @@ class Tab extends PureComponent { }); const path = getDisplayPath(source, tabSources); - const query = getSourceQueryString(source); return div( { draggable: true, - onDragOver: onDragOver, - onDragStart: onDragStart, - onDragEnd: onDragEnd, - className: className, + onDragOver, + onDragStart, + onDragEnd, + className, "data-index": index, "data-source-id": sourceId, onClick: handleTabClick, @@ -115,7 +113,7 @@ class Tab extends PureComponent { { className: "filename", }, - getTruncatedFileName(source, query), + getTruncatedFileName(source), path && span(null, `../${path}/..`) ), React.createElement(CloseButton, { diff --git a/devtools/client/debugger/src/components/Editor/Tabs.js b/devtools/client/debugger/src/components/Editor/Tabs.js index 3577a4909c..d93f7d3b18 100644 --- a/devtools/client/debugger/src/components/Editor/Tabs.js +++ b/devtools/client/debugger/src/components/Editor/Tabs.js @@ -23,7 +23,7 @@ import { import { isVisible } from "../../utils/ui"; import { getHiddenTabs } from "../../utils/tabs"; -import { getFilename, isPretty, getFileURL } from "../../utils/source"; +import { isPretty, getFileURL } from "../../utils/source"; import actions from "../../actions/index"; import Tab from "./Tab"; @@ -144,13 +144,12 @@ class Tabs extends PureComponent { renderDropdownSource = source => { const { selectSource } = this.props; - const filename = getFilename(source); const onClick = () => selectSource(source); return li( { key: source.id, - onClick: onClick, + onClick, title: getFileURL(source, false), }, React.createElement(AccessibleImage, { @@ -160,7 +159,7 @@ class Tabs extends PureComponent { { className: "dropdown-label", }, - filename + source.shortName ) ); }; diff --git a/devtools/client/debugger/src/components/Editor/index.js b/devtools/client/debugger/src/components/Editor/index.js index c659de77d2..ae9bde7657 100644 --- a/devtools/client/debugger/src/components/Editor/index.js +++ b/devtools/client/debugger/src/components/Editor/index.js @@ -12,6 +12,7 @@ import { connect } from "devtools/client/shared/vendor/react-redux"; import { getLineText, isLineBlackboxed } from "./../../utils/source"; import { createLocation } from "./../../utils/location"; import { getIndentation } from "../../utils/indentation"; +import { features } from "../../utils/prefs"; import { getActiveSearch, @@ -50,10 +51,9 @@ import BlackboxLines from "./BlackboxLines"; import { showSourceText, - showLoading, - showErrorMessage, + setDocument, + resetLineNumberFormat, getEditor, - clearEditor, getCursorLine, getCursorColumn, lineAtHeight, @@ -143,37 +143,45 @@ class Editor extends PureComponent { this.props.selectedSourceTextContent?.value || nextProps.symbols !== this.props.symbols; - const shouldUpdateSize = - nextProps.startPanelSize !== this.props.startPanelSize || - nextProps.endPanelSize !== this.props.endPanelSize; - - const shouldScroll = - nextProps.selectedLocation && - this.shouldScrollToLocation(nextProps, editor); + if (!features.codemirrorNext) { + const shouldUpdateSize = + nextProps.startPanelSize !== this.props.startPanelSize || + nextProps.endPanelSize !== this.props.endPanelSize; + + const shouldScroll = + nextProps.selectedLocation && + this.shouldScrollToLocation(nextProps, editor); + + if (shouldUpdateText || shouldUpdateSize || shouldScroll) { + startOperation(); + if (shouldUpdateText) { + this.setText(nextProps, editor); + } + if (shouldUpdateSize) { + editor.codeMirror.setSize(); + } + if (shouldScroll) { + this.scrollToLocation(nextProps, editor); + } + endOperation(); + } - if (shouldUpdateText || shouldUpdateSize || shouldScroll) { - startOperation(); + if (this.props.selectedSource != nextProps.selectedSource) { + this.props.updateViewport(); + resizeBreakpointGutter(editor.codeMirror); + resizeToggleButton(editor.codeMirror); + } + } else { + // For codemirror 6 + // eslint-disable-next-line no-lonely-if if (shouldUpdateText) { this.setText(nextProps, editor); } - if (shouldUpdateSize) { - editor.codeMirror.setSize(); - } - if (shouldScroll) { - this.scrollToLocation(nextProps, editor); - } - endOperation(); - } - - if (this.props.selectedSource != nextProps.selectedSource) { - this.props.updateViewport(); - resizeBreakpointGutter(editor.codeMirror); - resizeToggleButton(editor.codeMirror); } } setupEditor() { - const editor = getEditor(); + const editor = getEditor(features.codemirrorNext); // disables the default search shortcuts editor._initShortcuts = () => {}; @@ -183,71 +191,84 @@ class Editor extends PureComponent { editor.appendToLocalElement(node.querySelector(".editor-mount")); } - const { codeMirror } = editor; - - this.abortController = new window.AbortController(); - - // CodeMirror refreshes its internal state on window resize, but we need to also - // refresh it when the side panels are resized. - // We could have a ResizeObserver instead, but we wouldn't be able to differentiate - // between window resize and side panel resize and as a result, might refresh - // codeMirror twice, which is wasteful. - window.document - .querySelector(".editor-pane") - .addEventListener("resizeend", () => codeMirror.refresh(), { - signal: this.abortController.signal, - }); - - codeMirror.on("gutterClick", this.onGutterClick); - codeMirror.on("cursorActivity", this.onCursorChange); - - const codeMirrorWrapper = codeMirror.getWrapperElement(); - // Set code editor wrapper to be focusable - codeMirrorWrapper.tabIndex = 0; - codeMirrorWrapper.addEventListener("keydown", e => this.onKeyDown(e)); - codeMirrorWrapper.addEventListener("click", e => this.onClick(e)); - codeMirrorWrapper.addEventListener("mouseover", onMouseOver(codeMirror)); - - const toggleFoldMarkerVisibility = e => { - if (node instanceof HTMLElement) { - node - .querySelectorAll(".CodeMirror-guttermarker-subtle") - .forEach(elem => { - elem.classList.toggle("visible"); - }); - } - }; + if (!features.codemirrorNext) { + const { codeMirror } = editor; + + this.abortController = new window.AbortController(); + + // CodeMirror refreshes its internal state on window resize, but we need to also + // refresh it when the side panels are resized. + // We could have a ResizeObserver instead, but we wouldn't be able to differentiate + // between window resize and side panel resize and as a result, might refresh + // codeMirror twice, which is wasteful. + window.document + .querySelector(".editor-pane") + .addEventListener("resizeend", () => codeMirror.refresh(), { + signal: this.abortController.signal, + }); + + codeMirror.on("gutterClick", this.onGutterClick); + codeMirror.on("cursorActivity", this.onCursorChange); + + const codeMirrorWrapper = codeMirror.getWrapperElement(); + // Set code editor wrapper to be focusable + codeMirrorWrapper.tabIndex = 0; + codeMirrorWrapper.addEventListener("keydown", e => this.onKeyDown(e)); + codeMirrorWrapper.addEventListener("click", e => this.onClick(e)); + codeMirrorWrapper.addEventListener("mouseover", onMouseOver(codeMirror)); + + const toggleFoldMarkerVisibility = () => { + 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); - codeMirrorWrapper.addEventListener("contextmenu", event => - this.openMenu(event) - ); + const codeMirrorGutter = codeMirror.getGutterElement(); + codeMirrorGutter.addEventListener( + "mouseleave", + toggleFoldMarkerVisibility + ); + codeMirrorGutter.addEventListener( + "mouseenter", + toggleFoldMarkerVisibility + ); + codeMirrorWrapper.addEventListener("contextmenu", event => + this.openMenu(event) + ); - codeMirror.on("scroll", this.onEditorScroll); - this.onEditorScroll(); + codeMirror.on("scroll", this.onEditorScroll); + this.onEditorScroll(); + } this.setState({ editor }); return editor; } componentDidMount() { - const { shortcuts } = this.context; + if (!features.codemirrorNext) { + const { shortcuts } = this.context; - shortcuts.on(L10N.getStr("toggleBreakpoint.key"), this.onToggleBreakpoint); - shortcuts.on( - L10N.getStr("toggleCondPanel.breakpoint.key"), - this.onToggleConditionalPanel - ); - shortcuts.on( - L10N.getStr("toggleCondPanel.logPoint.key"), - this.onToggleConditionalPanel - ); - shortcuts.on( - L10N.getStr("sourceTabs.closeTab.key"), - this.onCloseShortcutPress - ); - shortcuts.on("Esc", this.onEscape); + shortcuts.on( + L10N.getStr("toggleBreakpoint.key"), + this.onToggleBreakpoint + ); + shortcuts.on( + L10N.getStr("toggleCondPanel.breakpoint.key"), + this.onToggleConditionalPanel + ); + shortcuts.on( + L10N.getStr("toggleCondPanel.logPoint.key"), + this.onToggleConditionalPanel + ); + shortcuts.on( + L10N.getStr("sourceTabs.closeTab.key"), + this.onCloseShortcutPress + ); + shortcuts.on("Esc", this.onEscape); + } } onCloseShortcutPress = e => { @@ -260,22 +281,24 @@ class Editor extends PureComponent { }; componentWillUnmount() { - const { editor } = this.state; - if (editor) { - editor.destroy(); - editor.codeMirror.off("scroll", this.onEditorScroll); - this.setState({ editor: null }); - } + if (!features.codemirrorNext) { + const { editor } = this.state; + if (editor) { + editor.destroy(); + editor.codeMirror.off("scroll", this.onEditorScroll); + this.setState({ editor: null }); + } - const { shortcuts } = this.context; - shortcuts.off(L10N.getStr("sourceTabs.closeTab.key")); - shortcuts.off(L10N.getStr("toggleBreakpoint.key")); - shortcuts.off(L10N.getStr("toggleCondPanel.breakpoint.key")); - shortcuts.off(L10N.getStr("toggleCondPanel.logPoint.key")); + const { shortcuts } = this.context; + shortcuts.off(L10N.getStr("sourceTabs.closeTab.key")); + shortcuts.off(L10N.getStr("toggleBreakpoint.key")); + shortcuts.off(L10N.getStr("toggleCondPanel.breakpoint.key")); + shortcuts.off(L10N.getStr("toggleCondPanel.logPoint.key")); - if (this.abortController) { - this.abortController.abort(); - this.abortController = null; + if (this.abortController) { + this.abortController.abort(); + this.abortController = null; + } } } @@ -542,7 +565,7 @@ class Editor extends PureComponent { } } - shouldScrollToLocation(nextProps, editor) { + shouldScrollToLocation(nextProps) { if ( !nextProps.selectedLocation?.line || !nextProps.selectedSourceTextContent @@ -583,12 +606,14 @@ class Editor extends PureComponent { // check if we previously had a selected source if (!selectedSource) { - this.clearEditor(); + if (!features.codemirrorNext) { + this.clearEditor(); + } return; } if (!selectedSourceTextContent?.value) { - showLoading(editor); + this.showLoadingMessage(editor); return; } @@ -602,7 +627,16 @@ class Editor extends PureComponent { return; } - showSourceText(editor, selectedSource, selectedSourceTextContent, symbols); + if (!features.codemirrorNext) { + showSourceText( + editor, + selectedSource, + selectedSourceTextContent, + symbols + ); + } else { + editor.setText(selectedSourceTextContent.value.value); + } } clearEditor() { @@ -611,7 +645,9 @@ class Editor extends PureComponent { return; } - clearEditor(editor); + const doc = editor.createDocument("", { name: "text" }); + editor.replaceDocument(doc); + resetLineNumberFormat(editor); } showErrorMessage(msg) { @@ -620,7 +656,37 @@ class Editor extends PureComponent { return; } - showErrorMessage(editor, msg); + let error; + if (msg.includes("WebAssembly binary source is not available")) { + error = L10N.getStr("wasmIsNotAvailable"); + } else { + error = L10N.getFormatStr("errorLoadingText3", msg); + } + if (!features.codemirrorNext) { + const doc = editor.createDocument(error, { name: "text" }); + editor.replaceDocument(doc); + resetLineNumberFormat(editor); + } else { + editor.setText(error); + } + } + + showLoadingMessage(editor) { + if (!features.codemirrorNext) { + // Create the "loading message" document only once + let doc = getDocument("loading"); + if (!doc) { + doc = editor.createDocument(L10N.getStr("loadingText"), { + name: "text", + }); + setDocument("loading", doc); + } + // `createDocument` won't be used right away in the editor, we still need to + // explicitely update it + editor.replaceDocument(doc); + } else { + editor.setText(L10N.getStr("loadingText")); + } } getInlineEditorStyles() { diff --git a/devtools/client/debugger/src/components/Editor/tests/DebugLine.spec.js b/devtools/client/debugger/src/components/Editor/tests/DebugLine.spec.js index 767dde9e6d..38bb318611 100644 --- a/devtools/client/debugger/src/components/Editor/tests/DebugLine.spec.js +++ b/devtools/client/debugger/src/components/Editor/tests/DebugLine.spec.js @@ -15,7 +15,7 @@ function createMockDocument(clear) { addLineClass: jest.fn(), removeLineClass: jest.fn(), markText: jest.fn(() => ({ clear })), - getLine: line => "", + getLine: () => "", }; return doc; diff --git a/devtools/client/debugger/src/components/Editor/tests/__snapshots__/ConditionalPanel.spec.js.snap b/devtools/client/debugger/src/components/Editor/tests/__snapshots__/ConditionalPanel.spec.js.snap index 58e86f5009..86d848ec3e 100644 --- a/devtools/client/debugger/src/components/Editor/tests/__snapshots__/ConditionalPanel.spec.js.snap +++ b/devtools/client/debugger/src/components/Editor/tests/__snapshots__/ConditionalPanel.spec.js.snap @@ -22,6 +22,8 @@ exports[`ConditionalPanel should render at location of selected breakpoint 1`] = "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -44,6 +46,8 @@ exports[`ConditionalPanel should render at location of selected breakpoint 1`] = "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -217,6 +221,8 @@ exports[`ConditionalPanel should render at location of selected breakpoint 1`] = "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -239,6 +245,8 @@ exports[`ConditionalPanel should render at location of selected breakpoint 1`] = "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", } @@ -268,6 +276,8 @@ exports[`ConditionalPanel should render with condition at selected breakpoint lo "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -290,6 +300,8 @@ exports[`ConditionalPanel should render with condition at selected breakpoint lo "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -467,6 +479,8 @@ exports[`ConditionalPanel should render with condition at selected breakpoint lo "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -489,6 +503,8 @@ exports[`ConditionalPanel should render with condition at selected breakpoint lo "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", } @@ -518,6 +534,8 @@ exports[`ConditionalPanel should render with logpoint at selected breakpoint loc "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -540,6 +558,8 @@ exports[`ConditionalPanel should render with logpoint at selected breakpoint loc "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -717,6 +737,8 @@ exports[`ConditionalPanel should render with logpoint at selected breakpoint loc "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -739,6 +761,8 @@ exports[`ConditionalPanel should render with logpoint at selected breakpoint loc "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", } diff --git a/devtools/client/debugger/src/components/Editor/tests/__snapshots__/Footer.spec.js.snap b/devtools/client/debugger/src/components/Editor/tests/__snapshots__/Footer.spec.js.snap index a453b034ff..6c56ad33e7 100644 --- a/devtools/client/debugger/src/components/Editor/tests/__snapshots__/Footer.spec.js.snap +++ b/devtools/client/debugger/src/components/Editor/tests/__snapshots__/Footer.spec.js.snap @@ -31,6 +31,16 @@ exports[`SourceFooter Component default case should render 1`] = ` className="prettyPrint" /> </button> + <MenuButton + className="devtools-button debugger-source-map-button disabled not-mapped" + icon={true} + menuId="debugger-source-map-button" + menuOffset={-5} + menuPosition="bottom" + title="Source Map status" + > + <Component /> + </MenuButton> </div> </div> <div @@ -77,6 +87,16 @@ exports[`SourceFooter Component move cursor should render new cursor position 1` className="prettyPrint" /> </button> + <MenuButton + className="devtools-button debugger-source-map-button disabled not-mapped" + icon={true} + menuId="debugger-source-map-button" + menuOffset={-5} + menuPosition="bottom" + title="Source Map status" + > + <Component /> + </MenuButton> </div> </div> <div diff --git a/devtools/client/debugger/src/components/PrimaryPanes/Outline.js b/devtools/client/debugger/src/components/PrimaryPanes/Outline.js index 79ebf7a38e..d52ed8ff40 100644 --- a/devtools/client/debugger/src/components/PrimaryPanes/Outline.js +++ b/devtools/client/debugger/src/components/PrimaryPanes/Outline.js @@ -82,6 +82,7 @@ export class Outline extends Component { selectedLocation: PropTypes.object.isRequired, getFunctionSymbols: PropTypes.func.isRequired, getClassSymbols: PropTypes.func.isRequired, + selectedSourceTextContent: PropTypes.object, canFetchSymbols: PropTypes.bool, }; } @@ -94,7 +95,8 @@ export class Outline extends Component { } componentDidUpdate(prevProps) { - const { cursorPosition, selectedLocation, canFetchSymbols } = this.props; + const { cursorPosition, selectedSourceTextContent, canFetchSymbols } = + this.props; if (cursorPosition && cursorPosition !== prevProps.cursorPosition) { this.setFocus(cursorPosition); } @@ -106,8 +108,11 @@ export class Outline extends Component { this.focusedElRef.scrollIntoView({ block: "center" }); } - // Lets make sure the source text has been loaded and is different - if (canFetchSymbols && prevProps.selectedLocation !== selectedLocation) { + // Lets make sure the source text has been loaded and it is different + if ( + canFetchSymbols && + prevProps.selectedSourceTextContent !== selectedSourceTextContent + ) { this.getClassAndFunctionSymbols(); } } @@ -133,8 +138,8 @@ export class Outline extends Component { } // Find items that enclose the selected location - const enclosedItems = [...classes, ...functions].filter( - ({ name, location }) => containsPosition(location, cursorPosition) + const enclosedItems = [...classes, ...functions].filter(({ location }) => + containsPosition(location, cursorPosition) ); if (!enclosedItems.length) { @@ -360,7 +365,7 @@ export class Outline extends Component { div( null, React.createElement(OutlineFilter, { - filter: filter, + filter, updateFilter: this.updateFilter, }), this.renderFunctions(functions), @@ -373,6 +378,7 @@ export class Outline extends Component { const mapStateToProps = state => { const selectedSourceTextContent = getSelectedSourceTextContent(state); return { + selectedSourceTextContent, selectedLocation: getSelectedLocation(state), canFetchSymbols: selectedSourceTextContent && isFulfilled(selectedSourceTextContent), diff --git a/devtools/client/debugger/src/components/PrimaryPanes/ProjectSearch.js b/devtools/client/debugger/src/components/PrimaryPanes/ProjectSearch.js index 68b08aed2b..b5a99316f8 100644 --- a/devtools/client/debugger/src/components/PrimaryPanes/ProjectSearch.js +++ b/devtools/client/debugger/src/components/PrimaryPanes/ProjectSearch.js @@ -16,7 +16,6 @@ import { getEditor } from "../../utils/editor/index"; import { searchKeys } from "../../constants"; import { getRelativePath } from "../../utils/sources-tree/utils"; -import { getFormattedSourceId } from "../../utils/source"; import { getProjectSearchQuery, getNavigateCounter, @@ -265,7 +264,7 @@ export class ProjectSearch extends Component { }, file.location.source.url ? getRelativePath(file.location.source.url) - : getFormattedSourceId(file.location.source.id) + : file.location.source.shortName ), span( { @@ -353,7 +352,7 @@ export class ProjectSearch extends Component { autoExpandAll: true, autoExpandDepth: 1, autoExpandNodeChildrenLimit: 100, - getParent: item => null, + getParent: () => null, getPath: getFilePath, renderItem: this.renderItem, focused: this.state.focusedItem, diff --git a/devtools/client/debugger/src/components/PrimaryPanes/SourcesTreeItem.js b/devtools/client/debugger/src/components/PrimaryPanes/SourcesTreeItem.js index fd5ceca46d..575d714ba5 100644 --- a/devtools/client/debugger/src/components/PrimaryPanes/SourcesTreeItem.js +++ b/devtools/client/debugger/src/components/PrimaryPanes/SourcesTreeItem.js @@ -19,7 +19,6 @@ import actions from "../../actions/index"; import { sourceTypes } from "../../utils/source"; import { createLocation } from "../../utils/location"; -import { safeDecodeItemName } from "../../utils/sources-tree/utils"; const classnames = require("resource://devtools/client/shared/classnames.js"); @@ -48,7 +47,7 @@ class SourceTreeItem extends Component { } } - onClick = e => { + onClick = () => { const { item, focusItem, selectSourceItem } = this.props; focusItem(item); @@ -147,19 +146,14 @@ class SourceTreeItem extends Component { ); } if (item.type == "group") { - return safeDecodeItemName(item.groupName); + return item.groupName; } if (item.type == "directory") { const parentItem = this.props.getParent(item); - return safeDecodeItemName( - item.path.replace(parentItem.path, "").replace(/^\//, "") - ); + return item.path.replace(parentItem.path, "").replace(/^\//, ""); } if (item.type == "source") { - const { displayURL } = item.source; - const name = - displayURL.filename + (displayURL.search ? displayURL.search : ""); - return safeDecodeItemName(name); + return item.source.longName; } return null; diff --git a/devtools/client/debugger/src/components/QuickOpenModal.js b/devtools/client/debugger/src/components/QuickOpenModal.js index aa3d4f73b6..438592296d 100644 --- a/devtools/client/debugger/src/components/QuickOpenModal.js +++ b/devtools/client/debugger/src/components/QuickOpenModal.js @@ -377,7 +377,7 @@ export class QuickOpenModal extends Component { isSourceSearch = () => this.isSourcesQuery() || this.isGotoSourceQuery(); /* eslint-disable react/no-danger */ - renderHighlight(candidateString, query, name) { + renderHighlight(candidateString, query) { const options = { wrap: { tagOpen: '<mark class="highlight">', @@ -444,7 +444,7 @@ export class QuickOpenModal extends Component { handleClose: this.closeModal, }, React.createElement(SearchInput, { - query: query, + query, hasPrefix: true, count: this.getResultCount(), placeholder: L10N.getStr("sourceSearch.search2"), @@ -454,7 +454,7 @@ export class QuickOpenModal extends Component { onChange: this.onChange, onKeyDown: this.onKeyDown, handleClose: this.closeModal, - expanded: expanded, + expanded, showClose: false, searchKey: searchKeys.QUICKOPEN_SEARCH, showExcludePatterns: false, @@ -466,11 +466,11 @@ export class QuickOpenModal extends Component { results && React.createElement(ResultList, { key: "results", - items: items, + items, selected: selectedIndex, selectItem: this.selectResultItem, ref: "resultList", - expanded: expanded, + expanded, ...(this.isSourceSearch() ? SIZE_BIG : SIZE_DEFAULT), }) ); diff --git a/devtools/client/debugger/src/components/SecondaryPanes/Breakpoints/BreakpointHeading.js b/devtools/client/debugger/src/components/SecondaryPanes/Breakpoints/BreakpointHeading.js index 78cc530cff..a4a5010c48 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/Breakpoints/BreakpointHeading.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/Breakpoints/BreakpointHeading.js @@ -12,7 +12,6 @@ import actions from "../../../actions/index"; import { getTruncatedFileName, getDisplayPath, - getSourceQueryString, getFileURL, } from "../../../utils/source"; import { createLocation } from "../../../utils/location"; @@ -40,7 +39,6 @@ class BreakpointHeading extends PureComponent { const { sources, source, selectSource } = this.props; const path = getDisplayPath(source, sources); - const query = getSourceQueryString(source); return div( { className: "breakpoint-heading", @@ -67,7 +65,7 @@ class BreakpointHeading extends PureComponent { { className: "filename", }, - getTruncatedFileName(source, query), + getTruncatedFileName(source), path && span(null, `../${path}/..`) ) ); diff --git a/devtools/client/debugger/src/components/SecondaryPanes/Breakpoints/ExceptionOption.js b/devtools/client/debugger/src/components/SecondaryPanes/Breakpoints/ExceptionOption.js index 31ff3f44a3..caec23b848 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/Breakpoints/ExceptionOption.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/Breakpoints/ExceptionOption.js @@ -21,7 +21,7 @@ export default function ExceptionOption({ input({ type: "checkbox", checked: isChecked, - onChange: onChange, + onChange, }), div( { diff --git a/devtools/client/debugger/src/components/SecondaryPanes/Breakpoints/index.js b/devtools/client/debugger/src/components/SecondaryPanes/Breakpoints/index.js index 0f5d6f7ae3..1f5e08cd7e 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/Breakpoints/index.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/Breakpoints/index.js @@ -17,6 +17,7 @@ import { getSelectedLocation } from "../../../utils/selected-location"; import { createHeadlessEditor } from "../../../utils/editor/create-editor"; import { makeBreakpointId } from "../../../utils/breakpoint/index"; +import { features } from "../../../utils/prefs"; import { getSelectedSource, @@ -44,7 +45,7 @@ class Breakpoints extends Component { this.removeEditor(); } - getEditor() { + getHeadlessEditor() { if (!this.headlessEditor) { this.headlessEditor = createHeadlessEditor(); } @@ -119,7 +120,7 @@ class Breakpoints extends Component { return null; } - const editor = this.getEditor(); + const editor = this.getHeadlessEditor(); const sources = breakpointSources.map(({ source }) => source); return div( { @@ -153,7 +154,7 @@ class Breakpoints extends Component { className: "pane", }, this.renderExceptionsOptions(), - this.renderBreakpoints() + !features.codemirrorNext ? this.renderBreakpoints() : null ); } } diff --git a/devtools/client/debugger/src/components/SecondaryPanes/CommandBar.js b/devtools/client/debugger/src/components/SecondaryPanes/CommandBar.js index deae156a40..3dca62d48a 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/CommandBar.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/CommandBar.js @@ -231,7 +231,7 @@ class CommandBar extends Component { formatKey("trace"), this.props.logMethod ), - onClick: event => { + onClick: () => { this.props.toggleTracing(); }, onContextMenu: event => { @@ -362,7 +362,7 @@ class CommandBar extends Component { MenuButton, { menuId: "debugger-settings-menu-button", - toolboxDoc: toolboxDoc, + toolboxDoc, className: "devtools-button command-bar-button debugger-settings-menu-button", title: L10N.getStr("settings.button.label"), diff --git a/devtools/client/debugger/src/components/SecondaryPanes/EventListeners.js b/devtools/client/debugger/src/components/SecondaryPanes/EventListeners.js index ce7eabf89d..00c885ec16 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/EventListeners.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/EventListeners.js @@ -116,11 +116,11 @@ class EventListeners extends Component { } }; - onFocus = event => { + onFocus = () => { this.setState({ focused: true }); }; - onBlur = event => { + onBlur = () => { this.setState({ focused: false }); }; @@ -136,7 +136,7 @@ class EventListeners extends Component { className: classnames("event-search-input", { focused, }), - placeholder: placeholder, + placeholder, value: searchText, onChange: this.onInputChange, onKeyDown: this.onKeyDown, @@ -233,7 +233,7 @@ class EventListeners extends Component { indeterminate ? false : e.target.checked ); }, - checked: checked, + checked, ref: el => el && (el.indeterminate = indeterminate), }), span( diff --git a/devtools/client/debugger/src/components/SecondaryPanes/Expressions.js b/devtools/client/debugger/src/components/SecondaryPanes/Expressions.js index be05c7327c..89b1f651ce 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/Expressions.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/Expressions.js @@ -296,7 +296,7 @@ class Expressions extends Component { roots: [root], autoExpandDepth: 0, disableWrap: true, - openLink: openLink, + openLink, createElement: this.createElement, onDoubleClick: (items, { depth }) => { if (depth === 0) { @@ -374,7 +374,7 @@ class Expressions extends Component { input({ className: "input-expression", type: "text", - placeholder: L10N.getStr("expressions.placeholder"), + placeholder: L10N.getStr("expressions.placeholder2"), onChange: this.handleChange, onBlur: this.hideInput, onKeyDown: this.handleKeyDown, diff --git a/devtools/client/debugger/src/components/SecondaryPanes/Frames/Frame.js b/devtools/client/debugger/src/components/SecondaryPanes/Frames/Frame.js index 0c81d8afb4..2c5cc679bf 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/Frames/Frame.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/Frames/Frame.js @@ -7,7 +7,7 @@ import PropTypes from "devtools/client/shared/vendor/react-prop-types"; import AccessibleImage from "../../shared/AccessibleImage"; import { formatDisplayName } from "../../../utils/pause/frames/index"; -import { getFilename, getFileURL } from "../../../utils/source"; +import { getFileURL } from "../../../utils/source"; import FrameIndent from "./FrameIndent"; const classnames = require("resource://devtools/client/shared/classnames.js"); @@ -52,7 +52,7 @@ const FrameLocation = memo( const location = getFrameLocation(frame, shouldDisplayOriginalLocation); const filename = displayFullUrl ? getFileURL(location.source, false) - : getFilename(location.source); + : location.source.shortName; return React.createElement( "span", { @@ -124,7 +124,7 @@ export default class FrameComponent extends Component { this.props.showFrameContextMenu(event, frame); } - onMouseDown(e, frame, selectedFrame) { + onMouseDown(e, frame) { if (e.button !== 0) { return; } @@ -132,7 +132,7 @@ export default class FrameComponent extends Component { this.props.selectFrame(frame); } - onKeyUp(event, frame, selectedFrame) { + onKeyUp(event, frame) { if (event.key != "Enter") { return; } @@ -167,12 +167,12 @@ export default class FrameComponent extends Component { { role: "listitem", key: frame.id, - className: className, + className, onMouseDown: e => this.onMouseDown(e, frame, selectedFrame), onKeyUp: e => this.onKeyUp(e, frame, selectedFrame), onContextMenu: disableContextMenu ? null : e => this.onContextMenu(e), tabIndex: 0, - title: title, + title, }, frame.asyncCause && React.createElement( diff --git a/devtools/client/debugger/src/components/SecondaryPanes/Frames/Group.js b/devtools/client/debugger/src/components/SecondaryPanes/Frames/Group.js index ab9f7073a7..a4ec7f72da 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/Frames/Group.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/Frames/Group.js @@ -110,18 +110,18 @@ export default class Group extends Component { }, group.map(frame => React.createElement(FrameComponent, { - frame: frame, - showFrameContextMenu: showFrameContextMenu, + frame, + showFrameContextMenu, hideLocation: true, key: frame.id, - selectedFrame: selectedFrame, - selectFrame: selectFrame, - selectLocation: selectLocation, + selectedFrame, + selectFrame, + selectLocation, shouldMapDisplayName: false, - displayFullUrl: displayFullUrl, - getFrameTitle: getFrameTitle, - disableContextMenu: disableContextMenu, - panel: panel, + displayFullUrl, + getFrameTitle, + disableContextMenu, + panel, isInGroup: true, }) ) diff --git a/devtools/client/debugger/src/components/SecondaryPanes/Frames/index.js b/devtools/client/debugger/src/components/SecondaryPanes/Frames/index.js index d83b413a01..ff60270024 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/Frames/index.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/Frames/index.js @@ -115,28 +115,28 @@ class Frames extends Component { frameOrGroup.id ? React.createElement(FrameComponent, { frame: frameOrGroup, - showFrameContextMenu: showFrameContextMenu, - selectFrame: selectFrame, - selectLocation: selectLocation, - selectedFrame: selectedFrame, - shouldDisplayOriginalLocation: shouldDisplayOriginalLocation, + showFrameContextMenu, + selectFrame, + selectLocation, + selectedFrame, + shouldDisplayOriginalLocation, key: String(frameOrGroup.id), - displayFullUrl: displayFullUrl, - getFrameTitle: getFrameTitle, - disableContextMenu: disableContextMenu, - panel: panel, + displayFullUrl, + getFrameTitle, + disableContextMenu, + panel, }) : React.createElement(Group, { group: frameOrGroup, - showFrameContextMenu: showFrameContextMenu, - selectFrame: selectFrame, - selectLocation: selectLocation, - selectedFrame: selectedFrame, + showFrameContextMenu, + selectFrame, + selectLocation, + selectedFrame, key: frameOrGroup[0].id, - displayFullUrl: displayFullUrl, - getFrameTitle: getFrameTitle, - disableContextMenu: disableContextMenu, - panel: panel, + displayFullUrl, + getFrameTitle, + disableContextMenu, + panel, }) ) ); diff --git a/devtools/client/debugger/src/components/SecondaryPanes/Frames/tests/__snapshots__/Frame.spec.js.snap b/devtools/client/debugger/src/components/SecondaryPanes/Frames/tests/__snapshots__/Frame.spec.js.snap index 90a5b1f906..c4e6722629 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/Frames/tests/__snapshots__/Frame.spec.js.snap +++ b/devtools/client/debugger/src/components/SecondaryPanes/Frames/tests/__snapshots__/Frame.spec.js.snap @@ -36,6 +36,8 @@ exports[`Frame getFrameTitle 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js", }, @@ -57,6 +59,8 @@ exports[`Frame getFrameTitle 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js", }, @@ -82,6 +86,8 @@ exports[`Frame getFrameTitle 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js", }, @@ -103,6 +109,8 @@ exports[`Frame getFrameTitle 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js", }, @@ -135,6 +143,8 @@ exports[`Frame getFrameTitle 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js", }, @@ -178,6 +188,8 @@ exports[`Frame getFrameTitle 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js", }, @@ -199,6 +211,8 @@ exports[`Frame getFrameTitle 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js", }, @@ -224,6 +238,8 @@ exports[`Frame getFrameTitle 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js", }, @@ -245,6 +261,8 @@ exports[`Frame getFrameTitle 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js", }, @@ -277,6 +295,8 @@ exports[`Frame getFrameTitle 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js", }, @@ -328,6 +348,8 @@ exports[`Frame library frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "backbone.js", + "shortName": "backbone.js", "thread": "FakeThread", "url": "backbone.js", }, @@ -349,6 +371,8 @@ exports[`Frame library frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "backbone.js", + "shortName": "backbone.js", "thread": "FakeThread", "url": "backbone.js", }, @@ -375,6 +399,8 @@ exports[`Frame library frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "backbone.js", + "shortName": "backbone.js", "thread": "FakeThread", "url": "backbone.js", }, @@ -396,6 +422,8 @@ exports[`Frame library frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "backbone.js", + "shortName": "backbone.js", "thread": "FakeThread", "url": "backbone.js", }, @@ -428,6 +456,8 @@ exports[`Frame library frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "backbone.js", + "shortName": "backbone.js", "thread": "FakeThread", "url": "backbone.js", }, @@ -471,6 +501,8 @@ exports[`Frame library frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "backbone.js", + "shortName": "backbone.js", "thread": "FakeThread", "url": "backbone.js", }, @@ -492,6 +524,8 @@ exports[`Frame library frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "backbone.js", + "shortName": "backbone.js", "thread": "FakeThread", "url": "backbone.js", }, @@ -518,6 +552,8 @@ exports[`Frame library frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "backbone.js", + "shortName": "backbone.js", "thread": "FakeThread", "url": "backbone.js", }, @@ -539,6 +575,8 @@ exports[`Frame library frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "backbone.js", + "shortName": "backbone.js", "thread": "FakeThread", "url": "backbone.js", }, @@ -571,6 +609,8 @@ exports[`Frame library frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "backbone.js", + "shortName": "backbone.js", "thread": "FakeThread", "url": "backbone.js", }, @@ -622,6 +662,8 @@ exports[`Frame user frame (not selected) 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -643,6 +685,8 @@ exports[`Frame user frame (not selected) 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -668,6 +712,8 @@ exports[`Frame user frame (not selected) 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -689,6 +735,8 @@ exports[`Frame user frame (not selected) 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -721,6 +769,8 @@ exports[`Frame user frame (not selected) 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -764,6 +814,8 @@ exports[`Frame user frame (not selected) 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -785,6 +837,8 @@ exports[`Frame user frame (not selected) 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -810,6 +864,8 @@ exports[`Frame user frame (not selected) 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -831,6 +887,8 @@ exports[`Frame user frame (not selected) 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -863,6 +921,8 @@ exports[`Frame user frame (not selected) 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -914,6 +974,8 @@ exports[`Frame user frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -935,6 +997,8 @@ exports[`Frame user frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -960,6 +1024,8 @@ exports[`Frame user frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -981,6 +1047,8 @@ exports[`Frame user frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -1013,6 +1081,8 @@ exports[`Frame user frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -1056,6 +1126,8 @@ exports[`Frame user frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -1077,6 +1149,8 @@ exports[`Frame user frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -1102,6 +1176,8 @@ exports[`Frame user frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -1123,6 +1199,8 @@ exports[`Frame user frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, @@ -1155,6 +1233,8 @@ exports[`Frame user frame 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "foo-view.js", + "shortName": "foo-view.js", "thread": "FakeThread", "url": "foo-view.js", }, diff --git a/devtools/client/debugger/src/components/SecondaryPanes/Frames/tests/__snapshots__/Group.spec.js.snap b/devtools/client/debugger/src/components/SecondaryPanes/Frames/tests/__snapshots__/Group.spec.js.snap index 97c4c2ad1a..21a5321ba1 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/Frames/tests/__snapshots__/Group.spec.js.snap +++ b/devtools/client/debugger/src/components/SecondaryPanes/Frames/tests/__snapshots__/Group.spec.js.snap @@ -37,6 +37,8 @@ exports[`Group displays a group 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -58,6 +60,8 @@ exports[`Group displays a group 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -84,6 +88,8 @@ exports[`Group displays a group 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -105,6 +111,8 @@ exports[`Group displays a group 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -137,6 +145,8 @@ exports[`Group displays a group 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -199,6 +209,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -220,6 +232,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -246,6 +260,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -267,6 +283,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -299,6 +317,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -348,6 +368,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -369,6 +391,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -395,6 +419,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -416,6 +442,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -448,6 +476,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -485,6 +515,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -506,6 +538,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -532,6 +566,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -553,6 +589,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -585,6 +623,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -620,6 +660,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -641,6 +683,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -667,6 +711,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -688,6 +734,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -720,6 +768,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -757,6 +807,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -778,6 +830,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -804,6 +858,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -825,6 +881,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -857,6 +915,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -892,6 +952,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -913,6 +975,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -939,6 +1003,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -960,6 +1026,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -992,6 +1060,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -1029,6 +1099,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1050,6 +1122,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1076,6 +1150,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1097,6 +1173,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1129,6 +1207,8 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1181,6 +1261,8 @@ exports[`Group renders group with anonymous functions 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1202,6 +1284,8 @@ exports[`Group renders group with anonymous functions 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1228,6 +1312,8 @@ exports[`Group renders group with anonymous functions 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1249,6 +1335,8 @@ exports[`Group renders group with anonymous functions 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1281,6 +1369,8 @@ exports[`Group renders group with anonymous functions 1`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1343,6 +1433,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1364,6 +1456,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1390,6 +1484,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1411,6 +1507,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1443,6 +1541,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1492,6 +1592,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1513,6 +1615,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1539,6 +1643,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1560,6 +1666,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1592,6 +1700,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "mahscripts.js", + "shortName": "mahscripts.js", "thread": "FakeThread", "url": "http://myfile.com/mahscripts.js", }, @@ -1628,6 +1738,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1649,6 +1761,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1675,6 +1789,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1696,6 +1812,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1728,6 +1846,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1763,6 +1883,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -1784,6 +1906,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -1810,6 +1934,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -1831,6 +1957,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -1863,6 +1991,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -1899,6 +2029,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1920,6 +2052,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1946,6 +2080,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1967,6 +2103,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -1999,6 +2137,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -2034,6 +2174,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -2055,6 +2197,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -2081,6 +2225,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -2102,6 +2248,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -2134,6 +2282,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "back.js", + "shortName": "back.js", "thread": "FakeThread", "url": "http://myfile.com/back.js", }, @@ -2170,6 +2320,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -2191,6 +2343,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -2217,6 +2371,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -2238,6 +2394,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -2270,6 +2428,8 @@ exports[`Group renders group with anonymous functions 2`] = ` "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, diff --git a/devtools/client/debugger/src/components/SecondaryPanes/Scopes.js b/devtools/client/debugger/src/components/SecondaryPanes/Scopes.js index 135decd254..65e4d19032 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/Scopes.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/Scopes.js @@ -307,7 +307,7 @@ class Scopes extends PureComponent { dimTopLevelWindow: true, frame: selectedFrame, mayUseCustomFormatter: true, - openLink: openLink, + openLink, onDOMNodeClick: grip => openElementInInspector(grip), onInspectIconClick: grip => openElementInInspector(grip), onDOMNodeMouseOver: grip => highlightDomElement(grip), @@ -315,7 +315,7 @@ class Scopes extends PureComponent { onContextMenu: this.onContextMenu, setExpanded: (path, expand) => setExpandedScope(selectedFrame, path, expand), - initiallyExpanded: initiallyExpanded, + initiallyExpanded, renderItemActions: this.renderWatchpointButton, shouldRenderTooltip: true, }) diff --git a/devtools/client/debugger/src/components/SecondaryPanes/Threads.js b/devtools/client/debugger/src/components/SecondaryPanes/Threads.js index 2d21a1dcc5..f1426c95cb 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/Threads.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/Threads.js @@ -25,7 +25,7 @@ export class Threads extends Component { }, threads.map(thread => React.createElement(Thread, { - thread: thread, + thread, key: thread.actor, }) ) diff --git a/devtools/client/debugger/src/components/SecondaryPanes/XHRBreakpoints.js b/devtools/client/debugger/src/components/SecondaryPanes/XHRBreakpoints.js index 9774255dcd..f0b86a5f5c 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/XHRBreakpoints.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/XHRBreakpoints.js @@ -164,7 +164,7 @@ class XHRBreakpoints extends Component { this.setState({ focused: true, editing: true }); }; - onMouseDown = e => { + onMouseDown = () => { this.setState({ editing: false, clickedOnFormElement: true }); }; @@ -205,12 +205,12 @@ class XHRBreakpoints extends Component { className: classnames("xhr-input-container xhr-input-form", { focused, }), - onSubmit: onSubmit, + onSubmit, }, input({ className: "xhr-input-url", type: "text", - placeholder: placeholder, + placeholder, onChange: this.handleChange, onBlur: this.hideInput, onFocus: this.onFocus, @@ -262,7 +262,7 @@ class XHRBreakpoints extends Component { className: "xhr-container", key: `${path}-${method}`, title: path, - onDoubleClick: (items, options) => this.editExpression(index), + onDoubleClick: () => this.editExpression(index), }, label( null, @@ -290,7 +290,7 @@ class XHRBreakpoints extends Component { className: "xhr-container__close-btn", }, React.createElement(CloseButton, { - handleClick: e => removeXHRBreakpoint(index), + handleClick: () => removeXHRBreakpoint(index), }) ) ) diff --git a/devtools/client/debugger/src/components/SecondaryPanes/index.js b/devtools/client/debugger/src/components/SecondaryPanes/index.js index 20830afc12..52d0d3298e 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/index.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/index.js @@ -52,7 +52,7 @@ const classnames = require("resource://devtools/client/shared/classnames.js"); function debugBtn(onClick, type, className, tooltip) { return button( { - onClick: onClick, + onClick, className: `${type} ${className}`, key: type, title: tooltip, @@ -136,7 +136,7 @@ class SecondaryPanes extends Component { }, "plus", "active", - L10N.getStr("expressions.placeholder") + L10N.getStr("expressions.placeholder2") ) ); return buttons; @@ -214,7 +214,7 @@ class SecondaryPanes extends Component { input({ type: "checkbox", checked: mapScopesEnabled ? "checked" : "", - onChange: e => this.props.toggleMapScopes(), + onChange: () => this.props.toggleMapScopes(), }), L10N.getStr("scopes.showOriginalScopes") ), @@ -249,7 +249,7 @@ class SecondaryPanes extends Component { input({ type: "checkbox", checked: logEventBreakpoints ? "checked" : "", - onChange: e => this.props.toggleEventLogging(), + onChange: () => this.props.toggleEventLogging(), }), L10N.getStr("eventlisteners.log") ) diff --git a/devtools/client/debugger/src/components/SecondaryPanes/tests/XHRBreakpoints.spec.js b/devtools/client/debugger/src/components/SecondaryPanes/tests/XHRBreakpoints.spec.js index 532c95e4ad..de7ab02ebe 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/tests/XHRBreakpoints.spec.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/tests/XHRBreakpoints.spec.js @@ -225,7 +225,7 @@ describe("XHR Breakpoints", function () { } // check each expected XHR Method to see if they match the actual methods - expectedXHRMethods.forEach((expectedMethod, i) => { + expectedXHRMethods.forEach(expectedMethod => { function compareMethods(actualMethod) { return expectedMethod === actualMethod; } diff --git a/devtools/client/debugger/src/components/shared/Button/CommandBarButton.js b/devtools/client/debugger/src/components/shared/Button/CommandBarButton.js index 4b0b52e186..430feed904 100644 --- a/devtools/client/debugger/src/components/shared/Button/CommandBarButton.js +++ b/devtools/client/debugger/src/components/shared/Button/CommandBarButton.js @@ -22,9 +22,9 @@ export function debugBtn( CommandBarButton, { className: classnames(type, className), - disabled: disabled, + disabled, key: type, - onClick: onClick, + onClick, pressed: ariaPressed, title: tooltip, }, diff --git a/devtools/client/debugger/src/components/shared/Button/tests/CloseButton.spec.js b/devtools/client/debugger/src/components/shared/Button/tests/CloseButton.spec.js index 5e448881d9..60a500776c 100644 --- a/devtools/client/debugger/src/components/shared/Button/tests/CloseButton.spec.js +++ b/devtools/client/debugger/src/components/shared/Button/tests/CloseButton.spec.js @@ -11,7 +11,7 @@ describe("CloseButton", () => { const tooltip = "testTooltip"; const wrapper = shallow( React.createElement(CloseButton, { - tooltip: tooltip, + tooltip, handleClick: () => {}, }) ); diff --git a/devtools/client/debugger/src/components/shared/Button/tests/CommandBarButton.spec.js b/devtools/client/debugger/src/components/shared/Button/tests/CommandBarButton.spec.js index 41537cf8e4..cad3dc1f6b 100644 --- a/devtools/client/debugger/src/components/shared/Button/tests/CommandBarButton.spec.js +++ b/devtools/client/debugger/src/components/shared/Button/tests/CommandBarButton.spec.js @@ -21,7 +21,7 @@ describe("CommandBarButton", () => { const children = [1, 2, 3, 4]; const wrapper = shallow( React.createElement(CommandBarButton, { - children: children, + children, className: "", }) ); diff --git a/devtools/client/debugger/src/components/shared/Dropdown.js b/devtools/client/debugger/src/components/shared/Dropdown.js index a47eef9534..69727b032a 100644 --- a/devtools/client/debugger/src/components/shared/Dropdown.js +++ b/devtools/client/debugger/src/components/shared/Dropdown.js @@ -21,7 +21,7 @@ export class Dropdown extends Component { }; } - toggleDropdown = e => { + toggleDropdown = () => { this.setState(prevState => ({ dropdownShown: !prevState.dropdownShown, })); diff --git a/devtools/client/debugger/src/components/shared/Popover.js b/devtools/client/debugger/src/components/shared/Popover.js index 8748e36418..b81fd7e89e 100644 --- a/devtools/client/debugger/src/components/shared/Popover.js +++ b/devtools/client/debugger/src/components/shared/Popover.js @@ -255,7 +255,6 @@ class Popover extends Component { React.createElement(SmartGap, { token: this.props.target, preview: this.$tooltip || this.$popover, - type: this.props.type, gapHeight: this.gapHeight, coords: this.state.coords, offset: this.$gap.getBoundingClientRect().left, diff --git a/devtools/client/debugger/src/components/shared/ResultList.js b/devtools/client/debugger/src/components/shared/ResultList.js index 6b29de51f4..fb921612e7 100644 --- a/devtools/client/debugger/src/components/shared/ResultList.js +++ b/devtools/client/debugger/src/components/shared/ResultList.js @@ -93,7 +93,7 @@ export default class ResultList extends Component { ref: this.ref, className: classnames("result-list", size), id: "result-list", - role: role, + role, "aria-live": "polite", }, items.map(this.renderListItem) diff --git a/devtools/client/debugger/src/components/shared/SmartGap.js b/devtools/client/debugger/src/components/shared/SmartGap.js index d76d018987..5810aea6ea 100644 --- a/devtools/client/debugger/src/components/shared/SmartGap.js +++ b/devtools/client/debugger/src/components/shared/SmartGap.js @@ -109,7 +109,6 @@ function getSmartGapDimensions( export default function SmartGap({ token, preview, - type, gapHeight, coords, offset, diff --git a/devtools/client/debugger/src/components/shared/tests/Popover.spec.js b/devtools/client/debugger/src/components/shared/tests/Popover.spec.js index 7150f4afe8..0febe5dcd5 100644 --- a/devtools/client/debugger/src/components/shared/tests/Popover.spec.js +++ b/devtools/client/debugger/src/components/shared/tests/Popover.spec.js @@ -53,10 +53,10 @@ describe("Popover", () => { React.createElement( Popover, { - onMouseLeave: onMouseLeave, - onKeyDown: onKeyDown, - editorRef: editorRef, - targetPosition: targetPosition, + onMouseLeave, + onKeyDown, + editorRef, + targetPosition, mouseout: () => {}, target: targetRef, }, @@ -69,10 +69,10 @@ describe("Popover", () => { Popover, { type: "tooltip", - onMouseLeave: onMouseLeave, - onKeyDown: onKeyDown, - editorRef: editorRef, - targetPosition: targetPosition, + onMouseLeave, + onKeyDown, + editorRef, + targetPosition, mouseout: () => {}, target: targetRef, }, @@ -94,10 +94,10 @@ describe("Popover", () => { React.createElement( Popover, { - onMouseLeave: onMouseLeave, - onKeyDown: onKeyDown, - editorRef: editorRef, - targetPosition: targetPosition, + onMouseLeave, + onKeyDown, + editorRef, + targetPosition, mouseout: () => {}, target: targetRef, }, @@ -113,10 +113,10 @@ describe("Popover", () => { Popover, { type: "tooltip", - onMouseLeave: onMouseLeave, - onKeyDown: onKeyDown, - editorRef: editorRef, - targetPosition: targetPosition, + onMouseLeave, + onKeyDown, + editorRef, + targetPosition, mouseout: () => {}, target: targetRef, }, @@ -153,8 +153,8 @@ describe("Popover", () => { Popover, { type: "tooltip", - onMouseLeave: onMouseLeave, - onKeyDown: onKeyDown, + onMouseLeave, + onKeyDown, editorRef: editor, targetPosition: target, mouseout: () => {}, @@ -195,8 +195,8 @@ describe("Popover", () => { Popover, { type: "tooltip", - onMouseLeave: onMouseLeave, - onKeyDown: onKeyDown, + onMouseLeave, + onKeyDown, editorRef: editor, targetPosition: target, mouseout: () => {}, diff --git a/devtools/client/debugger/src/components/shared/tests/SearchInput.spec.js b/devtools/client/debugger/src/components/shared/tests/SearchInput.spec.js index c4c3990771..d7e1e5805c 100644 --- a/devtools/client/debugger/src/components/shared/tests/SearchInput.spec.js +++ b/devtools/client/debugger/src/components/shared/tests/SearchInput.spec.js @@ -17,7 +17,7 @@ describe("SearchInput", () => { }); const wrapper = shallow( React.createElement(SearchInput, { - store: store, + store, query: "", count: 5, placeholder: "A placeholder", diff --git a/devtools/client/debugger/src/components/shared/tests/__snapshots__/Popover.spec.js.snap b/devtools/client/debugger/src/components/shared/tests/__snapshots__/Popover.spec.js.snap index 1c3589a6f8..6379668d6e 100644 --- a/devtools/client/debugger/src/components/shared/tests/__snapshots__/Popover.spec.js.snap +++ b/devtools/client/debugger/src/components/shared/tests/__snapshots__/Popover.spec.js.snap @@ -105,7 +105,6 @@ exports[`Popover mount popover 1`] = ` "getBoundingClientRect": [Function], } } - type="popover" > <svg style={ @@ -234,7 +233,6 @@ exports[`Popover mount tooltip 1`] = ` "getBoundingClientRect": [Function], } } - type="tooltip" > <svg style={ @@ -359,7 +357,6 @@ exports[`Popover render (tooltip) 1`] = ` "getBoundingClientRect": [Function], } } - type="tooltip" > <svg style={ @@ -504,7 +501,6 @@ exports[`Popover render 1`] = ` "getBoundingClientRect": [Function], } } - type="popover" > <svg style={ diff --git a/devtools/client/debugger/src/components/test/QuickOpenModal.spec.js b/devtools/client/debugger/src/components/test/QuickOpenModal.spec.js index 74bc7c75bc..2700960c37 100644 --- a/devtools/client/debugger/src/components/test/QuickOpenModal.spec.js +++ b/devtools/client/debugger/src/components/test/QuickOpenModal.spec.js @@ -130,6 +130,7 @@ describe("QuickOpenModal", () => { displayedSources: [ { url: "mozilla.com", + shortName: "mozilla.com", displayURL: getDisplayURL("mozilla.com"), }, ], @@ -147,6 +148,7 @@ describe("QuickOpenModal", () => { value: "mozilla.com", source: { url: "mozilla.com", + shortName: "mozilla.com", displayURL: getDisplayURL("mozilla.com"), }, }, diff --git a/devtools/client/debugger/src/main.js b/devtools/client/debugger/src/main.js index 83a6c1e6fc..ec734a89d0 100644 --- a/devtools/client/debugger/src/main.js +++ b/devtools/client/debugger/src/main.js @@ -66,7 +66,7 @@ function setPauseOnExceptions() { ); } -async function loadInitialState(commands, toolbox) { +async function loadInitialState() { const pendingBreakpoints = sanitizeBreakpoints( await asyncStore.pendingBreakpoints ); @@ -103,7 +103,7 @@ export async function bootstrap({ // record events. setToolboxTelemetry(panel.toolbox.telemetry); - const initialState = await loadInitialState(commands, panel.toolbox); + const initialState = await loadInitialState(); const workers = bootstrapWorkers(panelWorkers); const { store, actions, selectors } = bootstrapStore( diff --git a/devtools/client/debugger/src/reducers/sources-tree.js b/devtools/client/debugger/src/reducers/sources-tree.js index 0f0e8dadb3..ee8a8d0ca0 100644 --- a/devtools/client/debugger/src/reducers/sources-tree.js +++ b/devtools/client/debugger/src/reducers/sources-tree.js @@ -25,6 +25,11 @@ const IGNORED_EXTENSIONS = ["css", "svg", "png"]; import { isPretty, getRawSourceURL } from "../utils/source"; import { prefs } from "../utils/prefs"; +const lazy = {}; +ChromeUtils.defineESModuleGetters(lazy, { + BinarySearch: "resource://gre/modules/BinarySearch.sys.mjs", +}); + export function initialSourcesTreeState() { return { // List of all Thread Tree Items. @@ -224,8 +229,10 @@ function addThread(state, thread) { // (this is also used by sortThreadItems to sort the thread as a Tree in the Browser Toolbox) threadItem.thread = thread; - // We have to re-sort all threads because of the new `thread` attribute on current thread item - state.threadItems.sort(sortThreadItems); + // We have to remove and re-insert the thread as its order will be based on the newly set `thread` attribute + state.threadItems = [...state.threadItems]; + state.threadItems.splice(state.threadItems.indexOf(threadItem), 1); + addSortedItem(state.threadItems, threadItem, sortThreadItems); } } @@ -303,13 +310,12 @@ function isSourceVisibleInSourceTree( * The already sorted into which a value should be added. * @param {any} newValue * The value to add in the array while keeping the array sorted. - * @param {Function} sortFunction + * @param {Function} comparator * A function to compare two array values and their ordering. * Follow same behavior as Array sorting function. */ -function addSortedItem(array, newValue, sortFunction) { - let index = array.findIndex(value => sortFunction(value, newValue) === 1); - index = index >= 0 ? index : array.length; +function addSortedItem(array, newValue, comparator) { + const index = lazy.BinarySearch.insertionIndexOf(comparator, array, newValue); array.splice(index, 0, newValue); } @@ -396,12 +402,12 @@ function sortItems(a, b) { return -1; } else if (b.type == "directory" && a.type == "source") { return 1; + } else if (a.type == "group" && b.type == "group") { + return a.groupName.localeCompare(b.groupName); } else if (a.type == "directory" && b.type == "directory") { return a.path.localeCompare(b.path); } else if (a.type == "source" && b.type == "source") { - return a.source.displayURL.filename.localeCompare( - b.source.displayURL.filename - ); + return a.source.longName.localeCompare(b.source.longName); } return 0; } @@ -447,7 +453,7 @@ function sortThreadItems(a, b) { if (a.thread.processID > b.thread.processID) { return 1; } else if (a.thread.processID < b.thread.processID) { - return 0; + return -1; } // Order the frame targets and the worker targets by their target name diff --git a/devtools/client/debugger/src/reducers/sources.js b/devtools/client/debugger/src/reducers/sources.js index 76160b75f2..6d90fd5c91 100644 --- a/devtools/client/debugger/src/reducers/sources.js +++ b/devtools/client/debugger/src/reducers/sources.js @@ -182,6 +182,19 @@ function update(state = initialSourcesState(), action) { }; } + case "SET_DEFAULT_SELECTED_LOCATION": { + if ( + state.shouldSelectOriginalLocation == + action.shouldSelectOriginalLocation + ) { + return state; + } + return { + ...state, + shouldSelectOriginalLocation: action.shouldSelectOriginalLocation, + }; + } + case "SET_PENDING_SELECTED_LOCATION": { const pendingSelectedLocation = { url: action.url, diff --git a/devtools/client/debugger/src/reducers/ui.js b/devtools/client/debugger/src/reducers/ui.js index 7f37d2f54f..3544b3aa5c 100644 --- a/devtools/client/debugger/src/reducers/ui.js +++ b/devtools/client/debugger/src/reducers/ui.js @@ -63,6 +63,7 @@ export const initialUIState = () => ({ }, projectSearchQuery: "", hideIgnoredSources: prefs.hideIgnoredSources, + sourceMapsEnabled: prefs.clientSourceMapsEnabled, sourceMapIgnoreListEnabled: prefs.sourceMapIgnoreListEnabled, }); @@ -93,7 +94,7 @@ function update(state = initialUIState(), action) { case "TOGGLE_SOURCE_MAPS_ENABLED": { prefs.clientSourceMapsEnabled = action.value; - return { ...state }; + return { ...state, sourceMapsEnabled: action.value }; } case "SET_ORIENTATION": { diff --git a/devtools/client/debugger/src/selectors/breakpointSources.js b/devtools/client/debugger/src/selectors/breakpointSources.js index a0daedae21..4867ade82c 100644 --- a/devtools/client/debugger/src/selectors/breakpointSources.js +++ b/devtools/client/debugger/src/selectors/breakpointSources.js @@ -5,7 +5,6 @@ import { createSelector } from "devtools/client/shared/vendor/reselect"; import { getSelectedSource } from "./sources"; import { getBreakpointsList } from "./breakpoints"; -import { getFilename } from "../utils/source"; import { getSelectedLocation } from "../utils/selected-location"; // Returns a list of sources with their related breakpoints: @@ -37,16 +36,15 @@ export const getBreakpointSources = createSelector( sources.set(source, { source, breakpoints: [breakpoint], - filename: getFilename(source), }); } else { sources.get(source).breakpoints.push(breakpoint); } } - // Returns an array of breakpoints info per source, sorted by source's filename + // Returns an array of breakpoints info per source, sorted by source's displayed name return [...sources.values()].sort((a, b) => - a.filename.localeCompare(b.filename) + a.source.shortName.localeCompare(b.source.shortName) ); } ); diff --git a/devtools/client/debugger/src/selectors/sources.js b/devtools/client/debugger/src/selectors/sources.js index 938eae9fe2..6a67cf1a32 100644 --- a/devtools/client/debugger/src/selectors/sources.js +++ b/devtools/client/debugger/src/selectors/sources.js @@ -163,6 +163,16 @@ export function getSelectedMappedSource(state) { return mappedSource || null; } +/** + * Helps knowing if we are still computing the mapped location for the currently selected source. + */ +export function isSelectedMappedSourceLoading(state) { + const { selectedOriginalLocation } = state.sources; + // This `selectedOriginalLocation` attribute is set to UNDEFINED_LOCATION when selecting a new source attribute + // and later on, when the source map is processed, it will switch to either a valid location object, or NO_LOCATION if no valid one if found. + return selectedOriginalLocation === UNDEFINED_LOCATION; +} + export const getSelectedSource = createSelector( getSelectedLocation, selectedLocation => { diff --git a/devtools/client/debugger/src/selectors/test/__snapshots__/visibleColumnBreakpoints.spec.js.snap b/devtools/client/debugger/src/selectors/test/__snapshots__/visibleColumnBreakpoints.spec.js.snap index e4b18538cf..04bc12bbec 100644 --- a/devtools/client/debugger/src/selectors/test/__snapshots__/visibleColumnBreakpoints.spec.js.snap +++ b/devtools/client/debugger/src/selectors/test/__snapshots__/visibleColumnBreakpoints.spec.js.snap @@ -22,6 +22,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -44,6 +46,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -83,6 +87,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -105,6 +111,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -152,6 +160,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -174,6 +184,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -221,6 +233,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, @@ -243,6 +257,8 @@ Array [ "isOriginal": false, "isPrettyPrinted": false, "isWasm": false, + "longName": "url", + "shortName": "url", "thread": "FakeThread", "url": "url", }, diff --git a/devtools/client/debugger/src/selectors/ui.js b/devtools/client/debugger/src/selectors/ui.js index 4780b5e051..0dc97bed1b 100644 --- a/devtools/client/debugger/src/selectors/ui.js +++ b/devtools/client/debugger/src/selectors/ui.js @@ -115,3 +115,7 @@ export function getHideIgnoredSources(state) { export function isSourceMapIgnoreListEnabled(state) { return state.ui.sourceMapIgnoreListEnabled; } + +export function areSourceMapsEnabled(state) { + return state.ui.sourceMapsEnabled; +} diff --git a/devtools/client/debugger/src/utils/bootstrap.js b/devtools/client/debugger/src/utils/bootstrap.js index e8d6de2cf0..e0ee6c35be 100644 --- a/devtools/client/debugger/src/utils/bootstrap.js +++ b/devtools/client/debugger/src/utils/bootstrap.js @@ -42,7 +42,7 @@ export function bootstrapStore(client, workers, panel, initialState) { const createStore = configureStore({ log: prefs.logging || flags.testing, timing: debugJsModules, - makeThunkArgs: (args, state) => { + makeThunkArgs: args => { return { ...args, client, ...workers, panel }; }, }); diff --git a/devtools/client/debugger/src/utils/editor/create-editor.js b/devtools/client/debugger/src/utils/editor/create-editor.js index 6bb280fc4d..74b41ff78b 100644 --- a/devtools/client/debugger/src/utils/editor/create-editor.js +++ b/devtools/client/debugger/src/utils/editor/create-editor.js @@ -5,7 +5,7 @@ import SourceEditor from "devtools/client/shared/sourceeditor/editor"; import { features, prefs } from "../prefs"; -export function createEditor() { +export function createEditor(useCm6 = false) { const gutters = ["breakpoints", "hit-markers", "CodeMirror-linenumbers"]; if (features.codeFolding) { @@ -13,7 +13,8 @@ export function createEditor() { } return new SourceEditor({ - mode: "javascript", + mode: SourceEditor.modes.js, + cm6: useCm6, foldGutter: features.codeFolding, enableCodeFolding: features.codeFolding, readOnly: true, diff --git a/devtools/client/debugger/src/utils/editor/index.js b/devtools/client/debugger/src/utils/editor/index.js index 1adc73b4f8..d12e2f29f1 100644 --- a/devtools/client/debugger/src/utils/editor/index.js +++ b/devtools/client/debugger/src/utils/editor/index.js @@ -14,12 +14,12 @@ import { createLocation } from "../location"; let editor; -export function getEditor() { +export function getEditor(useCm6) { if (editor) { return editor; } - editor = createEditor(); + editor = createEditor(useCm6); return editor; } @@ -27,6 +27,16 @@ export function removeEditor() { editor = null; } +/** + * Update line wrapping for the codemirror editor. + */ +export function updateEditorLineWrapping(value) { + if (!editor) { + return; + } + editor.setLineWrapping(value); +} + function getCodeMirror() { return editor && editor.hasCodeMirror ? editor.codeMirror : null; } diff --git a/devtools/client/debugger/src/utils/editor/source-documents.js b/devtools/client/debugger/src/utils/editor/source-documents.js index 2ddb0b1965..53ee4f2f35 100644 --- a/devtools/client/debugger/src/utils/editor/source-documents.js +++ b/devtools/client/debugger/src/utils/editor/source-documents.js @@ -35,7 +35,7 @@ export function clearDocumentsForSources(sources) { } } -function resetLineNumberFormat(editor) { +export function resetLineNumberFormat(editor) { const cm = editor.codeMirror; cm.setOption("lineNumberFormatter", number => number); resizeBreakpointGutter(cm); @@ -54,59 +54,6 @@ function updateLineNumberFormat(editor, sourceId) { resizeToggleButton(cm); } -export function updateDocument(editor, source) { - if (!source) { - return; - } - - const sourceId = source.id; - const doc = getDocument(sourceId) || editor.createDocument(); - editor.replaceDocument(doc); - - updateLineNumberFormat(editor, sourceId); -} - -/* used to apply the context menu wrap line option change to all the docs */ -export function updateDocuments(updater) { - for (const doc of sourceDocs.values()) { - if (doc.cm == null) { - continue; - } else { - updater(doc); - } - } -} - -export function clearEditor(editor) { - const doc = editor.createDocument("", { name: "text" }); - editor.replaceDocument(doc); - resetLineNumberFormat(editor); -} - -export function showLoading(editor) { - // Create the "loading message" document only once - let doc = getDocument("loading"); - if (!doc) { - doc = editor.createDocument(L10N.getStr("loadingText"), { name: "text" }); - setDocument("loading", doc); - } - // `createDocument` won't be used right away in the editor, we still need to - // explicitely update it - editor.replaceDocument(doc); -} - -export function showErrorMessage(editor, msg) { - let error; - if (msg.includes("WebAssembly binary source is not available")) { - error = L10N.getStr("wasmIsNotAvailable"); - } else { - error = L10N.getFormatStr("errorLoadingText3", msg); - } - const doc = editor.createDocument(error, { name: "text" }); - editor.replaceDocument(doc); - resetLineNumberFormat(editor); -} - const contentTypeModeMap = new Map([ ["text/javascript", { name: "javascript" }], ["text/typescript", { name: "javascript", typescript: true }], diff --git a/devtools/client/debugger/src/utils/editor/source-search.js b/devtools/client/debugger/src/utils/editor/source-search.js index 92097377ba..2316cd2ccb 100644 --- a/devtools/client/debugger/src/utils/editor/source-search.js +++ b/devtools/client/debugger/src/utils/editor/source-search.js @@ -27,7 +27,7 @@ function SearchState() { * @memberof utils/source-search * @static */ -function getSearchState(cm, query) { +function getSearchState(cm) { const state = cm.state.search || (cm.state.search = new SearchState()); return state; } @@ -55,7 +55,7 @@ function searchOverlay(query, modifiers) { }); return { - token: function (stream, state) { + token(stream) { // set the last index to be the current stream position // this acts as an offset regexQuery.lastIndex = stream.pos; @@ -141,11 +141,11 @@ function doSearch( return cm.operation(function () { if (!query || isWhitespace(query)) { - clearSearch(cm, query); + clearSearch(cm); return null; } - const state = getSearchState(cm, query); + const state = getSearchState(cm); const isNewQuery = state.query !== query; state.query = query; @@ -179,7 +179,7 @@ export function searchSourceForHighlight( } cm.operation(function () { - const state = getSearchState(cm, query); + const state = getSearchState(cm); const isNewQuery = state.query !== query; state.query = query; @@ -207,7 +207,7 @@ function searchNext(ctx, rev, query, newQuery, modifiers) { const { cm } = ctx; let nextMatch; cm.operation(function () { - const state = getSearchState(cm, query); + const state = getSearchState(cm); const pos = getCursorPos(newQuery, rev, state); if (!state.query) { @@ -261,8 +261,8 @@ function findNextOnLine(ctx, rev, query, newQuery, modifiers, line, ch) { * @memberof utils/source-search * @static */ -export function removeOverlay(ctx, query) { - const state = getSearchState(ctx.cm, query); +export function removeOverlay(ctx) { + const state = getSearchState(ctx.cm); ctx.cm.removeOverlay(state.overlay); const { line, ch } = ctx.cm.getCursor(); ctx.cm.doc.setSelection({ line, ch }, { line, ch }, { scroll: false }); @@ -274,8 +274,8 @@ export function removeOverlay(ctx, query) { * @memberof utils/source-search * @static */ -export function clearSearch(cm, query) { - const state = getSearchState(cm, query); +export function clearSearch(cm) { + const state = getSearchState(cm); state.results = []; @@ -293,7 +293,7 @@ export function clearSearch(cm, query) { * @static */ export function find(ctx, query, keepSelection, modifiers, focusFirstResult) { - clearSearch(ctx.cm, query); + clearSearch(ctx.cm); return doSearch( ctx, false, diff --git a/devtools/client/debugger/src/utils/editor/tests/__snapshots__/create-editor.spec.js.snap b/devtools/client/debugger/src/utils/editor/tests/__snapshots__/create-editor.spec.js.snap Binary files differindex 843647731b..5c47ed94c7 100644 --- a/devtools/client/debugger/src/utils/editor/tests/__snapshots__/create-editor.spec.js.snap +++ b/devtools/client/debugger/src/utils/editor/tests/__snapshots__/create-editor.spec.js.snap diff --git a/devtools/client/debugger/src/utils/moz.build b/devtools/client/debugger/src/utils/moz.build index 8deb8e18db..742f96e060 100644 --- a/devtools/client/debugger/src/utils/moz.build +++ b/devtools/client/debugger/src/utils/moz.build @@ -42,7 +42,6 @@ CompiledModules( "source-queue.js", "source.js", "tabs.js", - "task.js", "telemetry.js", "text.js", "ui.js", diff --git a/devtools/client/debugger/src/utils/quick-open.js b/devtools/client/debugger/src/utils/quick-open.js index e2624559bc..f51d1c6ac7 100644 --- a/devtools/client/debugger/src/utils/quick-open.js +++ b/devtools/client/debugger/src/utils/quick-open.js @@ -3,12 +3,7 @@ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ import { endTruncateStr } from "./utils"; -import { - getFilename, - getSourceClassnames, - getSourceQueryString, - getRelativeUrl, -} from "./source"; +import { getSourceClassnames, getRelativeUrl } from "./source"; export const MODIFIERS = { "@": "functions", @@ -62,16 +57,15 @@ export function formatSourceForList( isBlackBoxed, projectDirectoryRoot ) { - const title = getFilename(source); const relativeUrlWithQuery = `${getRelativeUrl( source, projectDirectoryRoot - )}${getSourceQueryString(source) || ""}`; + )}${source.displayURL.search || ""}`; const subtitle = endTruncateStr(relativeUrlWithQuery, 100); const value = relativeUrlWithQuery; return { value, - title, + title: source.shortName, subtitle, icon: hasTabOpened ? "tab result-item-icon" diff --git a/devtools/client/debugger/src/utils/source.js b/devtools/client/debugger/src/utils/source.js index 31920453eb..91a02778e2 100644 --- a/devtools/client/debugger/src/utils/source.js +++ b/devtools/client/debugger/src/utils/source.js @@ -17,7 +17,6 @@ const { import { getRelativePath } from "../utils/sources-tree/utils"; import { endTruncateStr } from "./utils"; import { truncateMiddleText } from "../utils/text"; -import { parse as parseURL } from "../utils/url"; import { memoizeLast } from "../utils/memoizeLast"; import { renderWasmText } from "./wasm"; import { toEditorLine } from "./editor/index"; @@ -214,33 +213,10 @@ export function getFormattedSourceId(id) { } /** - * Gets a readable filename from a source URL for display purposes. - * If the source does not have a URL, the source ID will be returned instead. - * - * @memberof utils/source - * @static - */ -export function getFilename( - source, - rawSourceURL = getRawSourceURL(source.url) -) { - const { id } = source; - if (!rawSourceURL) { - return getFormattedSourceId(id); - } - - const { filename } = source.displayURL; - return getRawSourceURL(filename); -} - -/** - * Provides a middle-trunated filename - * - * @memberof utils/source - * @static + * Provides a middle-truncated filename displayed in Tab titles */ -export function getTruncatedFileName(source, querystring = "", length = 30) { - return truncateMiddleText(`${getFilename(source)}${querystring}`, length); +export function getTruncatedFileName(source) { + return truncateMiddleText(source.longName, 30); } /* Gets path for files with same filename for editor tabs, breakpoints, etc. @@ -252,15 +228,13 @@ export function getTruncatedFileName(source, querystring = "", length = 30) { export function getDisplayPath(mySource, sources) { const rawSourceURL = getRawSourceURL(mySource.url); - const filename = getFilename(mySource, rawSourceURL); + const filename = mySource.shortName; // Find sources that have the same filename, but different paths // as the original source const similarSources = sources.filter(source => { const rawSource = getRawSourceURL(source.url); - return ( - rawSourceURL != rawSource && filename == getFilename(source, rawSource) - ); + return rawSourceURL != rawSource && filename == source.shortName; }); if (!similarSources.length) { @@ -314,16 +288,6 @@ export function getFileURL(source, truncate = true) { return resolveFileURL(url, getUnicodeUrl, truncate); } -export function getSourcePath(url) { - if (!url) { - return ""; - } - - const { path, href } = parseURL(url); - // for URLs like "about:home" the path is null so we pass the full href - return path || href; -} - /** * Returns amount of lines in the source. If source is a WebAssembly binary, * the function returns amount of bytes. @@ -345,10 +309,6 @@ export function getSourceLineCount(content) { return count + 1; } -export function isInlineScript(source) { - return source.introductionType === "scriptElement"; -} - function getNthLine(str, lineNum) { let startIndex = -1; @@ -454,51 +414,6 @@ export function getRelativeUrl(source, root) { return url.slice(url.indexOf(root) + root.length + 1); } -/** - * source.url doesn't include thread actor ID, so before calling underRoot(), the thread actor ID - * must be removed from the root, which this function handles. - * @param {string} root The root url to be cleaned - * @param {Set<Thread>} threads The list of threads - * @returns {string} The root url with thread actor IDs removed - */ -export function removeThreadActorId(root, threads) { - threads.forEach(thread => { - if (root.includes(thread.actor)) { - root = root.slice(thread.actor.length + 1); - } - }); - return root; -} - -/** - * Checks if the source is descendant of the root identified by the - * root url specified. The root might likely be projectDirectoryRoot which - * is a defined by a pref that allows users restrict the source tree to - * a subset of sources. - * - * @param {Object} source - * The source object - * @param {String} rootUrlWithoutThreadActor - * The url for the root node, without the thread actor ID. This can be obtained - * by calling removeThreadActorId() - */ -export function isDescendantOfRoot(source, rootUrlWithoutThreadActor) { - if (source.url && source.url.includes("chrome://")) { - const { group, path } = source.displayURL; - return (group + path).includes(rootUrlWithoutThreadActor); - } - - return !!source.url && source.url.includes(rootUrlWithoutThreadActor); -} - -export function getSourceQueryString(source) { - if (!source) { - return ""; - } - - return parseURL(getRawSourceURL(source.url)).search; -} - export function isUrlExtension(url) { return url.includes("moz-extension:") || url.includes("chrome-extension"); } diff --git a/devtools/client/debugger/src/utils/sources-tree/getURL.js b/devtools/client/debugger/src/utils/sources-tree/getURL.js index c01fce5f23..5c9e7db6e5 100644 --- a/devtools/client/debugger/src/utils/sources-tree/getURL.js +++ b/devtools/client/debugger/src/utils/sources-tree/getURL.js @@ -56,6 +56,9 @@ const def = { * This is augmented with custom properties like: * - `group`, which is mostly the host of the source's URL. * This is used to sort sources in the Source tree. + * - `filename` which may not be quite matching the URL. + * When files are loaded from "/", they won't have a real name, + * but instead this will report "(index)". * - `fileExtension`, lowercased file extension of the source * (if any extension is available) * - `path` and `pathname` have some special behavior. @@ -66,8 +69,14 @@ export function getDisplayURL(url, extensionName = null) { return def; } - const { pathname, search, protocol, host } = parse(url); - const filename = getUnicodeUrlPath(getFilenameFromPath(pathname)); + let { pathname, search, protocol, host } = parse(url); + + // Decode encoded characters early so that all other code rely on decoded strings + pathname = getUnicodeUrlPath(pathname); + search = getUnicodeUrlPath(search); + host = getUnicodeHostname(host); + + const filename = getFilenameFromPath(pathname); switch (protocol) { case "javascript:": @@ -121,7 +130,7 @@ export function getDisplayURL(url, extensionName = null) { search, filename, fileExtension: getFileExtension("/"), - group: url, + group: getUnicodeUrlPath(url), }; case "data:": @@ -165,7 +174,7 @@ export function getDisplayURL(url, extensionName = null) { search, filename, fileExtension: getFileExtension(pathname), - group: getUnicodeHostname(host), + group: host, }; } diff --git a/devtools/client/debugger/src/utils/sources-tree/utils.js b/devtools/client/debugger/src/utils/sources-tree/utils.js index 0a2f41752b..45eba2d817 100644 --- a/devtools/client/debugger/src/utils/sources-tree/utils.js +++ b/devtools/client/debugger/src/utils/sources-tree/utils.js @@ -28,17 +28,3 @@ export function getRelativePath(url) { } return ""; } - -/** - * - * @param {String} name: Name (e.g. computed in SourcesTreeItem renderItemName), - * which might include URI search. - * @returns {String} result of `decodedURI(name)`, or name if it `name` is malformed. - */ -export function safeDecodeItemName(name) { - try { - return decodeURI(name); - } catch (e) { - return name; - } -} diff --git a/devtools/client/debugger/src/utils/task.js b/devtools/client/debugger/src/utils/task.js deleted file mode 100644 index 25663fdd16..0000000000 --- a/devtools/client/debugger/src/utils/task.js +++ /dev/null @@ -1,44 +0,0 @@ -/* 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 object provides the public module functions. - */ -export const Task = { - // XXX: Not sure if this works in all cases... - async: function (task) { - return function () { - return Task.spawn(task, this, arguments); - }; - }, - - /** - * Creates and starts a new task. - * @param task A generator function - * @return A promise, resolved when the task terminates - */ - spawn: function (task, scope, args) { - return new Promise(function (resolve, reject) { - const iterator = task.apply(scope, args); - - const callNext = lastValue => { - const iteration = iterator.next(lastValue); - Promise.resolve(iteration.value) - .then(value => { - if (iteration.done) { - resolve(value); - } else { - callNext(value); - } - }) - .catch(error => { - reject(error); - iterator.throw(error); - }); - }; - - callNext(undefined); - }); - }, -}; diff --git a/devtools/client/debugger/src/utils/test-head.js b/devtools/client/debugger/src/utils/test-head.js index c21f408b61..1021849d02 100644 --- a/devtools/client/debugger/src/utils/test-head.js +++ b/devtools/client/debugger/src/utils/test-head.js @@ -101,10 +101,11 @@ function makeFrame({ id, sourceId, thread }, opts = {}) { }; } -function createSourceObject(filename, props = {}) { +function createSourceObject(filename) { return { id: filename, url: makeSourceURL(filename), + shortName: filename, isPrettyPrinted: false, isExtension: false, isOriginal: filename.includes("originalSource"), diff --git a/devtools/client/debugger/src/utils/test-mockup.js b/devtools/client/debugger/src/utils/test-mockup.js index 521872b7cb..8224050f6a 100644 --- a/devtools/client/debugger/src/utils/test-mockup.js +++ b/devtools/client/debugger/src/utils/test-mockup.js @@ -20,6 +20,8 @@ function makeMockSource(url = "url", id = "source", thread = "FakeThread") { return { id, url, + shortName: getDisplayURL(url).filename, + longName: getDisplayURL(url).filename + getDisplayURL(url).search, displayURL: getDisplayURL(url), thread, isPrettyPrinted: false, diff --git a/devtools/client/debugger/src/utils/tests/source.spec.js b/devtools/client/debugger/src/utils/tests/source.spec.js index 484c8ce570..6542ee2c0d 100644 --- a/devtools/client/debugger/src/utils/tests/source.spec.js +++ b/devtools/client/debugger/src/utils/tests/source.spec.js @@ -3,14 +3,11 @@ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ import { - getFilename, getTruncatedFileName, getFileURL, getDisplayPath, getSourceLineCount, isJavaScript, - isDescendantOfRoot, - removeThreadActorId, isUrlExtension, getLineText, } from "../source.js"; @@ -20,7 +17,6 @@ import { makeMockSourceWithContent, makeMockSourceAndContent, makeMockWasmSourceWithContent, - makeMockThread, makeFullfilledMockSourceContent, } from "../test-mockup"; import { isFulfilled } from "../async-value.js"; @@ -29,66 +25,20 @@ describe("sources", () => { const unicode = "\u6e2c"; const encodedUnicode = encodeURIComponent(unicode); - describe("getFilename", () => { - it("should give us a default of (index)", () => { - expect( - getFilename(makeMockSource("http://localhost.com:7999/increment/")) - ).toBe("(index)"); - }); - it("should give us the filename", () => { - expect( - getFilename( - makeMockSource("http://localhost.com:7999/increment/hello.html") - ) - ).toBe("hello.html"); - }); - it("should give us the readable Unicode filename if encoded", () => { - expect( - getFilename( - makeMockSource( - `http://localhost.com:7999/increment/${encodedUnicode}.html` - ) - ) - ).toBe(`${unicode}.html`); - }); - it("should give us the filename excluding the query strings", () => { - expect( - getFilename( - makeMockSource( - "http://localhost.com:7999/increment/hello.html?query_strings" - ) - ) - ).toBe("hello.html"); - }); - it("should give us the proper filename for pretty files", () => { - expect( - getFilename( - makeMockSource( - "http://localhost.com:7999/increment/hello.html:formatted" - ) - ) - ).toBe("hello.html"); - }); - }); - describe("getTruncatedFileName", () => { it("should truncate the file name when it is more than 30 chars", () => { expect( getTruncatedFileName( makeMockSource( "really-really-really-really-really-really-long-name.html" - ), - "", - 30 + ) ) ).toBe("really-really…long-name.html"); }); it("should first decode the filename and then truncate it", () => { expect( getTruncatedFileName( - makeMockSource(`${encodedUnicode.repeat(30)}.html`), - "", - 30 + makeMockSource(`${encodedUnicode.repeat(30)}.html`) ) ).toBe("測測測測測測測測測測測測測…測測測測測測測測測.html"); }); @@ -274,42 +224,6 @@ describe("sources", () => { }); }); - describe("isDescendantOfRoot", () => { - const threads = [ - makeMockThread({ actor: "server0.conn1.child1/thread19" }), - ]; - - it("should detect normal source urls", () => { - const source = makeMockSource( - "resource://activity-stream/vendor/react.js" - ); - const rootWithoutThreadActor = removeThreadActorId( - "resource://activity-stream", - threads - ); - expect(isDescendantOfRoot(source, rootWithoutThreadActor)).toBe(true); - }); - - it("should detect source urls under chrome:// as root", () => { - const source = makeMockSource( - "chrome://browser/content/contentSearchUI.js" - ); - const rootWithoutThreadActor = removeThreadActorId("chrome://", threads); - expect(isDescendantOfRoot(source, rootWithoutThreadActor)).toBe(true); - }); - - it("should detect source urls if root is a thread actor Id", () => { - const source = makeMockSource( - "resource://activity-stream/vendor/react-dom.js" - ); - const rootWithoutThreadActor = removeThreadActorId( - "server0.conn1.child1/thread19", - threads - ); - expect(isDescendantOfRoot(source, rootWithoutThreadActor)).toBe(true); - }); - }); - describe("isUrlExtension", () => { it("should detect mozilla extension", () => { expect(isUrlExtension("moz-extension://id/js/content.js")).toBe(true); diff --git a/devtools/client/debugger/src/workers/parser/mapAwaitExpression.js b/devtools/client/debugger/src/workers/parser/mapAwaitExpression.js index ec29d6cf21..97018a129b 100644 --- a/devtools/client/debugger/src/workers/parser/mapAwaitExpression.js +++ b/devtools/client/debugger/src/workers/parser/mapAwaitExpression.js @@ -11,7 +11,7 @@ import { isTopLevel } from "./utils/helpers"; function hasTopLevelAwait(ast) { const hasAwait = hasNode( ast, - (node, ancestors, b) => t.isAwaitExpression(node) && isTopLevel(ancestors) + (node, ancestors) => t.isAwaitExpression(node) && isTopLevel(ancestors) ); return hasAwait; diff --git a/devtools/client/debugger/src/workers/parser/tests/__snapshots__/validate.spec.js.snap b/devtools/client/debugger/src/workers/parser/tests/__snapshots__/validate.spec.js.snap deleted file mode 100644 index a341538a5d..0000000000 --- a/devtools/client/debugger/src/workers/parser/tests/__snapshots__/validate.spec.js.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`has syntax error should return the error object for the invalid expression 1`] = `"SyntaxError : Missing semicolon. (1:3)"`; diff --git a/devtools/client/debugger/src/workers/parser/tests/framework.spec.js b/devtools/client/debugger/src/workers/parser/tests/framework.spec.js index d41f45b71c..fe25fbe283 100644 --- a/devtools/client/debugger/src/workers/parser/tests/framework.spec.js +++ b/devtools/client/debugger/src/workers/parser/tests/framework.spec.js @@ -8,7 +8,7 @@ import cases from "jest-in-case"; cases( "Parser.getFramework", - ({ name, file, value }) => { + () => { const source = populateOriginalSource("frameworks/plainJavascript"); const symbols = getSymbols(source.id); expect(symbols.framework).toBeNull(); diff --git a/devtools/client/debugger/src/workers/parser/tests/getSymbols.spec.js b/devtools/client/debugger/src/workers/parser/tests/getSymbols.spec.js index 723eef1fd9..0c5306d423 100644 --- a/devtools/client/debugger/src/workers/parser/tests/getSymbols.spec.js +++ b/devtools/client/debugger/src/workers/parser/tests/getSymbols.spec.js @@ -9,7 +9,7 @@ import cases from "jest-in-case"; cases( "Parser.getSymbols", - ({ name, file, original, type }) => { + ({ file, original, type }) => { const source = original ? populateOriginalSource(file, type) : populateSource(file, type); diff --git a/devtools/client/debugger/src/workers/parser/tests/mapBindings.spec.js b/devtools/client/debugger/src/workers/parser/tests/mapBindings.spec.js index 8c23ab5873..3731ac1dd5 100644 --- a/devtools/client/debugger/src/workers/parser/tests/mapBindings.spec.js +++ b/devtools/client/debugger/src/workers/parser/tests/mapBindings.spec.js @@ -12,7 +12,7 @@ function format(code) { return prettier.format(code, { semi: false, parser: "babel" }); } -function excludedTest({ name, expression, bindings = [] }) { +function excludedTest({ expression, bindings = [] }) { const safeExpression = mapExpressionBindings( expression, parseConsoleScript(expression), @@ -21,7 +21,7 @@ function excludedTest({ name, expression, bindings = [] }) { expect(format(safeExpression)).toEqual(format(expression)); } -function includedTest({ name, expression, newExpression, bindings }) { +function includedTest({ expression, newExpression, bindings }) { const safeExpression = mapExpressionBindings( expression, parseConsoleScript(expression), |