@wordpress/block-library
Version:
Block library for the WordPress editor.
60 lines (59 loc) • 1.75 kB
JavaScript
// packages/block-library/src/pattern/recursion-detector.js
import { useRegistry } from "@wordpress/data";
var cachedParsers = /* @__PURE__ */ new WeakMap();
function useParsePatternDependencies() {
const registry = useRegistry();
if (!cachedParsers.has(registry)) {
const deps = /* @__PURE__ */ new Map();
cachedParsers.set(
registry,
parsePatternDependencies.bind(null, deps)
);
}
return cachedParsers.get(registry);
}
function parsePatternDependencies(deps, { name, blocks }) {
const queue = [...blocks];
while (queue.length) {
const block = queue.shift();
for (const innerBlock of block.innerBlocks ?? []) {
queue.unshift(innerBlock);
}
if (block.name === "core/pattern") {
registerDependency(deps, name, block.attributes.slug);
}
}
}
function registerDependency(deps, a, b) {
if (!deps.has(a)) {
deps.set(a, /* @__PURE__ */ new Set());
}
deps.get(a).add(b);
if (hasCycle(deps, a)) {
throw new TypeError(
`Pattern ${a} has a circular dependency and cannot be rendered.`
);
}
}
function hasCycle(deps, slug, visitedNodes = /* @__PURE__ */ new Set(), currentPath = /* @__PURE__ */ new Set()) {
visitedNodes.add(slug);
currentPath.add(slug);
const dependencies = deps.get(slug) ?? /* @__PURE__ */ new Set();
for (const dependency of dependencies) {
if (!visitedNodes.has(dependency)) {
if (hasCycle(deps, dependency, visitedNodes, currentPath)) {
return true;
}
} else if (currentPath.has(dependency)) {
return true;
}
}
currentPath.delete(slug);
return false;
}
export {
parsePatternDependencies,
registerDependency,
useParsePatternDependencies
};
//# sourceMappingURL=recursion-detector.js.map