From 4cf1a466cdb0672341715ea72e34d6710c799023 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Thu, 6 Jul 2023 14:25:40 +0200 Subject: [PATCH] Revert "[Perf] Teact: Performance optimizations" This reverts commit fccdb019535c1eb23f6857ee97607cf39fbc48e8. --- src/lib/teact/teact.ts | 74 ++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/src/lib/teact/teact.ts b/src/lib/teact/teact.ts index 6c3ac85bd..d2c683716 100644 --- a/src/lib/teact/teact.ts +++ b/src/lib/teact/teact.ts @@ -1,13 +1,13 @@ import type { ReactElement } from 'react'; +import { requestMeasure, requestMutation } from '../fasterdom/fasterdom'; import { DEBUG, DEBUG_MORE } from '../../config'; +import { throttleWith } from '../../util/schedulers'; +import { orderBy } from '../../util/iteratees'; import { logUnequalProps } from '../../util/arePropsShallowEqual'; import { incrementOverlayCounter } from '../../util/debugOverlay'; -import { orderBy } from '../../util/iteratees'; -import safeExec from '../../util/safeExec'; -import { throttleWith } from '../../util/schedulers'; import { isSignal } from '../../util/signals'; -import { requestMeasure, requestMutation } from '../fasterdom/fasterdom'; +import safeExec from '../../util/safeExec'; export type Props = AnyLiteral; export type FC

= (props: P) => any; @@ -170,6 +170,8 @@ function createElement( props: Props, ...children: any[] ): VirtualElementParent | VirtualElementChildren { + children = children.flat(); + if (source === Fragment) { return buildFragmentElement(children); } else if (typeof source === 'function') { @@ -182,13 +184,18 @@ function createElement( function buildFragmentElement(children: any[]): VirtualElementFragment { return { type: VirtualElementTypesEnum.Fragment, - children: buildChildren(children, true), + children: dropEmptyTail(children, true).map(buildChildElement), }; } function createComponentInstance(Component: FC, props: Props, children: any[]): VirtualElementComponent { - if (children?.length) { - props.children = children.length === 1 ? children[0] : children; + let parsedChildren: any | any[] | undefined; + if (children.length === 0) { + parsedChildren = undefined; + } else if (children.length === 1) { + [parsedChildren] = children; + } else { + parsedChildren = children; } const componentInstance: ComponentInstance = { @@ -196,7 +203,10 @@ function createComponentInstance(Component: FC, props: Props, children: any[]): $element: {} as VirtualElementComponent, Component, name: Component.name, - props, + props: { + ...props, + ...(parsedChildren && { children: parsedChildren }), + }, mountState: MountState.New, hooks: { state: { @@ -225,13 +235,13 @@ function createComponentInstance(Component: FC, props: Props, children: any[]): function buildComponentElement( componentInstance: ComponentInstance, - children?: VirtualElementChildren, + children: VirtualElementChildren = [], ): VirtualElementComponent { return { type: VirtualElementTypesEnum.Component, componentInstance, props: componentInstance.props, - children: children ? buildChildren(children, true) : [], + children: dropEmptyTail(children, true).map(buildChildElement), }; } @@ -240,26 +250,10 @@ function buildTagElement(tag: string, props: Props, children: any[]): VirtualEle type: VirtualElementTypesEnum.Tag, tag, props, - children: buildChildren(children), + children: dropEmptyTail(children).map(buildChildElement), }; } -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). function dropEmptyTail(children: any[], noEmpty = false) { let i = children.length - 1; @@ -282,22 +276,31 @@ function dropEmptyTail(children: any[], noEmpty = false) { } function isEmptyPlaceholder(child: any) { - return !child && child !== 0; + // eslint-disable-next-line no-null/no-null + return child === false || child === null || child === undefined; } function buildChildElement(child: any): VirtualElement { if (isEmptyPlaceholder(child)) { - return { type: VirtualElementTypesEnum.Empty }; + return buildEmptyElement(); } else if (isParentElement(child)) { return child; } else { - return { - type: VirtualElementTypesEnum.Text, - value: String(child), - }; + return buildTextElement(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 const DEBUG_components: AnyLiteral = { TOTAL: { name: 'TOTAL', renders: 0 } }; // eslint-disable-next-line @typescript-eslint/naming-convention @@ -581,13 +584,12 @@ export function useState(): [T | undefined, StateHookSetter]; export function useState(initial: T, debugKey?: string): [T, StateHookSetter]; export function useState(initial?: T, debugKey?: string): [T, StateHookSetter] { const { cursor, byCursor } = renderingInstance.hooks.state; - const componentInstance = renderingInstance; if (byCursor[cursor] === undefined) { byCursor[cursor] = { value: initial, nextValue: initial, - setter: (newValue: ((current: T) => T) | T) => { + setter: ((componentInstance) => (newValue: ((current: T) => T) | T) => { if (componentInstance.mountState === MountState.Unmounted) { return; } @@ -614,7 +616,7 @@ export function useState(initial?: T, debugKey?: string): [T, StateHookSetter byCursor[cursor].nextValue, ); } - }, + })(renderingInstance), }; }