diff options
Diffstat (limited to 'devtools/client/debugger/src/reducers/pending-breakpoints.js')
-rw-r--r-- | devtools/client/debugger/src/reducers/pending-breakpoints.js | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/devtools/client/debugger/src/reducers/pending-breakpoints.js b/devtools/client/debugger/src/reducers/pending-breakpoints.js new file mode 100644 index 0000000000..25e9a65dd4 --- /dev/null +++ b/devtools/client/debugger/src/reducers/pending-breakpoints.js @@ -0,0 +1,135 @@ +/* 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/>. */ + +/** + * Pending breakpoints reducer. + * + * Pending breakpoints are a more lightweight version compared to regular breakpoints objects. + * They are meant to be persisted across Firefox restarts and stored into async-storage. + * This reducer data is saved into asyncStore from bootstrap.js and restored from main.js. + * + * The main difference with pending breakpoints is that we only save breakpoints + * against source with an URL as only them can be restored. (source IDs are different across reloads). + * The second difference is that we don't store the whole source object but only the source URL. + */ + +import { isPrettyURL } from "../utils/source"; +import assert from "../utils/assert"; + +function update(state = {}, action) { + switch (action.type) { + case "SET_BREAKPOINT": + if (action.status === "start") { + return setBreakpoint(state, action.breakpoint); + } + return state; + + case "REMOVE_BREAKPOINT": + if (action.status === "start") { + return removeBreakpoint(state, action.breakpoint); + } + return state; + + case "REMOVE_PENDING_BREAKPOINT": + return removePendingBreakpoint(state, action.pendingBreakpoint); + + case "CLEAR_BREAKPOINTS": { + return {}; + } + } + + return state; +} + +function shouldBreakpointBePersisted(breakpoint) { + // We only save breakpoint for source with URL. + // Source without URL can only be identified via their source actor ID + // which isn't persisted across reloads. + return !breakpoint.options.hidden && breakpoint.location.source.url; +} + +function setBreakpoint(state, breakpoint) { + if (!shouldBreakpointBePersisted(breakpoint)) { + return state; + } + + const id = makeIdFromBreakpoint(breakpoint); + const pendingBreakpoint = createPendingBreakpoint(breakpoint); + + return { ...state, [id]: pendingBreakpoint }; +} + +function removeBreakpoint(state, breakpoint) { + if (!shouldBreakpointBePersisted(breakpoint)) { + return state; + } + + const id = makeIdFromBreakpoint(breakpoint); + state = { ...state }; + + delete state[id]; + return state; +} + +function removePendingBreakpoint(state, pendingBreakpoint) { + const id = makeIdFromPendingBreakpoint(pendingBreakpoint); + state = { ...state }; + + delete state[id]; + return state; +} + +/** + * Return a unique identifier for a given breakpoint, + * using its original location, or for pretty-printed sources, + * its generated location. + * + * @param {Object} breakpoint + */ +function makeIdFromBreakpoint(breakpoint) { + const location = isPrettyURL(breakpoint.location.sourceUrl) + ? breakpoint.generatedLocation + : breakpoint.location; + + const { sourceUrl, line, column } = location; + const sourceUrlString = sourceUrl || ""; + const columnString = column || ""; + + return `${sourceUrlString}:${line}:${columnString}`; +} + +function makeIdFromPendingBreakpoint(pendingBreakpoint) { + const { sourceUrl, line, column } = pendingBreakpoint.location; + const sourceUrlString = sourceUrl || ""; + const columnString = column || ""; + + return `${sourceUrlString}:${line}:${columnString}`; +} + +/** + * Convert typical debugger frontend location (created via location.js:createLocation) + * to a more lightweight flavor of it which will be stored in async storage. + */ +function createPendingLocation(location) { + assert(location.hasOwnProperty("line"), "location must have a line"); + assert(location.hasOwnProperty("column"), "location must have a column"); + + const { sourceUrl, line, column } = location; + assert(sourceUrl !== undefined, "pending location must have a source url"); + return { sourceUrl, line, column }; +} + +/** + * Create a new pending breakpoint, which is a more lightweight version of the regular breakpoint object. + */ +function createPendingBreakpoint(bp) { + return { + options: bp.options, + disabled: bp.disabled, + location: createPendingLocation(bp.location), + generatedLocation: createPendingLocation(bp.generatedLocation), + }; +} + +export default update; |