[Perf] Teact: Fix memory leaks
This commit is contained in:
parent
3a282b8086
commit
29852d2bf6
@ -60,7 +60,11 @@ export default function useScrollHooks(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { offsetHeight, scrollHeight, scrollTop } = containerRef.current!;
|
if (!containerRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { offsetHeight, scrollHeight, scrollTop } = containerRef.current;
|
||||||
const scrollBottom = Math.round(scrollHeight - scrollTop - offsetHeight);
|
const scrollBottom = Math.round(scrollHeight - scrollTop - offsetHeight);
|
||||||
const isNearBottom = scrollBottom <= FAB_THRESHOLD;
|
const isNearBottom = scrollBottom <= FAB_THRESHOLD;
|
||||||
const isAtBottom = scrollBottom <= NOTCH_THRESHOLD;
|
const isAtBottom = scrollBottom <= NOTCH_THRESHOLD;
|
||||||
|
|||||||
@ -122,14 +122,20 @@ function renderWithVirtual(
|
|||||||
unmountTree($current);
|
unmountTree($current);
|
||||||
} else {
|
} else {
|
||||||
const areComponents = isComponentElement($current) && isComponentElement($new);
|
const areComponents = isComponentElement($current) && isComponentElement($new);
|
||||||
|
const currentTarget = getTarget($current);
|
||||||
|
|
||||||
if (!areComponents) {
|
if (!areComponents) {
|
||||||
setTarget($new, getTarget($current)!);
|
setTarget($new, currentTarget!);
|
||||||
|
setTarget($current, undefined as any); // Help GC
|
||||||
|
|
||||||
|
if ('props' in $current && 'props' in $new) {
|
||||||
|
$new.props.ref = $current.props.ref;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRealElement($current) && isRealElement($new)) {
|
if (isRealElement($current) && isRealElement($new)) {
|
||||||
if (moveDirection) {
|
if (moveDirection) {
|
||||||
const node = getTarget($current)!;
|
const node = currentTarget!;
|
||||||
const nextSibling = parentEl.childNodes[moveDirection === 'up' ? index : index + 1];
|
const nextSibling = parentEl.childNodes[moveDirection === 'up' ? index : index + 1];
|
||||||
|
|
||||||
if (nextSibling) {
|
if (nextSibling) {
|
||||||
@ -140,13 +146,13 @@ function renderWithVirtual(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!areComponents) {
|
if (!areComponents) {
|
||||||
updateAttributes($current, $new, getTarget($current) as HTMLElement);
|
updateAttributes($current, $new, currentTarget as HTMLElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
$new.children = renderChildren(
|
$new.children = renderChildren(
|
||||||
$current,
|
$current,
|
||||||
$new,
|
$new,
|
||||||
areComponents ? parentEl : getTarget($current) as HTMLElement,
|
areComponents ? parentEl : currentTarget as HTMLElement,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -336,17 +336,26 @@ export function hasElementChanged($old: VirtualElement, $new: VirtualElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function unmountTree($element: VirtualElement) {
|
export function unmountTree($element: VirtualElement) {
|
||||||
if (!isRealElement($element)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isComponentElement($element)) {
|
if (isComponentElement($element)) {
|
||||||
unmountComponent($element.componentInstance);
|
unmountComponent($element.componentInstance);
|
||||||
} else if ($element.target) {
|
} else {
|
||||||
removeAllDelegatedListeners($element.target as HTMLElement);
|
if (isTagElement($element)) {
|
||||||
// Trying to help GC
|
if ($element.target) {
|
||||||
// eslint-disable-next-line no-null/no-null
|
removeAllDelegatedListeners($element.target as HTMLElement);
|
||||||
$element.target = null as any;
|
}
|
||||||
|
|
||||||
|
if ($element.props.ref) {
|
||||||
|
$element.props.ref.current = undefined; // Help GC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($element.target) {
|
||||||
|
$element.target = undefined; // Help GC
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isRealElement($element)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$element.children.forEach(unmountTree);
|
$element.children.forEach(unmountTree);
|
||||||
@ -363,9 +372,9 @@ function unmountComponent(componentInstance: ComponentInstance) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentInstance.hooks.memos.byCursor.forEach((hook) => {
|
// We need to clean refs before running effect cleanups
|
||||||
// eslint-disable-next-line no-null/no-null
|
componentInstance.hooks.memos.byCursor.forEach((memoContainer) => {
|
||||||
hook.current = null;
|
memoContainer.current = undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
componentInstance.hooks.effects.byCursor.forEach(({ cleanup }) => {
|
componentInstance.hooks.effects.byCursor.forEach(({ cleanup }) => {
|
||||||
@ -383,35 +392,31 @@ function unmountComponent(componentInstance: ComponentInstance) {
|
|||||||
helpGc(componentInstance);
|
helpGc(componentInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to remove all references to DOM objects. We also clean all other references, just in case.
|
// We need to remove all references to DOM objects. We also clean all other references, just in case
|
||||||
function helpGc(componentInstance: ComponentInstance) {
|
function helpGc(componentInstance: ComponentInstance) {
|
||||||
/* eslint-disable no-null/no-null */
|
|
||||||
|
|
||||||
componentInstance.hooks.effects.byCursor.forEach((hook) => {
|
componentInstance.hooks.effects.byCursor.forEach((hook) => {
|
||||||
hook.cleanup = null as any;
|
hook.cleanup = undefined;
|
||||||
hook.effect = null as any;
|
hook.effect = undefined as any;
|
||||||
hook.dependencies = null as any;
|
hook.dependencies = undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
componentInstance.hooks.state.byCursor.forEach((hook) => {
|
componentInstance.hooks.state.byCursor.forEach((hook) => {
|
||||||
hook.value = null as any;
|
hook.value = undefined;
|
||||||
hook.nextValue = null as any;
|
hook.nextValue = undefined;
|
||||||
hook.setter = null as any;
|
hook.setter = undefined as any;
|
||||||
});
|
});
|
||||||
|
|
||||||
componentInstance.hooks.memos.byCursor.forEach((hook) => {
|
componentInstance.hooks.memos.byCursor.forEach((hook) => {
|
||||||
hook.dependencies = null as any;
|
hook.dependencies = undefined as any;
|
||||||
});
|
});
|
||||||
|
|
||||||
componentInstance.hooks = null as any;
|
componentInstance.hooks = undefined as any;
|
||||||
componentInstance.$element = null as any;
|
componentInstance.$element = undefined as any;
|
||||||
componentInstance.renderedValue = null as any;
|
componentInstance.renderedValue = undefined;
|
||||||
componentInstance.Component = null as any;
|
componentInstance.Component = undefined as any;
|
||||||
componentInstance.props = null as any;
|
componentInstance.props = undefined as any;
|
||||||
componentInstance.forceUpdate = null as any;
|
componentInstance.forceUpdate = undefined;
|
||||||
componentInstance.onUpdate = null as any;
|
componentInstance.onUpdate = undefined;
|
||||||
|
|
||||||
/* eslint-enable no-null/no-null */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareComponentForFrame(componentInstance: ComponentInstance) {
|
function prepareComponentForFrame(componentInstance: ComponentInstance) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user