From 59376adc139a647ad2982a2a2f5e1308212dd606 Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Fri, 19 Apr 2019 16:07:37 +0000 Subject: [PATCH] Bug 1541629 - Part 2: Add a new source-actor action/reducer root type. r=jlast Differential Revision: https://phabricator.services.mozilla.com/D27957 --HG-- extra : moz-landing-system : lando --- devtools/client/debugger/src/actions/index.js | 2 + .../client/debugger/src/actions/moz.build | 1 + .../debugger/src/actions/source-actors.js | 32 ++++ .../src/actions/types/SourceActorAction.js | 20 +++ .../debugger/src/actions/types/index.js | 2 + .../client/debugger/src/reducers/index.js | 2 + .../client/debugger/src/reducers/moz.build | 1 + .../debugger/src/reducers/source-actors.js | 160 ++++++++++++++++++ .../client/debugger/src/selectors/index.js | 5 + 9 files changed, 225 insertions(+) create mode 100644 devtools/client/debugger/src/actions/source-actors.js create mode 100644 devtools/client/debugger/src/actions/types/SourceActorAction.js create mode 100644 devtools/client/debugger/src/reducers/source-actors.js diff --git a/devtools/client/debugger/src/actions/index.js b/devtools/client/debugger/src/actions/index.js index c7a09789223f..dc36fadeec24 100644 --- a/devtools/client/debugger/src/actions/index.js +++ b/devtools/client/debugger/src/actions/index.js @@ -16,6 +16,7 @@ import * as projectTextSearch from "./project-text-search"; import * as quickOpen from "./quick-open"; import * as sourceTree from "./source-tree"; import * as sources from "./sources"; +import * as sourcesActors from "./source-actors"; import * as tabs from "./tabs"; import * as debuggee from "./debuggee"; import * as toolbox from "./toolbox"; @@ -27,6 +28,7 @@ export default { ...expressions, ...eventListeners, ...sources, + ...sourcesActors, ...tabs, ...pause, ...ui, diff --git a/devtools/client/debugger/src/actions/moz.build b/devtools/client/debugger/src/actions/moz.build index 632e95eb6245..8f1806641ab3 100644 --- a/devtools/client/debugger/src/actions/moz.build +++ b/devtools/client/debugger/src/actions/moz.build @@ -22,6 +22,7 @@ CompiledModules( 'preview.js', 'project-text-search.js', 'quick-open.js', + 'source-actors.js', 'source-tree.js', 'tabs.js', 'toolbox.js', diff --git a/devtools/client/debugger/src/actions/source-actors.js b/devtools/client/debugger/src/actions/source-actors.js new file mode 100644 index 000000000000..544529683a44 --- /dev/null +++ b/devtools/client/debugger/src/actions/source-actors.js @@ -0,0 +1,32 @@ +/* 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 . */ + +// @flow + +import type { ThunkArgs } from "./types"; +import type { SourceActor } from "../reducers/source-actors"; + +export function insertSourceActor(item: SourceActor) { + return insertSourceActors([item]); +} +export function insertSourceActors(items: Array) { + return function({ dispatch }: ThunkArgs) { + dispatch({ + type: "INSERT_SOURCE_ACTORS", + items + }); + }; +} + +export function removeSourceActor(item: SourceActor) { + return removeSourceActors([item]); +} +export function removeSourceActors(items: Array) { + return function({ dispatch }: ThunkArgs) { + dispatch({ + type: "REMOVE_SOURCE_ACTORS", + items + }); + }; +} diff --git a/devtools/client/debugger/src/actions/types/SourceActorAction.js b/devtools/client/debugger/src/actions/types/SourceActorAction.js new file mode 100644 index 000000000000..812f6b0e126d --- /dev/null +++ b/devtools/client/debugger/src/actions/types/SourceActorAction.js @@ -0,0 +1,20 @@ +/* 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 . */ + +// @flow + +import type { SourceActor } from "../../reducers/source-actors.js"; + +export type SourceActorsInsertAction = {| + type: "INSERT_SOURCE_ACTORS", + items: Array +|}; +export type SourceActorsRemoveAction = {| + type: "REMOVE_SOURCE_ACTORS", + items: Array +|}; + +export type SourceActorAction = + | SourceActorsInsertAction + | SourceActorsRemoveAction; diff --git a/devtools/client/debugger/src/actions/types/index.js b/devtools/client/debugger/src/actions/types/index.js index 5216e2fb2a78..24aa12b8e6eb 100644 --- a/devtools/client/debugger/src/actions/types/index.js +++ b/devtools/client/debugger/src/actions/types/index.js @@ -13,6 +13,7 @@ import type { SearchOperation } from "../../reducers/project-text-search"; import type { BreakpointAction } from "./BreakpointAction"; import type { SourceAction } from "./SourceAction"; +import type { SourceActorAction } from "./SourceActorAction"; import type { UIAction } from "./UIAction"; import type { PauseAction } from "./PauseAction"; import type { ASTAction } from "./ASTAction"; @@ -162,6 +163,7 @@ export type { ASTAction } from "./ASTAction"; export type Action = | AddTabAction | UpdateTabAction + | SourceActorAction | SourceAction | BreakpointAction | PauseAction diff --git a/devtools/client/debugger/src/reducers/index.js b/devtools/client/debugger/src/reducers/index.js index 30612f6fe6d9..08012d6db287 100644 --- a/devtools/client/debugger/src/reducers/index.js +++ b/devtools/client/debugger/src/reducers/index.js @@ -10,6 +10,7 @@ */ import expressions from "./expressions"; +import sourceActors from "./source-actors"; import sources from "./sources"; import tabs from "./tabs"; import breakpoints from "./breakpoints"; @@ -28,6 +29,7 @@ import eventListenerBreakpoints from "./event-listeners"; export default { expressions, + sourceActors, sources, tabs, breakpoints, diff --git a/devtools/client/debugger/src/reducers/moz.build b/devtools/client/debugger/src/reducers/moz.build index 55988991cee8..907da664d22e 100644 --- a/devtools/client/debugger/src/reducers/moz.build +++ b/devtools/client/debugger/src/reducers/moz.build @@ -20,6 +20,7 @@ CompiledModules( 'pending-breakpoints.js', 'project-text-search.js', 'quick-open.js', + 'source-actors.js', 'source-tree.js', 'sources.js', 'tabs.js', diff --git a/devtools/client/debugger/src/reducers/source-actors.js b/devtools/client/debugger/src/reducers/source-actors.js new file mode 100644 index 000000000000..3cd6952849b8 --- /dev/null +++ b/devtools/client/debugger/src/reducers/source-actors.js @@ -0,0 +1,160 @@ +/* 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 . */ + +// @flow + +import type { Action } from "../actions/types"; +import type { SourceId, ThreadId } from "../types"; +import { + createInitial, + insertResources, + removeResources, + hasResource, + getItem, + createFieldByIDGetter, + createFieldReducer, + type ResourceState, + type FieldReducer, + type FieldByIDGetter +} from "../utils/resource"; + +export opaque type SourceActorId = string; +export type SourceActor = {| + id: SourceActorId, + actor: string, + thread: ThreadId, + source: SourceId, + + isBlackBoxed: boolean, + + // The URL of the sourcemap for this source if there is one. + sourceMapURL: string | null, + + // The URL of the actor itself. If the source was from an "eval" or other + // string-based source, this will not be known. + url: string | null, + + // If this script was introduced by an eval, this will be the URL of the + // script that triggered the evaluation. + introductionUrl: string | null, + + // The debugger's Debugger.Source API provides type information for the + // cause of this source's creation. + introductionType: string | null +|}; + +type SourceActorResource = {| + item: SourceActor +|}; +export type SourceActorsState = ResourceState; +export type SourceActorOuterState = { sourceActors: SourceActorsState }; + +const initial: SourceActorsState = createInitial({ + item: {} +}); + +export default function update( + state: SourceActorsState = initial, + action: Action +): SourceActorsState { + switch (action.type) { + case "INSERT_SOURCE_ACTORS": { + const { items } = action; + state = insertResources(state, items.map(item => ({ item }))); + break; + } + case "REMOVE_SOURCE_ACTORS": { + const { items } = action; + state = removeResources(state, items); + break; + } + } + + return state; +} + +// Because we are using an opaque type for our source actor IDs, these +// functions are required to convert back and forth in order to get a string +// version of the IDs. That should be super rarely used, but it means that +// we can very easily see where we're relying on the string version of IDs. +export function stringToSourceActorId(s: string): SourceActorId { + return s; +} + +export function hasSourceActor( + state: SourceActorOuterState, + id: SourceActorId +): boolean { + return hasResource(state.sourceActors, id); +} + +export function getSourceActor( + state: SourceActorOuterState, + id: SourceActorId +): SourceActor { + return getItem(state.sourceActors, id); +} + +/** + * Get all of the source actors for a set of IDs. Caches based on the identity + * of "ids" when possible. + */ +const getSourceActorsById: FieldByIDGetter< + SourceActorResource, + "item" +> = createFieldByIDGetter("item"); +export function getSourceActors( + state: SourceActorOuterState, + ids: Array +): Array { + return getSourceActorsById(state.sourceActors, ids); +} + +const getSourcesByThreadID: FieldReducer< + SourceActorResource, + { [ThreadId]: Array } +> = createFieldReducer( + "item", + (acc, item, id) => { + acc[item.thread] = acc[item.thread] || []; + acc[item.thread].push(item); + return acc; + }, + () => ({}) +); +export function getSourceActorsForThread( + state: SourceActorOuterState, + ids: ThreadId | Array +): Array { + const sourcesByThread = getSourcesByThreadID(state.sourceActors); + + let sources = []; + for (const id of Array.isArray(ids) ? ids : [ids]) { + sources = sources.concat(sourcesByThread[id] || []); + } + return sources; +} + +const getThreadsBySourceObject: FieldReducer< + SourceActorResource, + { [SourceId]: Array } +> = createFieldReducer( + "item", + (acc, item, id) => { + let sourceThreads = acc[item.source]; + if (!sourceThreads) { + sourceThreads = []; + acc[item.source] = sourceThreads; + } + + sourceThreads.push(item.thread); + return acc; + }, + () => ({}) +); +export function getThreadsBySource( + state: SourceActorOuterState +): { [SourceId]: Array } { + return getThreadsBySourceObject(state.sourceActors); +} diff --git a/devtools/client/debugger/src/selectors/index.js b/devtools/client/debugger/src/selectors/index.js index 411b675c52ca..257a872324b2 100644 --- a/devtools/client/debugger/src/selectors/index.js +++ b/devtools/client/debugger/src/selectors/index.js @@ -18,6 +18,11 @@ export * from "../reducers/ast"; export * from "../reducers/project-text-search"; export * from "../reducers/source-tree"; +export { + getSourceActor, + getSourceActorsForThread, +} from "../reducers/source-actors"; + export { getQuickOpenEnabled, getQuickOpenQuery,