From eb00bcc8b3cf7ee7614f4172bf3a0f34729a37d6 Mon Sep 17 00:00:00 2001 From: Chris Lorenzo Date: Fri, 16 Oct 2026 23:38:16 -0400 Subject: [PATCH] perf(core): index loops instead of for-of in per-node and per-focus paths Legacy builds compile for-of to Babel's iterator helper, which on Chrome 38 runs through core-js's Symbol and array iterator polyfills. assignEffects and hasBorderWidth run for each node with effects, render's parent wiring for each node rendered, and keyExists on every path element of a focus change; each now walks its array by index. Co-Authored-By: Claude Opus 5.5 --- src/core/elementNode.ts | 13 ++++++++++--- src/core/utils.ts | 6 ++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/core/elementNode.ts b/src/core/elementNode.ts index 9a79727b..bfa89571 100644 --- a/src/core/elementNode.ts +++ b/src/core/elementNode.ts @@ -243,7 +243,11 @@ const parseAndAssignShaderProps = ( const assignEffects = (v: StyleEffects, props: Record) => { if (v.rounded) props.radius = v.rounded.radius; if (v.borderRadius) props.radius = v.borderRadius; - for (const k of EFFECT_SHADER_KEYS) { + // Index loops here and below: legacy builds compile for-of to an iterator + // helper, which on Chrome 38 runs through core-js's Symbol and array + // iterator polyfills. + for (let i = 0; i < EFFECT_SHADER_KEYS.length; i++) { + const k = EFFECT_SHADER_KEYS[i]!; if (v[k]) parseAndAssignShaderProps(k, v[k], props); } }; @@ -284,7 +288,8 @@ const hasBorderWidth = ( props: Record, change?: Record, ) => { - for (const key of BORDER_WIDTH_KEYS) { + for (let k = 0; k < BORDER_WIDTH_KEYS.length; k++) { + const key = BORDER_WIDTH_KEYS[k]!; const w = change !== undefined && key in change ? change[key] : props[key]; if (isArray(w)) { for (let i = 0; i < w.length; i++) if (w[i] > 0) return true; @@ -1875,7 +1880,9 @@ export class ElementNode { if (node._hasRenderedChildren) { node._hasRenderedChildren = false; - for (const child of node.children) { + const children = node.children; + for (let i = 0; i < children.length; i++) { + const child = children[i]!; if (isElementNode(child) && isINode(child.lng)) { child.lng.parent = node.lng as INode; } diff --git a/src/core/utils.ts b/src/core/utils.ts index 1c62c315..bc6db32d 100644 --- a/src/core/utils.ts +++ b/src/core/utils.ts @@ -70,8 +70,10 @@ export function keyExists( obj: Record, keys: (string | number | symbol)[], ) { - for (const key of keys) { - if (key in obj) { + // An index loop: legacy builds compile for-of to an iterator helper, which + // on Chrome 38 runs through core-js's polyfills (this runs per focus change). + for (let i = 0; i < keys.length; i++) { + if (keys[i]! in obj) { return true; } }