export function cutFibers(object) {
|
const objects = [object];
|
let obj;
|
|
while ((obj = objects.pop())) {
|
const keys = Object.keys(obj);
|
const descriptors = Object.getOwnPropertyDescriptors(obj);
|
const isSvg = obj.elementType === "svg";
|
|
// preventing processing svgs due to the problem with props,
|
// props sometimes come from the global variables, so it's tricky to clean them without breaking icons itself
|
if (isSvg) continue;
|
|
for (const key of keys) {
|
const prop = obj[key];
|
const isWritable = descriptors[key].writable;
|
|
if (prop && isWritable) {
|
if (key !== "_debugOwner" && typeof prop === "object" && {}.hasOwnProperty.call(prop, "stateNode")) {
|
objects.push(obj[key]);
|
}
|
if (typeof prop === "object" || typeof prop === "function") {
|
obj[key] = null;
|
}
|
}
|
}
|
}
|
}
|
|
export function findReactKey(node) {
|
const keys = Object.keys(node);
|
|
for (const key of keys) {
|
const match = RegExp(/^__reactProps(\$[^$]+)$/).exec(key);
|
|
if (match) {
|
return match[1];
|
}
|
}
|
return "";
|
}
|
|
export function cleanDomAfterReact(nodes, reactKey) {
|
for (const node of nodes) {
|
if (node.isConnected) return;
|
// preventing processing svgs due to the problem with props,
|
// props sometimes come from the global variables, so it's tricky to clean them without breaking icons itself
|
if (node.tagName === "svg") return;
|
const reactPropKeys = Object.keys(node).filter(
|
(key) =>
|
key.startsWith("__react") &&
|
(!RegExp(/^(?:__reactProps|__reactFiber)/).exec(key) || RegExp(new RegExp(`\\${reactKey}$`)).exec(key)),
|
);
|
|
if (reactPropKeys.length) {
|
for (const key of reactPropKeys) {
|
cutFibers(node[key]);
|
node[key] = null;
|
}
|
if (node.childNodes) {
|
cleanDomAfterReact(node.childNodes, reactKey);
|
}
|
}
|
}
|
}
|
|
const globalCache = new WeakMap();
|
|
function createCleaner() {
|
let ref = null;
|
|
return (node) => {
|
if (node) {
|
ref = node;
|
} else {
|
if (ref) {
|
const lastRef = ref;
|
const reactKey = findReactKey(lastRef);
|
|
ref = null;
|
setTimeout(() => {
|
cleanDomAfterReact([lastRef], reactKey);
|
});
|
}
|
}
|
};
|
}
|
|
export function reactCleaner(object, key = "default") {
|
if (!globalCache.has(object)) {
|
globalCache.set(object, new Map());
|
}
|
const cache = globalCache.get(object);
|
|
if (!cache.has(key)) {
|
cache.set(key, createCleaner());
|
}
|
|
return cache.get(key);
|
}
|