155 lines
4.5 KiB
JavaScript
155 lines
4.5 KiB
JavaScript
/* 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 }) {
|
|
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 }) {
|
|
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 ({ 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,
|
|
});
|
|
};
|
|
}
|