From cbd0d47aa5f602d3f4043214cfa15f8d2fb73b2f Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Fri, 7 Mar 2025 15:16:48 +0100 Subject: [PATCH] Teact: Some improvements --- src/lib/teact/dom-events.ts | 2 +- src/lib/teact/teact-dom.ts | 5 ++++- src/lib/teact/teact.ts | 32 ++++++++++++++++++++------------ src/util/safeExec.ts | 18 ++++++++++++------ 4 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/lib/teact/dom-events.ts b/src/lib/teact/dom-events.ts index 8d8e41ef4..c2299dc37 100644 --- a/src/lib/teact/dom-events.ts +++ b/src/lib/teact/dom-events.ts @@ -3,7 +3,7 @@ import { DEBUG } from '../../config'; type Handler = (e: Event) => void; type DelegationRegistry = Map; -const NON_BUBBLEABLE_EVENTS = new Set(['scroll', 'mouseenter', 'mouseleave', 'load']); +const NON_BUBBLEABLE_EVENTS = new Set(['scroll', 'mouseenter', 'mouseleave', 'load', 'error']); const documentEventCounters: Record = {}; const delegationRegistryByEventType: Record = {}; diff --git a/src/lib/teact/teact-dom.ts b/src/lib/teact/teact-dom.ts index 547640eb0..d42603f2b 100644 --- a/src/lib/teact/teact-dom.ts +++ b/src/lib/teact/teact-dom.ts @@ -46,8 +46,11 @@ const FILTERED_ATTRIBUTES = new Set(['key', 'ref', 'teactFastList', 'teactOrderK const HTML_ATTRIBUTES = new Set(['dir', 'role', 'form']); const CONTROLLABLE_TAGS = ['INPUT', 'TEXTAREA', 'SELECT']; const MAPPED_ATTRIBUTES: { [k: string]: string } = { - autoPlay: 'autoplay', + autoCapitalize: 'autocapitalize', autoComplete: 'autocomplete', + autoCorrect: 'autocorrect', + autoPlay: 'autoplay', + spellCheck: 'spellcheck', }; const INDEX_KEY_PREFIX = '__indexKey#'; diff --git a/src/lib/teact/teact.ts b/src/lib/teact/teact.ts index e501e44c9..8e3382d84 100644 --- a/src/lib/teact/teact.ts +++ b/src/lib/teact/teact.ts @@ -451,11 +451,13 @@ export function renderComponent(componentInstance: ComponentInstance) { incrementOverlayCounter(`${componentName} duration`, duration); } } - }, () => { - // eslint-disable-next-line no-console - console.error(`[Teact] Error while rendering component ${componentInstance.name}`, componentInstance); + }, { + rescue: () => { + // eslint-disable-next-line no-console + console.error(`[Teact] Error while rendering component ${componentInstance.name}`, componentInstance); - newRenderedValue = componentInstance.renderedValue; + newRenderedValue = componentInstance.renderedValue; + }, }); if (componentInstance.mountState === MountState.Mounted && newRenderedValue === componentInstance.renderedValue) { @@ -766,11 +768,15 @@ function scheduleEffect( ); } } - }, () => { - // eslint-disable-next-line no-console, max-len - console.error(`[Teact] Error in effect cleanup at cursor #${cursor} in ${componentInstance.name}`, componentInstance); - }, () => { - byCursor[cursor].cleanup = undefined; + }, { + rescue: () => { + // eslint-disable-next-line no-console, max-len + console.error(`[Teact] Error in effect cleanup at cursor #${cursor} in ${componentInstance.name}`, + componentInstance); + }, + always: () => { + byCursor[cursor].cleanup = undefined; + }, }); cleanupsContainer.set(effectId, runEffectCleanup); @@ -800,9 +806,11 @@ function scheduleEffect( console.warn(`[Teact] Slow effect at cursor #${cursor}: ${componentName}, ${Math.round(duration)} ms`); } } - }, () => { - // eslint-disable-next-line no-console - console.error(`[Teact] Error in effect at cursor #${cursor} in ${componentInstance.name}`, componentInstance); + }, { + rescue: () => { + // eslint-disable-next-line no-console + console.error(`[Teact] Error in effect at cursor #${cursor} in ${componentInstance.name}`, componentInstance); + }, }); effectsContainer.set(effectId, runEffect); diff --git a/src/util/safeExec.ts b/src/util/safeExec.ts index 50369529f..efd4843ac 100644 --- a/src/util/safeExec.ts +++ b/src/util/safeExec.ts @@ -3,20 +3,26 @@ import { handleError } from './handleError'; const SAFE_EXEC_ENABLED = !DEBUG_MORE; -export default function safeExec( - cb: F, - rescue?: (err: Error) => void, - always?: NoneToVoidFunction, -): ReturnType | undefined { +type SafeExecOptions = { + rescue?: (err: Error) => void; + always?: NoneToVoidFunction; + shouldIgnoreError?: boolean; +}; + +export default function safeExec(cb: T, options?: SafeExecOptions): ReturnType | undefined { if (!SAFE_EXEC_ENABLED) { return cb(); } + const { rescue, always, shouldIgnoreError } = options ?? {}; + try { return cb(); } catch (err: any) { rescue?.(err); - handleError(err); + if (!shouldIgnoreError) { + handleError(err); + } return undefined; } finally { always?.();