Revert "Revert "[Perf] Teact: Performance optimizations""
This reverts commit 1ef9a367504f35f8c86f0865cb25305756a93e3c.
This commit is contained in:
parent
2f21b34689
commit
255fb11d94
@ -1,13 +1,13 @@
|
|||||||
import type { ReactElement } from 'react';
|
import type { ReactElement } from 'react';
|
||||||
import { requestMeasure, requestMutation } from '../fasterdom/fasterdom';
|
|
||||||
|
|
||||||
import { DEBUG, DEBUG_MORE } from '../../config';
|
import { DEBUG, DEBUG_MORE } from '../../config';
|
||||||
import { throttleWith } from '../../util/schedulers';
|
|
||||||
import { orderBy } from '../../util/iteratees';
|
|
||||||
import { logUnequalProps } from '../../util/arePropsShallowEqual';
|
import { logUnequalProps } from '../../util/arePropsShallowEqual';
|
||||||
import { incrementOverlayCounter } from '../../util/debugOverlay';
|
import { incrementOverlayCounter } from '../../util/debugOverlay';
|
||||||
import { isSignal } from '../../util/signals';
|
import { orderBy } from '../../util/iteratees';
|
||||||
import safeExec from '../../util/safeExec';
|
import safeExec from '../../util/safeExec';
|
||||||
|
import { throttleWith } from '../../util/schedulers';
|
||||||
|
import { isSignal } from '../../util/signals';
|
||||||
|
import { requestMeasure, requestMutation } from '../fasterdom/fasterdom';
|
||||||
|
|
||||||
export type Props = AnyLiteral;
|
export type Props = AnyLiteral;
|
||||||
export type FC<P extends Props = any> = (props: P) => any;
|
export type FC<P extends Props = any> = (props: P) => any;
|
||||||
@ -170,8 +170,6 @@ function createElement(
|
|||||||
props: Props,
|
props: Props,
|
||||||
...children: any[]
|
...children: any[]
|
||||||
): VirtualElementParent | VirtualElementChildren {
|
): VirtualElementParent | VirtualElementChildren {
|
||||||
children = children.flat();
|
|
||||||
|
|
||||||
if (source === Fragment) {
|
if (source === Fragment) {
|
||||||
return buildFragmentElement(children);
|
return buildFragmentElement(children);
|
||||||
} else if (typeof source === 'function') {
|
} else if (typeof source === 'function') {
|
||||||
@ -184,18 +182,13 @@ function createElement(
|
|||||||
function buildFragmentElement(children: any[]): VirtualElementFragment {
|
function buildFragmentElement(children: any[]): VirtualElementFragment {
|
||||||
return {
|
return {
|
||||||
type: VirtualElementTypesEnum.Fragment,
|
type: VirtualElementTypesEnum.Fragment,
|
||||||
children: dropEmptyTail(children, true).map(buildChildElement),
|
children: buildChildren(children, true),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createComponentInstance(Component: FC, props: Props, children: any[]): VirtualElementComponent {
|
function createComponentInstance(Component: FC, props: Props, children: any[]): VirtualElementComponent {
|
||||||
let parsedChildren: any | any[] | undefined;
|
if (children?.length) {
|
||||||
if (children.length === 0) {
|
props.children = children.length === 1 ? children[0] : children;
|
||||||
parsedChildren = undefined;
|
|
||||||
} else if (children.length === 1) {
|
|
||||||
[parsedChildren] = children;
|
|
||||||
} else {
|
|
||||||
parsedChildren = children;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const componentInstance: ComponentInstance = {
|
const componentInstance: ComponentInstance = {
|
||||||
@ -203,10 +196,7 @@ function createComponentInstance(Component: FC, props: Props, children: any[]):
|
|||||||
$element: {} as VirtualElementComponent,
|
$element: {} as VirtualElementComponent,
|
||||||
Component,
|
Component,
|
||||||
name: Component.name,
|
name: Component.name,
|
||||||
props: {
|
props,
|
||||||
...props,
|
|
||||||
...(parsedChildren && { children: parsedChildren }),
|
|
||||||
},
|
|
||||||
mountState: MountState.New,
|
mountState: MountState.New,
|
||||||
hooks: {
|
hooks: {
|
||||||
state: {
|
state: {
|
||||||
@ -235,13 +225,13 @@ function createComponentInstance(Component: FC, props: Props, children: any[]):
|
|||||||
|
|
||||||
function buildComponentElement(
|
function buildComponentElement(
|
||||||
componentInstance: ComponentInstance,
|
componentInstance: ComponentInstance,
|
||||||
children: VirtualElementChildren = [],
|
children?: VirtualElementChildren,
|
||||||
): VirtualElementComponent {
|
): VirtualElementComponent {
|
||||||
return {
|
return {
|
||||||
type: VirtualElementTypesEnum.Component,
|
type: VirtualElementTypesEnum.Component,
|
||||||
componentInstance,
|
componentInstance,
|
||||||
props: componentInstance.props,
|
props: componentInstance.props,
|
||||||
children: dropEmptyTail(children, true).map(buildChildElement),
|
children: children ? buildChildren(children, true) : [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,10 +240,26 @@ function buildTagElement(tag: string, props: Props, children: any[]): VirtualEle
|
|||||||
type: VirtualElementTypesEnum.Tag,
|
type: VirtualElementTypesEnum.Tag,
|
||||||
tag,
|
tag,
|
||||||
props,
|
props,
|
||||||
children: dropEmptyTail(children).map(buildChildElement),
|
children: buildChildren(children),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildChildren(children: any[], noEmpty = false): VirtualElement[] {
|
||||||
|
const cleanChildren = dropEmptyTail(children, noEmpty);
|
||||||
|
const newChildren = [];
|
||||||
|
|
||||||
|
for (let i = 0, l = cleanChildren.length; i < l; i++) {
|
||||||
|
const child = cleanChildren[i];
|
||||||
|
if (Array.isArray(child)) {
|
||||||
|
newChildren.push(...buildChildren(child, noEmpty));
|
||||||
|
} else {
|
||||||
|
newChildren.push(buildChildElement(child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newChildren;
|
||||||
|
}
|
||||||
|
|
||||||
// We only need placeholders in the middle of collection (to ensure other elements order).
|
// We only need placeholders in the middle of collection (to ensure other elements order).
|
||||||
function dropEmptyTail(children: any[], noEmpty = false) {
|
function dropEmptyTail(children: any[], noEmpty = false) {
|
||||||
let i = children.length - 1;
|
let i = children.length - 1;
|
||||||
@ -276,31 +282,22 @@ function dropEmptyTail(children: any[], noEmpty = false) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isEmptyPlaceholder(child: any) {
|
function isEmptyPlaceholder(child: any) {
|
||||||
// eslint-disable-next-line no-null/no-null
|
return !child && child !== 0;
|
||||||
return child === false || child === null || child === undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildChildElement(child: any): VirtualElement {
|
function buildChildElement(child: any): VirtualElement {
|
||||||
if (isEmptyPlaceholder(child)) {
|
if (isEmptyPlaceholder(child)) {
|
||||||
return buildEmptyElement();
|
return { type: VirtualElementTypesEnum.Empty };
|
||||||
} else if (isParentElement(child)) {
|
} else if (isParentElement(child)) {
|
||||||
return child;
|
return child;
|
||||||
} else {
|
} else {
|
||||||
return buildTextElement(child);
|
return {
|
||||||
|
type: VirtualElementTypesEnum.Text,
|
||||||
|
value: String(child),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildTextElement(value: any): VirtualElementText {
|
|
||||||
return {
|
|
||||||
type: VirtualElementTypesEnum.Text,
|
|
||||||
value: String(value),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildEmptyElement(): VirtualElementEmpty {
|
|
||||||
return { type: VirtualElementTypesEnum.Empty };
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
const DEBUG_components: AnyLiteral = { TOTAL: { name: 'TOTAL', renders: 0 } };
|
const DEBUG_components: AnyLiteral = { TOTAL: { name: 'TOTAL', renders: 0 } };
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
@ -584,12 +581,13 @@ export function useState<T>(): [T | undefined, StateHookSetter<T | undefined>];
|
|||||||
export function useState<T>(initial: T, debugKey?: string): [T, StateHookSetter<T>];
|
export function useState<T>(initial: T, debugKey?: string): [T, StateHookSetter<T>];
|
||||||
export function useState<T>(initial?: T, debugKey?: string): [T, StateHookSetter<T>] {
|
export function useState<T>(initial?: T, debugKey?: string): [T, StateHookSetter<T>] {
|
||||||
const { cursor, byCursor } = renderingInstance.hooks.state;
|
const { cursor, byCursor } = renderingInstance.hooks.state;
|
||||||
|
const componentInstance = renderingInstance;
|
||||||
|
|
||||||
if (byCursor[cursor] === undefined) {
|
if (byCursor[cursor] === undefined) {
|
||||||
byCursor[cursor] = {
|
byCursor[cursor] = {
|
||||||
value: initial,
|
value: initial,
|
||||||
nextValue: initial,
|
nextValue: initial,
|
||||||
setter: ((componentInstance) => (newValue: ((current: T) => T) | T) => {
|
setter: (newValue: ((current: T) => T) | T) => {
|
||||||
if (componentInstance.mountState === MountState.Unmounted) {
|
if (componentInstance.mountState === MountState.Unmounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -616,7 +614,7 @@ export function useState<T>(initial?: T, debugKey?: string): [T, StateHookSetter
|
|||||||
byCursor[cursor].nextValue,
|
byCursor[cursor].nextValue,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
})(renderingInstance),
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user