[Perf] Teact: Properly GC refs on unmount
This commit is contained in:
parent
0f0aba96c8
commit
188251f0fb
@ -76,10 +76,16 @@ interface ComponentInstance {
|
|||||||
memos: {
|
memos: {
|
||||||
cursor: number;
|
cursor: number;
|
||||||
byCursor: {
|
byCursor: {
|
||||||
current: any;
|
value: any;
|
||||||
dependencies: any[];
|
dependencies: any[];
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
|
refs: {
|
||||||
|
cursor: number;
|
||||||
|
byCursor: {
|
||||||
|
current: any;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
prepareForFrame?: () => void;
|
prepareForFrame?: () => void;
|
||||||
forceUpdate?: () => void;
|
forceUpdate?: () => void;
|
||||||
@ -176,6 +182,10 @@ function createComponentInstance(Component: FC, props: Props, children: any[]):
|
|||||||
cursor: 0,
|
cursor: 0,
|
||||||
byCursor: [],
|
byCursor: [],
|
||||||
},
|
},
|
||||||
|
refs: {
|
||||||
|
cursor: 0,
|
||||||
|
byCursor: [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -259,6 +269,7 @@ export function renderComponent(componentInstance: ComponentInstance) {
|
|||||||
componentInstance.hooks.state.cursor = 0;
|
componentInstance.hooks.state.cursor = 0;
|
||||||
componentInstance.hooks.effects.cursor = 0;
|
componentInstance.hooks.effects.cursor = 0;
|
||||||
componentInstance.hooks.memos.cursor = 0;
|
componentInstance.hooks.memos.cursor = 0;
|
||||||
|
componentInstance.hooks.refs.cursor = 0;
|
||||||
|
|
||||||
const { Component, props } = componentInstance;
|
const { Component, props } = componentInstance;
|
||||||
let newRenderedValue;
|
let newRenderedValue;
|
||||||
@ -373,11 +384,6 @@ function unmountComponent(componentInstance: ComponentInstance) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to clean refs before running effect cleanups
|
|
||||||
componentInstance.hooks.memos.byCursor.forEach((memoContainer) => {
|
|
||||||
memoContainer.current = undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
componentInstance.hooks.effects.byCursor.forEach((effect) => {
|
componentInstance.hooks.effects.byCursor.forEach((effect) => {
|
||||||
if (effect.cleanup) {
|
if (effect.cleanup) {
|
||||||
try {
|
try {
|
||||||
@ -410,9 +416,14 @@ function helpGc(componentInstance: ComponentInstance) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
componentInstance.hooks.memos.byCursor.forEach((hook) => {
|
componentInstance.hooks.memos.byCursor.forEach((hook) => {
|
||||||
|
hook.value = undefined as any;
|
||||||
hook.dependencies = undefined as any;
|
hook.dependencies = undefined as any;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
componentInstance.hooks.refs.byCursor.forEach((hook) => {
|
||||||
|
hook.current = undefined as any;
|
||||||
|
});
|
||||||
|
|
||||||
componentInstance.hooks = undefined as any;
|
componentInstance.hooks = undefined as any;
|
||||||
componentInstance.$element = undefined as any;
|
componentInstance.$element = undefined as any;
|
||||||
componentInstance.renderedValue = undefined;
|
componentInstance.renderedValue = undefined;
|
||||||
@ -643,7 +654,7 @@ export function useLayoutEffect(effect: () => Function | void, dependencies?: re
|
|||||||
|
|
||||||
export function useMemo<T extends any>(resolver: () => T, dependencies: any[], debugKey?: string): T {
|
export function useMemo<T extends any>(resolver: () => T, dependencies: any[], debugKey?: string): T {
|
||||||
const { cursor, byCursor } = renderingInstance.hooks.memos;
|
const { cursor, byCursor } = renderingInstance.hooks.memos;
|
||||||
let { current } = byCursor[cursor] || {};
|
let { value } = byCursor[cursor] || {};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
byCursor[cursor] === undefined
|
byCursor[cursor] === undefined
|
||||||
@ -659,17 +670,17 @@ export function useMemo<T extends any>(resolver: () => T, dependencies: any[], d
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
current = resolver();
|
value = resolver();
|
||||||
}
|
}
|
||||||
|
|
||||||
byCursor[cursor] = {
|
byCursor[cursor] = {
|
||||||
current,
|
value,
|
||||||
dependencies,
|
dependencies,
|
||||||
};
|
};
|
||||||
|
|
||||||
renderingInstance.hooks.memos.cursor++;
|
renderingInstance.hooks.memos.cursor++;
|
||||||
|
|
||||||
return current;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useCallback<F extends AnyFunction>(newCallback: F, dependencies: any[], debugKey?: string): F {
|
export function useCallback<F extends AnyFunction>(newCallback: F, dependencies: any[], debugKey?: string): F {
|
||||||
@ -682,10 +693,16 @@ export function useRef<T>(): { current: T | undefined }; // TT way (empty is `un
|
|||||||
export function useRef<T>(initial: null): { current: T | null }; // React way (empty is `null`)
|
export function useRef<T>(initial: null): { current: T | null }; // React way (empty is `null`)
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
export function useRef<T>(initial?: T | null) {
|
export function useRef<T>(initial?: T | null) {
|
||||||
return useMemo(() => ({
|
const { cursor, byCursor } = renderingInstance.hooks.refs;
|
||||||
current: initial,
|
if (!byCursor[cursor]) {
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
byCursor[cursor] = {
|
||||||
}), []);
|
current: initial,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
renderingInstance.hooks.refs.cursor++;
|
||||||
|
|
||||||
|
return byCursor[cursor];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function memo<T extends FC>(Component: T, debugKey?: string) {
|
export function memo<T extends FC>(Component: T, debugKey?: string) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user