summaryrefslogtreecommitdiffstats
path: root/devtools/client/framework/actions/dom-mutation-breakpoints.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/framework/actions/dom-mutation-breakpoints.js')
-rw-r--r--devtools/client/framework/actions/dom-mutation-breakpoints.js155
1 files changed, 155 insertions, 0 deletions
diff --git a/devtools/client/framework/actions/dom-mutation-breakpoints.js b/devtools/client/framework/actions/dom-mutation-breakpoints.js
new file mode 100644
index 0000000000..1e1273d711
--- /dev/null
+++ b/devtools/client/framework/actions/dom-mutation-breakpoints.js
@@ -0,0 +1,155 @@
+/* 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/>. */
+"use strict";
+
+const { assert } = require("resource://devtools/shared/DevToolsUtils.js");
+const {
+ getDOMMutationBreakpoint,
+ getDOMMutationBreakpoints,
+} = require("resource://devtools/client/framework/reducers/dom-mutation-breakpoints.js");
+
+exports.registerWalkerListeners = registerWalkerListeners;
+function registerWalkerListeners(store, walker) {
+ walker.on("mutations", mutations => handleWalkerMutations(mutations, store));
+}
+
+/**
+ * Called when a target is destroyed. This will allow the reducer to remove breakpoints on
+ * nodeFront associated with the passed target
+ *
+ * @param {ToolboxStore} store: The toolbox redux store
+ * @param {TargetFront} targetFront
+ */
+function removeTarget(store, targetFront) {
+ store.dispatch({
+ type: "REMOVE_TARGET",
+ targetFront,
+ });
+}
+exports.removeTarget = removeTarget;
+
+function handleWalkerMutations(mutations, store) {
+ // If we got BP updates for detach/unload, we want to drop those nodes from
+ // the list of active DOM mutation breakpoints. We explicitly check these
+ // cases because BP updates could also happen due to explicitly API
+ // operations to add/remove bps.
+ const mutationItems = mutations.filter(
+ mutation => mutation.type === "mutationBreakpoint"
+ );
+ if (mutationItems.length) {
+ store.dispatch(updateBreakpointsForMutations(mutationItems));
+ }
+}
+
+exports.createDOMMutationBreakpoint = createDOMMutationBreakpoint;
+function createDOMMutationBreakpoint(nodeFront, mutationType) {
+ assert(typeof nodeFront === "object" && nodeFront);
+ assert(typeof mutationType === "string");
+
+ return async function ({ dispatch, getState }) {
+ const walker = nodeFront.walkerFront;
+
+ dispatch({
+ type: "ADD_DOM_MUTATION_BREAKPOINT",
+ nodeFront,
+ mutationType,
+ });
+
+ await walker.setMutationBreakpoints(nodeFront, {
+ [mutationType]: true,
+ });
+ };
+}
+
+exports.deleteDOMMutationBreakpoint = deleteDOMMutationBreakpoint;
+function deleteDOMMutationBreakpoint(nodeFront, mutationType) {
+ assert(typeof nodeFront === "object" && nodeFront);
+ assert(typeof mutationType === "string");
+
+ return async function ({ dispatch, getState }) {
+ const walker = nodeFront.walkerFront;
+ await walker.setMutationBreakpoints(nodeFront, {
+ [mutationType]: false,
+ });
+
+ dispatch({
+ type: "REMOVE_DOM_MUTATION_BREAKPOINT",
+ nodeFront,
+ mutationType,
+ });
+ };
+}
+
+function updateBreakpointsForMutations(mutationItems) {
+ return async function ({ dispatch, getState }) {
+ const removedNodeFronts = [];
+ const changedNodeFronts = new Set();
+
+ for (const { target: nodeFront, mutationReason } of mutationItems) {
+ switch (mutationReason) {
+ case "api":
+ changedNodeFronts.add(nodeFront);
+ break;
+ default:
+ console.error(
+ "Unexpected mutation reason",
+ mutationReason,
+ ", removing"
+ );
+ // Fall Through
+ case "detach":
+ case "unload":
+ removedNodeFronts.push(nodeFront);
+ break;
+ }
+ }
+
+ if (removedNodeFronts.length) {
+ dispatch({
+ type: "REMOVE_DOM_MUTATION_BREAKPOINTS_FOR_FRONTS",
+ nodeFronts: removedNodeFronts,
+ });
+ }
+ if (changedNodeFronts.size > 0) {
+ const enabledStates = [];
+ for (const {
+ id,
+ nodeFront,
+ mutationType,
+ enabled,
+ } of getDOMMutationBreakpoints(getState())) {
+ if (changedNodeFronts.has(nodeFront)) {
+ const bpEnabledOnFront = nodeFront.mutationBreakpoints[mutationType];
+ if (bpEnabledOnFront !== enabled) {
+ // Sync the bp state from the front into the store.
+ enabledStates.push([id, bpEnabledOnFront]);
+ }
+ }
+ }
+
+ dispatch({
+ type: "SET_DOM_MUTATION_BREAKPOINTS_ENABLED_STATE",
+ enabledStates,
+ });
+ }
+ };
+}
+
+exports.toggleDOMMutationBreakpointState = toggleDOMMutationBreakpointState;
+function toggleDOMMutationBreakpointState(id, enabled) {
+ assert(typeof id === "string");
+ assert(typeof enabled === "boolean");
+
+ return async function ({ dispatch, getState }) {
+ const bp = getDOMMutationBreakpoint(getState(), id);
+ if (!bp) {
+ throw new Error(`No DOM mutation BP with ID ${id}`);
+ }
+
+ const walker = bp.nodeFront.getParent();
+ await walker.setMutationBreakpoints(bp.nodeFront, {
+ [bp.mutationType]: enabled,
+ });
+ };
+}