@getforma/core 0.8.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runtime.ts","../node_modules/alien-signals/esm/system.mjs","../node_modules/alien-signals/esm/index.mjs","../src/reactive/signal.ts","../src/reactive/root.ts","../src/reactive/effect.ts","../src/reactive/computed.ts","../src/reactive/batch.ts","../src/dom/list.ts","../src/dom/reconcile.ts"],"sourcesContent":["/**\n * FormaJS HTML Runtime — Alpine-like declarative API via data-* attributes.\n *\n * Usage:\n * <script src=\"formajs.runtime.min.js\"></script>\n * <div data-forma-state='{\"count\": 0}'>\n * <p data-text=\"{count}\"></p>\n * <button data-on:click=\"{count++}\">+1</button>\n * </div>\n *\n * Supported attributes:\n * data-forma-state='{\"key\": value}' State declaration (JSON)\n * data-text=\"{expr}\" Text content binding\n * data-show=\"{expr}\" Display toggle (display: none)\n * data-transition:*=\"...\" Enter/leave transitions for data-show\n * data-if=\"{expr}\" Conditional render (remove/restore)\n * data-model=\"{prop}\" Two-way input binding\n * data-on:event=\"{expr}\" Event handler\n * data-class:name=\"{expr}\" Conditional CSS class\n * data-bind:attr=\"{expr}\" Dynamic attribute\n * data-computed=\"name = expr\" Computed value\n * data-persist=\"{prop}\" localStorage sync\n * data-list=\"{expr}\" List rendering (first child = template)\n * data-fetch=\"GET /url → prop\" Fetch binding\n * data-fetch-id=\"name\" Register fetch for $refetch('name')\n */\nimport { createSignal, internalEffect, createComputed, batch } from './reactive';\nimport { reconcileList, type ListTransitionHooks } from './dom/list';\nimport { createReconciler } from './dom/reconcile';\n\ntype Getter = () => unknown;\ntype Setter = (v: unknown) => void;\n\ninterface Scope {\n getters: Record<string, Getter>;\n setters: Record<string, Setter>;\n}\n\n// ── $refetch registry ──\n// Maps data-fetch-id values to their doFetch() functions so handlers can\n// trigger imperative refetches via $refetch('id').\nconst _refetchRegistry = new Map<string, () => void>();\n\nfunction $refetch(id: string): void {\n const fn = _refetchRegistry.get(id);\n if (fn) {\n fn();\n } else if (_debug) {\n dbg(`$refetch: no data-fetch with id \"${id}\" found`);\n }\n}\n\nfunction createChildScope(parent: Scope, locals: Record<string, unknown>): Scope {\n const localGetters: Record<string, Getter> = Object.create(null);\n for (const key of Object.keys(locals)) {\n localGetters[key] = () => locals[key];\n }\n\n return {\n getters: new Proxy(parent.getters, {\n get(target, prop: string) {\n if (prop in localGetters) return localGetters[prop];\n return target[prop];\n },\n has(target, prop: string) {\n return prop in localGetters || prop in target;\n },\n }),\n setters: parent.setters,\n };\n}\n\n// ── Debug logger — enable via FormaRuntime.debug = true or window.__FORMA_DEBUG = true ──\nlet _debug = false;\ntype UnsafeEvalMode = 'mutable' | 'locked-off' | 'locked-on';\nlet _unsafeEvalMode: UnsafeEvalMode = 'mutable';\nlet _allowUnsafeEval = false;\nlet _diagnosticsEnabled = true;\nfunction dbg(...args: unknown[]): void {\n if (_debug || (typeof window !== 'undefined' && (window as any).__FORMA_DEBUG)) {\n console.log('[FormaJS]', ...args);\n }\n}\n\ninterface RuntimeConfig {\n allowUnsafeEval?: boolean;\n unsafeEvalMode?: UnsafeEvalMode;\n lockUnsafeEval?: boolean;\n diagnostics?: boolean;\n autoContainment?: boolean;\n}\n\ninterface RuntimeDiagnostic {\n kind: 'handler-unsupported' | 'expression-unsupported';\n expr: string;\n reason: string;\n count: number;\n firstSeenAt: number;\n lastSeenAt: number;\n}\n\nconst diagnostics = new Map<string, RuntimeDiagnostic>();\n\nfunction parseBooleanFlag(raw: string | null | undefined): boolean | undefined {\n if (raw == null) return undefined;\n const normalized = raw.trim().toLowerCase();\n if (normalized === '1' || normalized === 'true' || normalized === 'on' || normalized === 'yes') return true;\n if (normalized === '0' || normalized === 'false' || normalized === 'off' || normalized === 'no') return false;\n return undefined;\n}\n\nfunction parseUnsafeEvalMode(raw: string | null | undefined): UnsafeEvalMode | undefined {\n if (raw == null) return undefined;\n const normalized = raw.trim().toLowerCase();\n if (normalized === 'mutable') return 'mutable';\n if (normalized === 'locked-off' || normalized === 'off' || normalized === 'disabled') {\n return 'locked-off';\n }\n if (normalized === 'locked-on' || normalized === 'on' || normalized === 'enabled') {\n return 'locked-on';\n }\n return undefined;\n}\n\nfunction readRuntimeConfig(): RuntimeConfig {\n const config: RuntimeConfig = {};\n\n if (typeof window !== 'undefined') {\n const globalConfig = (window as any).__FORMA_RUNTIME_CONFIG as RuntimeConfig | undefined;\n if (globalConfig) {\n if (typeof globalConfig.allowUnsafeEval === 'boolean') {\n config.allowUnsafeEval = globalConfig.allowUnsafeEval;\n }\n if (typeof globalConfig.unsafeEvalMode === 'string') {\n const parsed = parseUnsafeEvalMode(globalConfig.unsafeEvalMode);\n if (parsed) config.unsafeEvalMode = parsed;\n }\n if (typeof globalConfig.lockUnsafeEval === 'boolean') {\n config.lockUnsafeEval = globalConfig.lockUnsafeEval;\n }\n if (typeof globalConfig.diagnostics === 'boolean') {\n config.diagnostics = globalConfig.diagnostics;\n }\n if (typeof globalConfig.autoContainment === 'boolean') {\n config.autoContainment = globalConfig.autoContainment;\n }\n }\n }\n\n if (typeof document !== 'undefined') {\n const script = document.currentScript as HTMLScriptElement | null;\n if (script) {\n const unsafeFromAttr = parseBooleanFlag(script.getAttribute('data-forma-unsafe-eval'));\n if (unsafeFromAttr !== undefined) {\n config.allowUnsafeEval = unsafeFromAttr;\n }\n const modeFromAttr = parseUnsafeEvalMode(\n script.getAttribute('data-forma-unsafe-eval-mode'),\n );\n if (modeFromAttr !== undefined) {\n config.unsafeEvalMode = modeFromAttr;\n }\n const lockFromAttr = parseBooleanFlag(script.getAttribute('data-forma-lock-unsafe-eval'));\n if (lockFromAttr !== undefined) {\n config.lockUnsafeEval = lockFromAttr;\n }\n const diagnosticsFromAttr = parseBooleanFlag(script.getAttribute('data-forma-diagnostics'));\n if (diagnosticsFromAttr !== undefined) {\n config.diagnostics = diagnosticsFromAttr;\n }\n const containmentFromAttr = parseBooleanFlag(script.getAttribute('data-forma-auto-containment'));\n if (containmentFromAttr !== undefined) {\n config.autoContainment = containmentFromAttr;\n }\n }\n }\n\n return config;\n}\n\nfunction reportDiagnostic(\n kind: RuntimeDiagnostic['kind'],\n expr: string,\n reason: string,\n): void {\n if (!_diagnosticsEnabled) return;\n\n const key = `${kind}|${reason}|${expr}`;\n const now = Date.now();\n const existing = diagnostics.get(key);\n\n if (existing) {\n existing.count += 1;\n existing.lastSeenAt = now;\n } else {\n diagnostics.set(key, {\n kind,\n expr,\n reason,\n count: 1,\n firstSeenAt: now,\n lastSeenAt: now,\n });\n console.warn(`[FormaJS] ${reason}: ${expr}`);\n }\n\n try {\n if (typeof window !== 'undefined') {\n const detail = {\n kind,\n expr,\n reason,\n count: diagnostics.get(key)?.count ?? 1,\n };\n window.dispatchEvent(new CustomEvent('formajs:diagnostic', { detail }));\n }\n } catch {\n // Ignore event dispatch failures\n }\n}\n\ndeclare const __FORMA_UNSAFE_EVAL_MODE__: string | undefined;\nconst buildUnsafeEvalMode = parseUnsafeEvalMode(\n typeof __FORMA_UNSAFE_EVAL_MODE__ === 'string'\n ? __FORMA_UNSAFE_EVAL_MODE__\n : undefined,\n);\n\nif (buildUnsafeEvalMode) {\n _unsafeEvalMode = buildUnsafeEvalMode;\n if (_unsafeEvalMode === 'locked-off') _allowUnsafeEval = false;\n if (_unsafeEvalMode === 'locked-on') _allowUnsafeEval = true;\n if (_unsafeEvalMode === 'mutable') _allowUnsafeEval = true;\n}\n\nconst runtimeConfig = readRuntimeConfig();\nconst configUnsafeMode = runtimeConfig.lockUnsafeEval\n ? 'locked-off'\n : runtimeConfig.unsafeEvalMode;\nif (configUnsafeMode) {\n _unsafeEvalMode = configUnsafeMode;\n if (_unsafeEvalMode === 'locked-off') _allowUnsafeEval = false;\n if (_unsafeEvalMode === 'locked-on') _allowUnsafeEval = true;\n}\nif (\n _unsafeEvalMode === 'mutable'\n && typeof runtimeConfig.allowUnsafeEval === 'boolean'\n) {\n _allowUnsafeEval = runtimeConfig.allowUnsafeEval;\n}\nif (typeof runtimeConfig.diagnostics === 'boolean') {\n _diagnosticsEnabled = runtimeConfig.diagnostics;\n}\nconst _autoContainment = runtimeConfig.autoContainment === true;\n\ninterface SchedulerLike {\n yield?: () => Promise<unknown>;\n postTask?: (\n callback: () => void,\n options?: { priority?: 'user-blocking' | 'user-visible' | 'background' },\n ) => Promise<unknown>;\n}\n\nfunction getScheduler(): SchedulerLike | undefined {\n const candidate = (globalThis as any)?.scheduler as SchedulerLike | undefined;\n if (!candidate) return undefined;\n if (typeof candidate.yield === 'function' || typeof candidate.postTask === 'function') {\n return candidate;\n }\n return undefined;\n}\n\n/** Yield control to keep the main thread responsive during large batches. */\nasync function yieldToMain(): Promise<void> {\n const scheduler = getScheduler();\n if (scheduler?.yield) {\n await scheduler.yield();\n return;\n }\n if (scheduler?.postTask) {\n await scheduler.postTask(() => {}, { priority: 'background' });\n return;\n }\n await new Promise<void>((resolve) => setTimeout(resolve, 0));\n}\n\ninterface ContainmentHintsOptions {\n selector?: string;\n contain?: string;\n contentVisibility?: string;\n containIntrinsicSize?: string;\n skipIfAlreadySet?: boolean;\n}\n\n/** Apply CSS containment hints to opt-in containers for lower layout/paint cost. */\nfunction applyContainmentHints(\n root: ParentNode = document,\n options: ContainmentHintsOptions = {},\n): number {\n const selector = options.selector ?? '[data-forma-contain]';\n if (!selector) return 0;\n if (typeof (root as ParentNode).querySelectorAll !== 'function') return 0;\n\n const nodes = root.querySelectorAll(selector);\n let applied = 0;\n for (let i = 0; i < nodes.length; i++) {\n const el = nodes[i] as HTMLElement;\n if (!el?.style) continue;\n\n const contain = el.getAttribute('data-forma-contain') ?? options.contain ?? 'layout style paint';\n const contentVisibility = el.getAttribute('data-forma-content-visibility')\n ?? options.contentVisibility\n ?? 'auto';\n const containIntrinsicSize = el.getAttribute('data-forma-contain-intrinsic-size')\n ?? options.containIntrinsicSize\n ?? 'auto 800px';\n const skipExisting = options.skipIfAlreadySet === true;\n let changed = false;\n\n const containCurrent = el.style.getPropertyValue('contain');\n const contentVisCurrent = el.style.getPropertyValue('content-visibility');\n const containSizeCurrent = el.style.getPropertyValue('contain-intrinsic-size');\n\n if (contain !== 'off' && (!skipExisting || !containCurrent)) {\n el.style.setProperty('contain', contain);\n changed = true;\n }\n if (contentVisibility !== 'off' && (!skipExisting || !contentVisCurrent)) {\n el.style.setProperty('content-visibility', contentVisibility);\n changed = true;\n }\n if (containIntrinsicSize !== 'off' && (!skipExisting || !containSizeCurrent)) {\n el.style.setProperty('contain-intrinsic-size', containIntrinsicSize);\n changed = true;\n }\n\n if (changed) applied++;\n }\n\n if (_debug && applied > 0) {\n dbg('applyContainmentHints: applied to', applied, 'element(s)');\n }\n return applied;\n}\n\n// ── Pre-compiled regexes (avoid re-creation in hot paths) ──\n\nconst RE_STRING_SINGLE = /^'[^']*'$/;\nconst RE_STRING_DOUBLE = /^\"[^\"]*\"$/;\nconst RE_NUMBER = /^-?\\d+(\\.\\d+)?$/;\nconst RE_IDENTIFIER = /^[a-zA-Z_$]\\w*$/;\nconst RE_DOT_ACCESS = /^(\\w+)\\.(\\w+)$/;\nconst RE_DEEP_DOT = /^(\\w+)\\.(\\w+)\\.(\\w+)(?:\\.(\\w+))?$/;\nconst RE_BRACKET = /^(\\w+)\\[(\\d+|'[^']*'|\"[^\"]*\")\\]$/;\nconst RE_TERNARY = /^(.+?)\\s*\\?\\s*(.+?)\\s*:\\s*(.+)$/;\nconst RE_NULLISH = /^(.+?)\\s*\\?\\?\\s*(.+)$/;\nconst RE_AND = /^(.+?)\\s*&&\\s*(.+)$/;\nconst RE_OR = /^(.+?)\\s*\\|\\|\\s*(.+)$/;\nconst RE_COMPARISON = /^(.+?)\\s*(===|!==|==|!=|>=|<=|>|<)\\s*(.+)$/;\nconst RE_MUL = /^(.+?)\\s*([*/%])\\s*(.+)$/;\nconst RE_ADD = /^(.+?)\\s*([+-])\\s*(.+)$/;\nconst RE_TEMPLATE_LIT = /^`([^`]*)`$/;\nconst RE_TEMPLATE_INTERP = /\\$\\{([^}]+)\\}/g;\nconst RE_METHOD_CALL = /^(\\w+)\\.(\\w+)\\((.*)\\)$/;\nconst RE_GROUP_METHOD_CALL = /^\\((.+)\\)\\.(\\w+)\\((.*)\\)$/;\nconst RE_STRIP_BRACES = /^\\{|\\}$/g;\nconst RE_ITEM_TEMPLATE = /\\{item\\.?(\\w*)\\}/g;\nconst RE_DIGIT_ONLY = /^\\d+$/;\nconst RE_POST_INCR = /^(\\w+)(\\+\\+|--)$/;\nconst RE_PRE_INCR = /^(\\+\\+|--)(\\w+)$/;\nconst RE_TOGGLE = /^(\\w+)\\s*=\\s*!(\\w+)$/;\nconst RE_ASSIGN = /^(\\w+)\\s*=\\s*(.+)$/;\nconst RE_COMPOUND = /^(\\w+)\\s*(\\+=|-=|\\*=|\\/=)\\s*(.+)$/;\nconst RE_IF_PREFIX = /^if\\b/;\n// RE_UNQUOTED_KEYS removed in v0.5.0 — relaxed JSON parsing corrupted URLs\n// and string values containing colons. Use valid JSON in data-forma-state.\nconst RE_COMPUTED = /^(\\w+)\\s*=\\s*(.+)$/;\nconst RE_FETCH = /^(.+?)(?:→|->)\\s*(\\S+)(.*)$/;\nconst RE_FETCH_METHOD = /^(GET|POST|PUT|PATCH|DELETE)\\s+(.+)$/i;\nconst RE_STRIP_ITEM_BRACES = /^\\{item\\.?|\\}$/g;\n// Detect expressions referencing DOM event parameters — these can't be resolved\n// through scope getters and must fall through to the new Function handler path.\nconst RE_EVENT_REF = /\\bevent\\s*[.([]|\\$event\\b/;\nconst RE_REFETCH_CALL = /^\\$refetch\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)$/;\n\ninterface TransitionSpec {\n enter: string[];\n enterFrom: string[];\n enterTo: string[];\n leave: string[];\n leaveFrom: string[];\n leaveTo: string[];\n enterDurationMs?: number;\n leaveDurationMs?: number;\n}\n\ninterface ElementTransitionState {\n token: number;\n cancel: (() => void) | null;\n}\n\nconst TRANSITION_STATE_SYM = Symbol.for('forma-transition-state');\n\n// ── Expression factory cache ──\n// Maps expression string -> factory function that takes a scope and returns a getter.\n// This avoids re-parsing the same expression pattern across different scopes.\ntype ExpressionFactory = (scope: Scope) => (() => unknown) | null;\nconst EXPRESSION_CACHE_MAX = 2048;\nconst expressionCache = new Map<string, ExpressionFactory>();\nfunction cacheExpression(key: string, factory: ExpressionFactory): void {\n if (expressionCache.size >= EXPRESSION_CACHE_MAX) {\n // Evict oldest entry (first inserted)\n const first = expressionCache.keys().next().value;\n if (first !== undefined) expressionCache.delete(first);\n }\n expressionCache.set(key, factory);\n}\nlet scopeExpressionCache = new WeakMap<Scope, Map<string, () => unknown>>();\n\ninterface HandlerBuildResult {\n handler: (e: Event) => void;\n supported: boolean;\n}\n\nlet scopeHandlerCache = new WeakMap<Scope, Map<string, HandlerBuildResult>>();\n\n// ── Compiled template cache ──\n// Pre-splits template text into static/dynamic segments for fast re-evaluation.\ninterface CompiledTemplate {\n statics: string[];\n dynamics: string[]; // expression strings between {item.xxx}\n hasItemRef: boolean;\n}\n\nconst compiledTemplateCache = new Map<string, CompiledTemplate>();\nconst COMPILED_TEMPLATE_CACHE_MAX = 2048;\nfunction cacheCompiledTemplate(key: string, template: CompiledTemplate): void {\n if (compiledTemplateCache.size >= COMPILED_TEMPLATE_CACHE_MAX) {\n // Evict oldest entry (first inserted)\n const first = compiledTemplateCache.keys().next().value;\n if (first !== undefined) compiledTemplateCache.delete(first);\n }\n compiledTemplateCache.set(key, template);\n}\nconst UNSAFE_METHOD_NAMES = new Set([\n 'constructor', '__proto__', 'prototype',\n '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__',\n 'eval', 'Function',\n]);\n\n/**\n * Pre-compiled regexes for each blocked method name — avoids re-creating\n * RegExp objects on every call.\n */\nconst BLOCKED_METHOD_REGEXES: Array<{ name: string; dotRe: RegExp; bracketRe: RegExp }> = (() => {\n const result: Array<{ name: string; dotRe: RegExp; bracketRe: RegExp }> = [];\n for (const name of UNSAFE_METHOD_NAMES) {\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n result.push({\n name,\n // Match as property access (.name) or bare identifier at start\n dotRe: new RegExp(`(?:^|\\\\.)${escaped}(?:\\\\s*\\\\(|\\\\s*$|[^\\\\w$])`, 'm'),\n // Match bracket access with single quotes, double quotes, or backticks\n bracketRe: new RegExp(`\\\\[\\\\s*(?:'${escaped}'|\"${escaped}\"|` + '`' + escaped + '`' + `)\\\\s*\\\\]`),\n });\n }\n return result;\n})();\n\n/**\n * Scan an expression string for any UNSAFE_METHOD_NAMES usage.\n * Uses word-boundary matching to avoid false positives on substrings\n * (e.g. \"constructorValue\" should not match \"constructor\").\n *\n * Before scanning:\n * 1. Strips JS block comments and line comments\n * 2. Normalizes whitespace around dots (e.g. \"x . constructor\" → \"x.constructor\")\n * 3. Checks bracket access with static string literals and backtick templates\n * 4. Detects string concatenation inside brackets that could produce a blocked name\n *\n * Returns the matched blocked name, or null if clean.\n */\nfunction findBlockedMethod(expr: string): string | null {\n // Strip block comments (/* ... */)\n let cleaned = expr.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n // Strip line comments (// ... to end of line)\n cleaned = cleaned.replace(/\\/\\/[^\\n]*/g, '');\n // Normalize whitespace around dots: \"x . constructor\" → \"x.constructor\"\n cleaned = cleaned.replace(/\\s*\\.\\s*/g, '.');\n\n for (const { name, dotRe, bracketRe } of BLOCKED_METHOD_REGEXES) {\n if (dotRe.test(cleaned)) return name;\n if (bracketRe.test(cleaned)) return name;\n }\n\n // Layer 2: detect string concatenation inside brackets that could produce\n // a blocked name. Extract all bracket contents and check if concatenated\n // string fragments could form a blocked name.\n // e.g. x['constr' + 'uctor'] → extract 'constr' and 'uctor' → 'constructor'\n if (cleaned.includes('[')) {\n const bracketContents = extractBracketContents(cleaned);\n for (const content of bracketContents) {\n // Only check contents with concatenation operators\n if (!content.includes('+')) continue;\n // Extract all string literal fragments and join them\n const fragments = content.match(/['\"`]([^'\"`]*?)['\"`]/g);\n if (!fragments) continue;\n const joined = fragments.map(f => f.slice(1, -1)).join('');\n if (UNSAFE_METHOD_NAMES.has(joined)) return joined;\n }\n }\n\n return null;\n}\n\n/** Extract the contents of all bracket access expressions (between [ and ]). */\nfunction extractBracketContents(expr: string): string[] {\n const results: string[] = [];\n let depth = 0;\n let start = -1;\n for (let i = 0; i < expr.length; i++) {\n if (expr[i] === '[') {\n if (depth === 0) start = i + 1;\n depth++;\n } else if (expr[i] === ']') {\n depth--;\n if (depth === 0 && start >= 0) {\n results.push(expr.slice(start, i));\n start = -1;\n }\n }\n }\n return results;\n}\n\nconst TEXT_BINDING_SYM = Symbol.for('forma-text-binding-cache');\n\ninterface TextBindingCache {\n initialized: boolean;\n last: string;\n node: Text | null;\n}\n\nfunction toTextValue(value: unknown): string {\n if (value == null) return '';\n if (typeof value === 'string') return value;\n if (typeof value === 'symbol') return value.toString();\n return String(value);\n}\n\nfunction setElementTextFast(el: Element, next: string): void {\n let cache = (el as any)[TEXT_BINDING_SYM] as TextBindingCache | undefined;\n if (!cache) {\n cache = { initialized: false, last: '', node: null };\n (el as any)[TEXT_BINDING_SYM] = cache;\n }\n\n if (cache.initialized && cache.last === next) return;\n\n // Reuse direct text-node writes when this element is a single text child.\n let node = cache.node;\n if (!node || node.parentNode !== el || el.childNodes.length !== 1 || el.firstChild !== node) {\n if (el.childNodes.length === 1 && el.firstChild?.nodeType === Node.TEXT_NODE) {\n node = el.firstChild as Text;\n cache.node = node;\n } else {\n el.textContent = next;\n const first = el.firstChild;\n cache.node = (first && first.nodeType === Node.TEXT_NODE && el.childNodes.length === 1)\n ? (first as Text)\n : null;\n cache.last = next;\n cache.initialized = true;\n return;\n }\n }\n\n node.data = next;\n cache.last = next;\n cache.initialized = true;\n}\n\nfunction splitCallArgs(raw: string): string[] {\n const out: string[] = [];\n if (raw.trim() === '') return out;\n\n let depth = 0;\n let inSingle = false;\n let inDouble = false;\n let escaped = false;\n let start = 0;\n\n for (let i = 0; i < raw.length; i++) {\n const ch = raw[i]!;\n\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (ch === '\\\\') {\n escaped = true;\n continue;\n }\n\n if (inSingle) {\n if (ch === '\\'') inSingle = false;\n continue;\n }\n if (inDouble) {\n if (ch === '\"') inDouble = false;\n continue;\n }\n\n if (ch === '\\'') {\n inSingle = true;\n continue;\n }\n if (ch === '\"') {\n inDouble = true;\n continue;\n }\n\n if (ch === '(') {\n depth++;\n continue;\n }\n if (ch === ')') {\n if (depth > 0) depth--;\n continue;\n }\n\n if (ch === ',' && depth === 0) {\n out.push(raw.slice(start, i).trim());\n start = i + 1;\n }\n }\n\n out.push(raw.slice(start).trim());\n return out.filter(Boolean);\n}\n\nfunction readBalancedSegment(\n input: string,\n start: number,\n open: string,\n close: string,\n): { inner: string; end: number } | null {\n if (input[start] !== open) return null;\n\n let depth = 0;\n let inSingle = false;\n let inDouble = false;\n let inTemplate = false;\n let escaped = false;\n\n for (let i = start; i < input.length; i++) {\n const ch = input[i]!;\n\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (ch === '\\\\' && (inSingle || inDouble || inTemplate)) {\n escaped = true;\n continue;\n }\n\n if (inSingle) {\n if (ch === '\\'') inSingle = false;\n continue;\n }\n if (inDouble) {\n if (ch === '\"') inDouble = false;\n continue;\n }\n if (inTemplate) {\n if (ch === '`') inTemplate = false;\n continue;\n }\n\n if (ch === '\\'') {\n inSingle = true;\n continue;\n }\n if (ch === '\"') {\n inDouble = true;\n continue;\n }\n if (ch === '`') {\n inTemplate = true;\n continue;\n }\n\n if (ch === open) {\n depth++;\n continue;\n }\n if (ch === close) {\n depth--;\n if (depth === 0) {\n return {\n inner: input.slice(start + 1, i),\n end: i,\n };\n }\n }\n }\n\n return null;\n}\n\nfunction splitTopLevelStatements(raw: string): string[] {\n const input = raw.trim();\n if (!input) return [];\n\n const out: string[] = [];\n let depthParen = 0;\n let depthBrace = 0;\n let depthBracket = 0;\n let inSingle = false;\n let inDouble = false;\n let inTemplate = false;\n let escaped = false;\n let start = 0;\n\n for (let i = 0; i < input.length; i++) {\n const ch = input[i]!;\n\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (ch === '\\\\' && (inSingle || inDouble || inTemplate)) {\n escaped = true;\n continue;\n }\n\n if (inSingle) {\n if (ch === '\\'') inSingle = false;\n continue;\n }\n if (inDouble) {\n if (ch === '\"') inDouble = false;\n continue;\n }\n if (inTemplate) {\n if (ch === '`') inTemplate = false;\n continue;\n }\n\n if (ch === '\\'') {\n inSingle = true;\n continue;\n }\n if (ch === '\"') {\n inDouble = true;\n continue;\n }\n if (ch === '`') {\n inTemplate = true;\n continue;\n }\n\n if (ch === '(') depthParen++;\n else if (ch === ')' && depthParen > 0) depthParen--;\n else if (ch === '{') depthBrace++;\n else if (ch === '}' && depthBrace > 0) depthBrace--;\n else if (ch === '[') depthBracket++;\n else if (ch === ']' && depthBracket > 0) depthBracket--;\n\n if (ch === ';' && depthParen === 0 && depthBrace === 0 && depthBracket === 0) {\n const stmt = input.slice(start, i).trim();\n if (stmt) out.push(stmt);\n start = i + 1;\n }\n }\n\n const tail = input.slice(start).trim();\n if (tail) out.push(tail);\n return out;\n}\n\nfunction consumeStatement(raw: string): { body: string; rest: string } | null {\n const input = raw.trim();\n if (!input) return null;\n\n if (input.startsWith('{')) {\n const block = readBalancedSegment(input, 0, '{', '}');\n if (!block) return null;\n const body = block.inner.trim();\n let rest = input.slice(block.end + 1).trim();\n if (rest.startsWith(';')) rest = rest.slice(1).trim();\n return { body, rest };\n }\n\n let depthParen = 0;\n let depthBrace = 0;\n let depthBracket = 0;\n let inSingle = false;\n let inDouble = false;\n let inTemplate = false;\n let escaped = false;\n\n for (let i = 0; i < input.length; i++) {\n const ch = input[i]!;\n\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (ch === '\\\\' && (inSingle || inDouble || inTemplate)) {\n escaped = true;\n continue;\n }\n\n if (inSingle) {\n if (ch === '\\'') inSingle = false;\n continue;\n }\n if (inDouble) {\n if (ch === '\"') inDouble = false;\n continue;\n }\n if (inTemplate) {\n if (ch === '`') inTemplate = false;\n continue;\n }\n\n if (ch === '\\'') {\n inSingle = true;\n continue;\n }\n if (ch === '\"') {\n inDouble = true;\n continue;\n }\n if (ch === '`') {\n inTemplate = true;\n continue;\n }\n\n if (ch === '(') depthParen++;\n else if (ch === ')' && depthParen > 0) depthParen--;\n else if (ch === '{') depthBrace++;\n else if (ch === '}' && depthBrace > 0) depthBrace--;\n else if (ch === '[') depthBracket++;\n else if (ch === ']' && depthBracket > 0) depthBracket--;\n\n if (ch === ';' && depthParen === 0 && depthBrace === 0 && depthBracket === 0) {\n return {\n body: input.slice(0, i).trim(),\n rest: input.slice(i + 1).trim(),\n };\n }\n }\n\n return {\n body: input,\n rest: '',\n };\n}\n\nfunction parseIfHandler(expr: string, scope: Scope): ((e: Event) => void) | null {\n const input = expr.trim();\n if (!RE_IF_PREFIX.test(input)) return null;\n\n // If the expression references DOM event parameters (`event`, `$event`),\n // bail out — these aren't in scope getters and must use new Function.\n if (RE_EVENT_REF.test(input)) return null;\n\n let idx = 2;\n while (idx < input.length && /\\s/.test(input[idx]!)) idx++;\n if (input[idx] !== '(') return null;\n\n const condSegment = readBalancedSegment(input, idx, '(', ')');\n if (!condSegment) return null;\n\n const condExpr = parseExpression(condSegment.inner.trim(), scope);\n if (!condExpr) return null;\n\n let rest = input.slice(condSegment.end + 1).trim();\n const thenStmt = consumeStatement(rest);\n if (!thenStmt || !thenStmt.body) return null;\n\n const thenHandler = parseHandler(thenStmt.body, scope);\n if (!thenHandler) return null;\n\n rest = thenStmt.rest.trim();\n let elseHandler: ((e: Event) => void) | null = null;\n if (rest.startsWith('else')) {\n rest = rest.slice('else'.length).trim();\n const elseStmt = consumeStatement(rest);\n if (!elseStmt || !elseStmt.body) return null;\n elseHandler = parseHandler(elseStmt.body, scope);\n if (!elseHandler) return null;\n rest = elseStmt.rest.trim();\n }\n\n if (rest.length > 0) return null;\n\n return (e: Event) => {\n batch(() => {\n if (condExpr()) thenHandler(e);\n else elseHandler?.(e);\n });\n };\n}\n\nfunction unwrapOuterParens(raw: string): string {\n let expr = raw.trim();\n while (expr.startsWith('(')) {\n const segment = readBalancedSegment(expr, 0, '(', ')');\n if (!segment || segment.end !== expr.length - 1) break;\n const inner = segment.inner.trim();\n if (!inner) break;\n expr = inner;\n }\n return expr;\n}\n\nfunction compileTemplate(text: string): CompiledTemplate {\n const cached = compiledTemplateCache.get(text);\n if (cached) return cached;\n\n const statics: string[] = [];\n const dynamics: string[] = [];\n let lastIndex = 0;\n // Use a fresh regex each time since it has the 'g' flag\n const re = /\\{item\\.?(\\w*)\\}/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n statics.push(text.slice(lastIndex, m.index));\n dynamics.push(m[1]!); // the key after \"item.\" (empty string means whole item)\n lastIndex = re.lastIndex;\n }\n statics.push(text.slice(lastIndex));\n\n const result: CompiledTemplate = {\n statics,\n dynamics,\n hasItemRef: dynamics.length > 0,\n };\n cacheCompiledTemplate(text, result);\n return result;\n}\n\n// ── Template text caching for data-list ──\n\n/** Maps text nodes to their compiled template (pre-split static/dynamic segments). */\nconst templateTexts = new WeakMap<Node, CompiledTemplate>();\n\n/**\n * Resolve template placeholders in a text string using pre-compiled template.\n * Concatenates static segments with evaluated dynamic segments.\n */\nfunction resolveTemplate(text: string, item: unknown): string {\n const compiled = compileTemplate(text);\n return evaluateCompiledTemplate(compiled, item);\n}\n\n/**\n * Evaluate a pre-compiled template against an item.\n * Only evaluates dynamic parts and concatenates with static segments.\n */\nfunction evaluateCompiledTemplate(compiled: CompiledTemplate, item: unknown): string {\n if (!compiled.hasItemRef) return compiled.statics[0]!;\n let result = compiled.statics[0]!;\n for (let i = 0; i < compiled.dynamics.length; i++) {\n const key = compiled.dynamics[i]!;\n if (!key) {\n result += typeof item === 'object' ? JSON.stringify(item) : String(item ?? '');\n } else {\n result += String((item as Record<string, unknown>)?.[key] ?? '');\n }\n result += compiled.statics[i + 1] ?? '';\n }\n return result;\n}\n\n/**\n * Clone a template element and apply item data to all text node placeholders.\n * Stores the original template text in a WeakMap so updates can re-apply without re-cloning.\n */\nfunction cloneWithTemplateData(template: Element, item: unknown): Element {\n const clone = template.cloneNode(true) as Element;\n const walker = document.createTreeWalker(clone, NodeFilter.SHOW_TEXT);\n while (walker.nextNode()) {\n const node = walker.currentNode;\n const text = node.textContent ?? '';\n if (text.includes('{item')) {\n const compiled = compileTemplate(text);\n templateTexts.set(node, compiled); // Store compiled template\n node.textContent = evaluateCompiledTemplate(compiled, item);\n }\n }\n // Also process attributes (e.g. data-key, href, src, etc.)\n cloneAttributeTemplates(clone, item);\n return clone;\n}\n\n/**\n * Update an existing cloned element's text nodes with new item data.\n * Uses the cached original template patterns from the WeakMap.\n */\nfunction updateTemplateData(el: Element, item: unknown): void {\n const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);\n while (walker.nextNode()) {\n const node = walker.currentNode;\n const compiled = templateTexts.get(node);\n if (compiled) {\n node.textContent = evaluateCompiledTemplate(compiled, item);\n }\n }\n}\n\n/** WeakMap for caching compiled attribute templates */\nconst templateAttrs = new WeakMap<Element, Array<{ attr: string; compiled: CompiledTemplate }>>();\n\n/**\n * Process attribute templates on a cloned element and its descendants.\n * Pre-compiles patterns and resolves them with item data.\n */\n/** Directive attribute names/prefixes that bindElement processes — these must NOT be\n * template-interpolated by cloneAttributeTemplates because their values will be\n * evaluated by the reactive binding system using the child scope. */\nconst DIRECTIVE_ATTR_PREFIXES = [\n 'data-list', 'data-show', 'data-text', 'data-if', 'data-model',\n 'data-on:', 'data-class:', 'data-bind:', 'data-computed', 'data-persist', 'data-fetch',\n 'data-transition', 'data-transition:',\n];\nfunction isDirectiveAttr(name: string): boolean {\n for (const prefix of DIRECTIVE_ATTR_PREFIXES) {\n if (name === prefix || name.startsWith(prefix)) return true;\n }\n return false;\n}\n\nfunction splitClassTokens(raw: string | null): string[] {\n if (!raw) return [];\n return raw\n .trim()\n .split(/\\s+/)\n .map((t) => t.trim())\n .filter(Boolean);\n}\n\nfunction parseDurationTokenMs(token: string): number | null {\n const t = token.trim().toLowerCase();\n if (t.endsWith('ms')) {\n const n = Number(t.slice(0, -2));\n return Number.isFinite(n) && n >= 0 ? n : null;\n }\n if (t.endsWith('s')) {\n const n = Number(t.slice(0, -1));\n return Number.isFinite(n) && n >= 0 ? n * 1000 : null;\n }\n return null;\n}\n\nfunction parseClassTokensAndDuration(raw: string | null): { classes: string[]; durationMs?: number } {\n const classes: string[] = [];\n let durationMs: number | undefined;\n for (const token of splitClassTokens(raw)) {\n const parsed = parseDurationTokenMs(token);\n if (parsed != null) {\n durationMs = parsed;\n } else {\n classes.push(token);\n }\n }\n return { classes, durationMs };\n}\n\nfunction uniqueTokens(tokens: string[]): string[] {\n return Array.from(new Set(tokens.filter(Boolean)));\n}\n\nfunction parseCssTimeListMs(raw: string): number[] {\n if (!raw) return [];\n return raw\n .split(',')\n .map((part) => parseDurationTokenMs(part.trim()))\n .filter((ms): ms is number => ms != null);\n}\n\nfunction maxCombinedTimingsMs(durations: number[], delays: number[]): number {\n if (durations.length === 0 && delays.length === 0) return 0;\n if (durations.length === 0) return Math.max(...delays, 0);\n if (delays.length === 0) return Math.max(...durations, 0);\n\n const len = Math.max(durations.length, delays.length);\n let max = 0;\n for (let i = 0; i < len; i++) {\n const d = durations[i % durations.length] ?? 0;\n const delay = delays[i % delays.length] ?? 0;\n if (d + delay > max) max = d + delay;\n }\n return max;\n}\n\nfunction resolveTransitionDurationMs(el: HTMLElement, explicitMs?: number): number {\n if (typeof explicitMs === 'number') return explicitMs;\n const cs = window.getComputedStyle(el);\n const trans = maxCombinedTimingsMs(\n parseCssTimeListMs(cs.transitionDuration),\n parseCssTimeListMs(cs.transitionDelay),\n );\n const anim = maxCombinedTimingsMs(\n parseCssTimeListMs(cs.animationDuration),\n parseCssTimeListMs(cs.animationDelay),\n );\n return Math.max(trans, anim);\n}\n\nfunction getTransitionState(el: HTMLElement): ElementTransitionState {\n const existing = (el as any)[TRANSITION_STATE_SYM] as ElementTransitionState | undefined;\n if (existing) return existing;\n const created: ElementTransitionState = { token: 0, cancel: null };\n (el as any)[TRANSITION_STATE_SYM] = created;\n return created;\n}\n\nfunction clearTransitionState(el: HTMLElement): void {\n const state = (el as any)[TRANSITION_STATE_SYM] as ElementTransitionState | undefined;\n if (state?.cancel) {\n state.cancel();\n }\n delete (el as any)[TRANSITION_STATE_SYM];\n}\n\nfunction parseTransitionSpec(el: Element): TransitionSpec | null {\n const hasTransitionAttr = el.hasAttribute('data-transition')\n || Array.from(el.attributes).some((a) => a.name.startsWith('data-transition:'));\n if (!hasTransitionAttr) return null;\n\n const base = parseClassTokensAndDuration(el.getAttribute('data-transition')).classes;\n\n const enter = parseClassTokensAndDuration(el.getAttribute('data-transition:enter'));\n const leave = parseClassTokensAndDuration(el.getAttribute('data-transition:leave'));\n const enterFrom = splitClassTokens(\n el.getAttribute('data-transition:enter-from')\n ?? el.getAttribute('data-transition:enter-start'),\n );\n const enterTo = splitClassTokens(\n el.getAttribute('data-transition:enter-to')\n ?? el.getAttribute('data-transition:enter-end'),\n );\n const leaveFrom = splitClassTokens(\n el.getAttribute('data-transition:leave-from')\n ?? el.getAttribute('data-transition:leave-start'),\n );\n const leaveTo = splitClassTokens(\n el.getAttribute('data-transition:leave-to')\n ?? el.getAttribute('data-transition:leave-end'),\n );\n\n const durationBoth = parseDurationTokenMs(el.getAttribute('data-transition:duration') ?? '');\n const enterDuration = parseDurationTokenMs(el.getAttribute('data-transition:duration-enter') ?? '')\n ?? enter.durationMs\n ?? durationBoth\n ?? undefined;\n const leaveDuration = parseDurationTokenMs(el.getAttribute('data-transition:duration-leave') ?? '')\n ?? leave.durationMs\n ?? durationBoth\n ?? undefined;\n\n return {\n enter: uniqueTokens([...base, ...enter.classes]),\n enterFrom: uniqueTokens(enterFrom),\n enterTo: uniqueTokens(enterTo),\n leave: uniqueTokens([...base, ...leave.classes]),\n leaveFrom: uniqueTokens(leaveFrom),\n leaveTo: uniqueTokens(leaveTo),\n enterDurationMs: enterDuration,\n leaveDurationMs: leaveDuration,\n };\n}\n\nfunction removeClasses(el: Element, classes: string[]): void {\n for (const cls of classes) {\n el.classList.remove(cls);\n }\n}\n\nfunction addClasses(el: Element, classes: string[]): void {\n for (const cls of classes) {\n el.classList.add(cls);\n }\n}\n\nfunction runTransitionPhase(\n el: HTMLElement,\n phaseClasses: { base: string[]; from: string[]; to: string[]; durationMs?: number },\n onDone: () => void,\n): () => void {\n const cleanupClasses = uniqueTokens([\n ...phaseClasses.base,\n ...phaseClasses.from,\n ...phaseClasses.to,\n ]);\n\n let done = false;\n let timeoutId: number | null = null;\n let raf1: number | null = null;\n let raf2: number | null = null;\n\n const finish = () => {\n if (done) return;\n done = true;\n if (timeoutId != null) window.clearTimeout(timeoutId);\n if (raf1 != null) cancelAnimationFrame(raf1);\n if (raf2 != null) cancelAnimationFrame(raf2);\n removeClasses(el, cleanupClasses);\n onDone();\n };\n\n addClasses(el, phaseClasses.base);\n addClasses(el, phaseClasses.from);\n removeClasses(el, phaseClasses.to);\n\n raf1 = requestAnimationFrame(() => {\n raf2 = requestAnimationFrame(() => {\n if (done) return;\n removeClasses(el, phaseClasses.from);\n addClasses(el, phaseClasses.to);\n\n const ms = resolveTransitionDurationMs(el, phaseClasses.durationMs);\n if (ms <= 0) {\n finish();\n return;\n }\n timeoutId = window.setTimeout(finish, ms + 25);\n });\n });\n\n return finish;\n}\n\n/**\n * Insert an element into the DOM and optionally run an enter transition.\n * The element is functional immediately — the animation is purely visual.\n */\nfunction transitionInsert(\n el: HTMLElement,\n parent: Node,\n ref: Node | null,\n spec: TransitionSpec | null,\n): void {\n parent.insertBefore(el, ref);\n if (!spec) return;\n\n const state = getTransitionState(el);\n state.token += 1;\n const token = state.token;\n if (state.cancel) state.cancel();\n\n state.cancel = runTransitionPhase(\n el,\n {\n base: spec.enter,\n from: spec.enterFrom,\n to: spec.enterTo,\n durationMs: spec.enterDurationMs,\n },\n () => {\n const current = getTransitionState(el);\n if (current.token === token) current.cancel = null;\n },\n );\n}\n\n/**\n * Run a leave transition on an element, then call onDone when complete.\n * Sets data-forma-leaving immediately so the element is excluded from diffs.\n * If no transition spec, calls onDone synchronously.\n */\nfunction transitionRemove(\n el: HTMLElement,\n spec: TransitionSpec | null,\n onDone: () => void,\n): void {\n // Guard: if already leaving, don't start another leave\n if (el.hasAttribute('data-forma-leaving')) {\n onDone();\n return;\n }\n\n if (!spec) {\n onDone();\n return;\n }\n\n el.setAttribute('data-forma-leaving', '');\n\n const state = getTransitionState(el);\n state.token += 1;\n const token = state.token;\n if (state.cancel) state.cancel();\n\n state.cancel = runTransitionPhase(\n el,\n {\n base: spec.leave,\n from: spec.leaveFrom,\n to: spec.leaveTo,\n durationMs: spec.leaveDurationMs,\n },\n () => {\n const current = getTransitionState(el);\n if (current.token === token) current.cancel = null;\n el.removeAttribute('data-forma-leaving');\n onDone();\n },\n );\n}\n\nfunction applyShowVisibility(\n el: HTMLElement,\n visible: boolean,\n transition: TransitionSpec | null,\n initial: boolean,\n): void {\n if (!transition || initial) {\n el.style.display = visible ? '' : 'none';\n if (transition) {\n removeClasses(el, uniqueTokens([\n ...transition.enter, ...transition.enterFrom, ...transition.enterTo,\n ...transition.leave, ...transition.leaveFrom, ...transition.leaveTo,\n ]));\n }\n return;\n }\n\n const state = getTransitionState(el);\n state.token += 1;\n const token = state.token;\n if (state.cancel) state.cancel();\n state.cancel = null;\n\n if (visible) {\n el.style.display = '';\n state.cancel = runTransitionPhase(\n el,\n {\n base: transition.enter,\n from: transition.enterFrom,\n to: transition.enterTo,\n durationMs: transition.enterDurationMs,\n },\n () => {\n const current = getTransitionState(el);\n if (current.token === token) current.cancel = null;\n },\n );\n return;\n }\n\n state.cancel = runTransitionPhase(\n el,\n {\n base: transition.leave,\n from: transition.leaveFrom,\n to: transition.leaveTo,\n durationMs: transition.leaveDurationMs,\n },\n () => {\n const current = getTransitionState(el);\n if (current.token !== token) return;\n el.style.display = 'none';\n current.cancel = null;\n },\n );\n}\n\nfunction cloneAttributeTemplates(el: Element, item: unknown): void {\n const all = [el, ...Array.from(el.querySelectorAll('*'))];\n for (const node of all) {\n const entries: Array<{ attr: string; compiled: CompiledTemplate }> = [];\n for (const attr of Array.from(node.attributes)) {\n // Skip directive attributes — they'll be evaluated by bindElement with the child scope\n if (isDirectiveAttr(attr.name)) continue;\n if (attr.value.includes('{item')) {\n const compiled = compileTemplate(attr.value);\n entries.push({ attr: attr.name, compiled });\n node.setAttribute(attr.name, evaluateCompiledTemplate(compiled, item));\n }\n }\n if (entries.length > 0) {\n templateAttrs.set(node, entries);\n }\n }\n}\n\n// ── Chained access / optional chaining parser ──\n\n/**\n * Represents a single step in a property/method chain.\n * - type 'prop': property access (`.name` or `?.name`)\n * - type 'call': method call (`.method(args)` or `?.method(args)`)\n */\ninterface ChainStep {\n type: 'prop' | 'call';\n name: string;\n optional: boolean; // true for `?.`\n argFns?: Array<() => unknown>; // only for 'call' type\n}\n\n/**\n * Parse an expression that starts with an identifier and is followed by\n * zero or more chain steps: `.prop`, `?.prop`, `.method(args)`, `?.method(args)`.\n * Returns null if the expression doesn't match this pattern.\n *\n * Handles: \"user.name\", \"user?.name\", \"str.trim().toUpperCase()\",\n * \"obj?.method()\", \"items.filter(x).map(y)\", \"a.b.c.d\" (any depth).\n */\nfunction parseChainedAccess(expr: string, scope: Scope): (() => unknown) | null {\n // Must start with an identifier (or Math)\n let pos = 0;\n const identMatch = expr.match(/^[a-zA-Z_$]\\w*/);\n if (!identMatch) return null;\n\n const rootName = identMatch[0]!;\n pos = rootName.length;\n\n // Must have at least one chain step after the identifier\n if (pos >= expr.length) return null;\n // Next char must be '.' or '?' (for '?.')\n if (expr[pos] !== '.' && !(expr[pos] === '?' && expr[pos + 1] === '.')) return null;\n\n const steps: ChainStep[] = [];\n\n while (pos < expr.length) {\n let optional = false;\n\n // Check for `?.` (optional chaining) or `.` (regular access)\n if (expr[pos] === '?' && expr[pos + 1] === '.') {\n optional = true;\n pos += 2;\n } else if (expr[pos] === '.') {\n pos += 1;\n } else {\n // Not a chain continuation — unexpected character\n return null;\n }\n\n // Parse property/method name\n const nameMatch = expr.slice(pos).match(/^\\w+/);\n if (!nameMatch) return null;\n const name = nameMatch[0]!;\n pos += name.length;\n\n if (UNSAFE_METHOD_NAMES.has(name)) return () => undefined;\n\n // Check if this is a method call: followed by `(`\n if (pos < expr.length && expr[pos] === '(') {\n const balanced = readBalancedSegment(expr, pos, '(', ')');\n if (!balanced) return null;\n\n const argsRaw = balanced.inner.trim();\n const argFns: Array<() => unknown> = [];\n for (const arg of splitCallArgs(argsRaw)) {\n const parsed = parseExpression(arg, scope);\n if (!parsed) return null;\n argFns.push(parsed);\n }\n\n steps.push({ type: 'call', name, optional, argFns });\n pos = balanced.end + 1;\n } else {\n steps.push({ type: 'prop', name, optional });\n }\n }\n\n // If we didn't consume the entire expression, this isn't a simple chain\n if (pos !== expr.length) return null;\n\n // If there are no steps, fall back (just an identifier)\n if (steps.length === 0) return null;\n\n // Build the root expression getter\n const rootExpr = rootName === 'Math'\n ? (() => Math)\n : (() => scope.getters[rootName]?.());\n\n return () => {\n let val: any = rootExpr();\n for (const step of steps) {\n if (val == null) {\n if (step.optional) return undefined;\n // Non-optional access on null/undefined — use ?. semantics\n // (existing behavior used ?. for dot access)\n return undefined;\n }\n if (step.type === 'prop') {\n val = val[step.name];\n } else {\n const method = val[step.name];\n if (typeof method !== 'function') return undefined;\n const args = step.argFns!.map(fn => fn());\n val = method.apply(val, args);\n }\n }\n return val;\n };\n}\n\n// ── CSP-safe expression parser ──\n\n/**\n * Parse a simple expression into a closure that evaluates against the scope.\n * Handles common patterns without requiring `new Function()` or `eval`.\n * Returns null if the expression is too complex for the CSP-safe parser.\n */\nfunction parseExpression(expr: string, scope: Scope): (() => unknown) | null {\n // Check expression factory cache first\n const cachedFactory = expressionCache.get(expr);\n if (cachedFactory) return cachedFactory(scope);\n\n const result = parseExpressionUncached(expr, scope);\n\n // Cache factory functions for common simple patterns that can be re-bound to different scopes\n if (result !== null) {\n // Cache factories for simple patterns (identifier, dot access, etc.)\n // Complex patterns with sub-expressions are scope-dependent and harder to cache as factories,\n // but we can still cache the structural match result for them.\n // Keyword literals MUST be checked before RE_IDENTIFIER — \"true\", \"false\",\n // \"null\", \"undefined\" all match /^[a-zA-Z_$]\\w*$/ and would be incorrectly\n // cached as scope variable lookups (returning undefined).\n if (expr === 'true' || expr === 'false' || expr === 'null' || expr === 'undefined') {\n const val = expr === 'true' ? true : expr === 'false' ? false : expr === 'null' ? null : undefined;\n cacheExpression(expr, () => () => val);\n } else if (RE_IDENTIFIER.test(expr)) {\n cacheExpression(expr, (s) => () => s.getters[expr]?.());\n } else if (RE_STRING_SINGLE.test(expr) || RE_STRING_DOUBLE.test(expr)) {\n const val = expr.slice(1, -1);\n cacheExpression(expr, () => () => val);\n } else if (RE_NUMBER.test(expr)) {\n const val = Number(expr);\n cacheExpression(expr, () => () => val);\n } else {\n const dotMatch = expr.match(RE_DOT_ACCESS);\n if (dotMatch) {\n const p1 = dotMatch[1]!, p2 = dotMatch[2]!;\n cacheExpression(expr, (s) => () => {\n const obj = s.getters[p1]?.();\n return (obj as any)?.[p2];\n });\n }\n }\n }\n\n return result;\n}\n\n/**\n * Core expression parser — called on cache miss.\n * Uses pre-compiled module-level regexes for all pattern matching.\n */\nfunction parseExpressionUncached(expr: string, scope: Scope): (() => unknown) | null {\n expr = expr.trim();\n\n // Parenthesized group: \"(a + b)\", \"((count))\"\n const unwrapped = unwrapOuterParens(expr);\n if (unwrapped !== expr) {\n return parseExpression(unwrapped, scope);\n }\n\n // Literals first (before identifier check, since \\w matches digits)\n\n // String literals\n if (RE_STRING_SINGLE.test(expr) || RE_STRING_DOUBLE.test(expr)) {\n const val = expr.slice(1, -1);\n return () => val;\n }\n\n // Number literals\n if (RE_NUMBER.test(expr)) {\n const val = Number(expr);\n return () => val;\n }\n\n // Boolean / null / undefined literals\n if (expr === 'true') return () => true;\n if (expr === 'false') return () => false;\n if (expr === 'null') return () => null;\n if (expr === 'undefined') return () => undefined;\n\n // Simple identifier: \"count\", \"name\" (must start with letter/underscore/$)\n if (RE_IDENTIFIER.test(expr)) {\n return () => scope.getters[expr]?.();\n }\n\n // Chained access / method calls / optional chaining:\n // \"user.name\", \"user?.name\", \"str.trim().toUpperCase()\", \"obj?.method()\", \"items.filter(x).map(y)\"\n // Also handles simple dot access, deep dot access, and single method calls.\n {\n const chainResult = parseChainedAccess(expr, scope);\n if (chainResult) return chainResult;\n }\n\n // Grouped method call: \"(expr).method(args)\" — base is a parenthesized expression\n const groupedCallMatch = expr.match(RE_GROUP_METHOD_CALL);\n if (groupedCallMatch) {\n const baseRaw = groupedCallMatch[1]!.trim();\n const methodName = groupedCallMatch[2]!;\n const argsRaw = groupedCallMatch[3]!.trim();\n\n if (UNSAFE_METHOD_NAMES.has(methodName)) return () => undefined;\n\n const baseExpr = parseExpression(baseRaw, scope);\n if (!baseExpr) return null;\n\n const argFns: Array<() => unknown> = [];\n for (const arg of splitCallArgs(argsRaw)) {\n const parsed = parseExpression(arg, scope);\n if (!parsed) return null;\n argFns.push(parsed);\n }\n\n return () => {\n const base = baseExpr() as any;\n const method = base?.[methodName];\n if (typeof method !== 'function') return undefined;\n const args = argFns.map(fn => fn());\n return method.apply(base, args);\n };\n }\n\n // Negation: \"!active\", \"!user.loggedIn\"\n if (expr.startsWith('!')) {\n const inner = parseExpression(expr.slice(1).trim(), scope);\n if (inner) return () => !inner();\n }\n\n // Bracket access: \"items[0]\", \"obj['key']\"\n const bracketMatch = expr.match(RE_BRACKET);\n if (bracketMatch) {\n const objExpr = parseExpression(bracketMatch[1]!, scope);\n let key: string | number;\n const rawKey = bracketMatch[2]!;\n if (RE_DIGIT_ONLY.test(rawKey)) {\n key = Number(rawKey);\n } else {\n key = rawKey.slice(1, -1);\n }\n if (objExpr) {\n return () => (objExpr() as any)?.[key];\n }\n }\n\n // Array literal: \"[1, 2, 3]\", \"[item.name, item.id]\", \"['a', 'b']\"\n if (expr.startsWith('[')) {\n const balanced = readBalancedSegment(expr, 0, '[', ']');\n if (balanced && balanced.end === expr.length - 1) {\n const inner = balanced.inner.trim();\n if (inner === '') {\n // Empty array: []\n return () => [];\n }\n const elements = splitCallArgs(inner);\n const elementFns: Array<() => unknown> = [];\n let allParsed = true;\n for (const el of elements) {\n const parsed = parseExpression(el.trim(), scope);\n if (!parsed) { allParsed = false; break; }\n elementFns.push(parsed);\n }\n if (allParsed) {\n return () => elementFns.map(fn => fn());\n }\n }\n }\n\n // Ternary: \"expr ? a : b\"\n const ternaryMatch = expr.match(RE_TERNARY);\n if (ternaryMatch) {\n const cond = parseExpression(ternaryMatch[1]!.trim(), scope);\n const then = parseExpression(ternaryMatch[2]!.trim(), scope);\n const els = parseExpression(ternaryMatch[3]!.trim(), scope);\n if (cond && then && els) {\n return () => cond() ? then() : els();\n }\n }\n\n // Nullish coalescing: \"value ?? 'default'\"\n const nullishMatch = expr.match(RE_NULLISH);\n if (nullishMatch) {\n const left = parseExpression(nullishMatch[1]!.trim(), scope);\n const right = parseExpression(nullishMatch[2]!.trim(), scope);\n if (left && right) {\n return () => left() ?? right();\n }\n }\n\n // Logical OR: \"a || b\" (lower precedence than AND — checked first)\n const orMatch = expr.match(RE_OR);\n if (orMatch) {\n const left = parseExpression(orMatch[1]!.trim(), scope);\n const right = parseExpression(orMatch[2]!.trim(), scope);\n if (left && right) {\n return () => left() || right();\n }\n }\n\n // Logical AND: \"a && b\" (higher precedence than OR — checked after)\n const andMatch = expr.match(RE_AND);\n if (andMatch) {\n const left = parseExpression(andMatch[1]!.trim(), scope);\n const right = parseExpression(andMatch[2]!.trim(), scope);\n if (left && right) {\n return () => left() && right();\n }\n }\n\n // Comparison operators: ===, !==, ==, !=, >=, <=, >, <\n const compMatch = expr.match(RE_COMPARISON);\n if (compMatch) {\n const left = parseExpression(compMatch[1]!.trim(), scope);\n const right = parseExpression(compMatch[3]!.trim(), scope);\n if (left && right) {\n const op = compMatch[2]!;\n return () => {\n const l = left(), r = right();\n switch (op) {\n case '===': return l === r;\n case '!==': return l !== r;\n case '==': return l == r;\n case '!=': return l != r;\n case '>': return (l as number) > (r as number);\n case '<': return (l as number) < (r as number);\n case '>=': return (l as number) >= (r as number);\n case '<=': return (l as number) <= (r as number);\n }\n };\n }\n }\n\n // Arithmetic: +, -, *, /, %\n // Addition/subtraction first (lower precedence — checked first), then * / %\n const addMatch = expr.match(RE_ADD);\n if (addMatch) {\n const left = parseExpression(addMatch[1]!.trim(), scope);\n const right = parseExpression(addMatch[3]!.trim(), scope);\n if (left && right) {\n const op = addMatch[2]!;\n return () => {\n const l = left(), r = right();\n if (op === '+') return (l as any) + (r as any);\n return (l as number) - (r as number);\n };\n }\n }\n\n // Multiplication / division / modulo (higher precedence — checked after addition)\n const mulMatch = expr.match(RE_MUL);\n if (mulMatch) {\n const left = parseExpression(mulMatch[1]!.trim(), scope);\n const right = parseExpression(mulMatch[3]!.trim(), scope);\n if (left && right) {\n const op = mulMatch[2]!;\n return () => {\n const l = left() as number, r = right() as number;\n switch (op) {\n case '*': return l * r;\n case '/': return l / r;\n case '%': return l % r;\n }\n };\n }\n }\n\n // Template literals: `Hello ${name}`\n const tmplMatch = expr.match(RE_TEMPLATE_LIT);\n if (tmplMatch) {\n const raw = tmplMatch[1]!;\n // Pre-split template literal into static/dynamic segments\n const staticParts: string[] = [];\n const dynamicFns: (() => unknown)[] = [];\n let lastIndex = 0;\n // Create a fresh regex since RE_TEMPLATE_INTERP has the 'g' flag\n const re = new RegExp(RE_TEMPLATE_INTERP.source, 'g');\n let m: RegExpExecArray | null;\n while ((m = re.exec(raw)) !== null) {\n staticParts.push(raw.slice(lastIndex, m.index));\n const inner = parseExpression(m[1]!.trim(), scope);\n if (!inner) return null; // Can't parse inner expression\n dynamicFns.push(inner);\n lastIndex = re.lastIndex;\n }\n staticParts.push(raw.slice(lastIndex));\n\n // Optimized evaluation: concatenate instead of map+join\n return () => {\n let result = staticParts[0]!;\n for (let i = 0; i < dynamicFns.length; i++) {\n result += String(dynamicFns[i]!() ?? '');\n result += staticParts[i + 1] ?? '';\n }\n return result;\n };\n }\n\n // Can't parse — return null for fallback\n return null;\n}\n\n// ── Expression evaluator ──\n\nfunction getScopeCache<T>(cache: WeakMap<Scope, Map<string, T>>, scope: Scope): Map<string, T> {\n let scoped = cache.get(scope);\n if (!scoped) {\n scoped = new Map<string, T>();\n cache.set(scope, scoped);\n }\n return scoped;\n}\n\n/** Build an actionable hint for expressions/handlers that failed CSP-safe parsing. */\nfunction cspExpressionHint(expr: string): string {\n if (expr.includes('...')) {\n return `Unsupported expression in CSP-safe mode: spread syntax detected. Use .concat() instead, or enable unsafe-eval via setUnsafeEval(true).`;\n }\n // Note: optional chaining (?.) is now supported by the CSP-safe parser.\n if (expr.includes('=>')) {\n return `Unsupported expression in CSP-safe mode: arrow function detected. Extract logic to a data-computed attribute, or enable unsafe-eval via setUnsafeEval(true).`;\n }\n return `Unsupported expression in CSP-safe mode. Simplify the expression or enable unsafe-eval via setUnsafeEval(true).`;\n}\n\nfunction buildEvaluator(expr: string, scope: Scope): () => unknown {\n const cleaned = expr.replace(RE_STRIP_BRACES, '').trim();\n const cache = getScopeCache(scopeExpressionCache, scope);\n const cached = cache.get(cleaned);\n if (cached) return cached;\n\n // Try CSP-safe parsing first\n const cspFn = parseExpression(cleaned, scope);\n if (cspFn) {\n cache.set(cleaned, cspFn);\n return cspFn;\n }\n\n // Fallback to Function constructor (for complex expressions)\n if (!_allowUnsafeEval) {\n dbg('buildEvaluator: blocked unsafe eval fallback for expression:', cleaned);\n reportDiagnostic('expression-unsupported', cleaned, cspExpressionHint(cleaned));\n const blocked = () => undefined;\n cache.set(cleaned, blocked);\n return blocked;\n }\n\n // Apply UNSAFE_METHOD_NAMES blocklist before new Function — prevents\n // prototype-pollution and eval injection via the unsafe eval path.\n const blockedMethod = findBlockedMethod(cleaned);\n if (blockedMethod) {\n const msg = `Blocked unsafe method \"${blockedMethod}\" in expression`;\n reportDiagnostic('expression-unsupported', cleaned, msg);\n throw new Error(`[FormaJS] ${msg}: ${cleaned}`);\n }\n\n try {\n const fn = new Function('__scope', `with(__scope) { return (${cleaned}); }`);\n // Cache proxy — scope.getters is a mutable object, so the proxy\n // always reflects current state without needing to be recreated.\n const proxy = new Proxy(Object.create(null) as Record<string, unknown>, {\n has(_, key: string) { return key in scope.getters; },\n get(_, key: string) {\n // Defense-in-depth: block dangerous property access even if\n // findBlockedMethod missed a bypass (e.g. computed bracket names)\n if (UNSAFE_METHOD_NAMES.has(key)) return undefined;\n const g = scope.getters[key];\n return g ? g() : undefined;\n },\n });\n const unsafe = () => fn(proxy);\n cache.set(cleaned, unsafe);\n return unsafe;\n } catch {\n reportDiagnostic('expression-unsupported', cleaned, 'Expression too complex for CSP-safe mode. Enable unsafe-eval via FormaRuntime.unsafeEval = true, or use the standard (non-hardened) build.');\n const failed = () => undefined;\n cache.set(cleaned, failed);\n return failed;\n }\n}\n\n// ── CSP-safe handler parser ──\n\n/**\n * Parse common handler patterns without `new Function()`.\n * Returns null if the expression is too complex for the CSP-safe parser.\n */\nfunction parseHandler(expr: string, scope: Scope): ((e: Event) => void) | null {\n const normalized = expr.trim().replace(/;+$/g, '').trim();\n if (!normalized) return null;\n\n const ifHandler = parseIfHandler(normalized, scope);\n if (ifHandler) return ifHandler;\n\n const stmts = splitTopLevelStatements(normalized);\n if (stmts.length > 1) {\n const handlers = stmts.map(s => parseHandler(s, scope));\n if (handlers.every(h => h !== null)) {\n return (e: Event) => {\n batch(() => {\n for (const h of handlers) h!(e);\n });\n };\n }\n return null;\n }\n\n const single = stmts[0] ?? normalized;\n\n // count++ or count--\n const incrMatch = single.match(RE_POST_INCR);\n if (incrMatch) {\n const name = incrMatch[1]!;\n const op = incrMatch[2]!;\n return () => {\n batch(() => {\n const val = scope.getters[name]?.() as number ?? 0;\n scope.setters[name]?.(op === '++' ? val + 1 : val - 1);\n });\n };\n }\n\n // ++count or --count\n const preIncrMatch = single.match(RE_PRE_INCR);\n if (preIncrMatch) {\n const op = preIncrMatch[1]!;\n const name = preIncrMatch[2]!;\n return () => {\n batch(() => {\n const val = scope.getters[name]?.() as number ?? 0;\n scope.setters[name]?.(op === '++' ? val + 1 : val - 1);\n });\n };\n }\n\n // prop = !prop (toggle)\n const toggleMatch = single.match(RE_TOGGLE);\n if (toggleMatch && toggleMatch[1] === toggleMatch[2]) {\n const name = toggleMatch[1]!;\n return () => {\n batch(() => {\n scope.setters[name]?.(!scope.getters[name]?.());\n });\n };\n }\n\n // prop = expr (simple assignment)\n const assignMatch = single.match(RE_ASSIGN);\n if (assignMatch) {\n const name = assignMatch[1]!;\n const valExpr = parseExpression(assignMatch[2]!.trim(), scope);\n if (valExpr) {\n if (_debug) dbg(`parseHandler: assignment \"${name} = ...\" — setter exists:`, !!scope.setters[name], ', getter exists:', !!scope.getters[name]);\n return () => {\n batch(() => {\n const val = valExpr();\n if (_debug) dbg(`SETTER: ${name} = ${val} (was: ${scope.getters[name]?.()})`);\n scope.setters[name]?.(val);\n });\n };\n }\n }\n\n // prop += value, prop -= value, prop *= value, prop /= value\n const compoundMatch = single.match(RE_COMPOUND);\n if (compoundMatch) {\n const name = compoundMatch[1]!;\n const op = compoundMatch[2]!;\n const valExpr = parseExpression(compoundMatch[3]!.trim(), scope);\n if (valExpr) {\n return () => {\n batch(() => {\n const current = scope.getters[name]?.() as number ?? 0;\n const val = valExpr() as number;\n switch (op) {\n case '+=': scope.setters[name]?.(current + val); break;\n case '-=': scope.setters[name]?.(current - val); break;\n case '*=': scope.setters[name]?.(current * val); break;\n case '/=': scope.setters[name]?.(current / val); break;\n }\n });\n };\n }\n }\n\n // $refetch('id') — imperative data-fetch trigger (CSP-safe)\n const refetchMatch = single.match(RE_REFETCH_CALL);\n if (refetchMatch) {\n const fetchId = refetchMatch[1]!;\n return () => $refetch(fetchId);\n }\n\n return null;\n}\n\nfunction buildHandler(expr: string, scope: Scope): HandlerBuildResult {\n // Strip balanced outer braces (e.g., `{count++}` → `count++`) but NOT\n // unbalanced ones like `if (x) { a = b }` where the `}` is a code-block close.\n let cleaned = expr.trim();\n if (cleaned.startsWith('{')) {\n const seg = readBalancedSegment(cleaned, 0, '{', '}');\n if (seg && seg.end === cleaned.length - 1) {\n cleaned = seg.inner.trim();\n }\n }\n const cache = getScopeCache(scopeHandlerCache, scope);\n const cached = cache.get(cleaned);\n if (cached) return cached;\n\n // Try CSP-safe parsing first\n const cspFn = parseHandler(cleaned, scope);\n if (cspFn) {\n const result: HandlerBuildResult = { handler: cspFn, supported: true };\n cache.set(cleaned, result);\n return result;\n }\n\n // Fallback to Function constructor (for complex expressions)\n // Use a Proxy with getters and setters so the handler can both read and\n // mutate state (e.g. \"count++\", \"active = !active\").\n if (!_allowUnsafeEval) {\n dbg('buildHandler: blocked unsafe eval fallback for expression:', cleaned);\n reportDiagnostic('handler-unsupported', cleaned, cspExpressionHint(cleaned));\n const result: HandlerBuildResult = {\n handler: () => {},\n supported: false,\n };\n cache.set(cleaned, result);\n return result;\n }\n\n // Apply UNSAFE_METHOD_NAMES blocklist before new Function — prevents\n // prototype-pollution and eval injection via the unsafe eval path.\n const blockedMethod = findBlockedMethod(cleaned);\n if (blockedMethod) {\n const msg = `Blocked unsafe method \"${blockedMethod}\" in handler`;\n reportDiagnostic('handler-unsupported', cleaned, msg);\n throw new Error(`[FormaJS] ${msg}: ${cleaned}`);\n }\n\n try {\n // Accept both `$event` and bare `event` — Claude sometimes generates either.\n const fn = new Function('__scope', '$event', 'event', `with(__scope) { ${cleaned} }`);\n // Cache proxy — scope.getters/setters are mutable objects, so the proxy\n // always reflects current state without needing to be recreated.\n const proxy = new Proxy(Object.create(null) as Record<string, unknown>, {\n has(_, key: string) {\n // Do NOT intercept '$event' or 'event' — let them fall through to\n // function parameters so $event.key, event.stopPropagation(), etc. work.\n if (key === '$event' || key === 'event') return false;\n return key in scope.getters || key in scope.setters;\n },\n get(_, key: string) {\n // Defense-in-depth: block dangerous property access\n if (UNSAFE_METHOD_NAMES.has(key)) return undefined;\n const g = scope.getters[key];\n return g ? g() : undefined;\n },\n set(_, key: string, value: unknown) {\n const s = scope.setters[key];\n if (s) s(value);\n return true;\n },\n });\n const unsafeHandler = (e: Event) => {\n batch(() => fn(proxy, e, e));\n };\n const result: HandlerBuildResult = {\n handler: unsafeHandler,\n supported: true,\n };\n cache.set(cleaned, result);\n return result;\n } catch {\n reportDiagnostic('handler-unsupported', cleaned, 'Expression too complex for CSP-safe mode. Enable unsafe-eval via FormaRuntime.unsafeEval = true, or use the standard (non-hardened) build.');\n const result: HandlerBuildResult = {\n handler: () => {},\n supported: false,\n };\n cache.set(cleaned, result);\n return result;\n }\n}\n\n// ── State initialization ──\n\nconst FORBIDDEN_STATE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction parseState(raw: string): Record<string, unknown> {\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(raw);\n } catch {\n if (_debug) {\n dbg('parseState: Invalid JSON in data-forma-state — use valid JSON with quoted keys. Got:', raw.slice(0, 200));\n }\n return {};\n }\n // Strip prototype-pollution keys\n for (const key of FORBIDDEN_STATE_KEYS) {\n if (key in parsed) delete parsed[key];\n }\n return parsed;\n}\n\n// ── DOM scanner ──\n\nfunction initScope(stateEl: Element): Scope {\n const raw = stateEl.getAttribute('data-forma-state') ?? '{}';\n const state = parseState(raw);\n const keys = Object.keys(state);\n if (_debug) {\n dbg('initScope: parsed', keys.length, 'keys:', keys.join(', '));\n if (keys.length === 0) {\n dbg('initScope: WARNING — empty state! Raw attribute:', raw.slice(0, 200));\n }\n }\n const getters: Record<string, Getter> = {};\n const setters: Record<string, Setter> = {};\n\n for (const [key, initial] of Object.entries(state)) {\n const [get, set] = createSignal(initial);\n getters[key] = get;\n setters[key] = set as Setter;\n }\n\n // Inject $refetch as a callable getter so handlers can use $refetch('id')\n getters['$refetch'] = () => $refetch;\n\n return { getters, setters };\n}\n\n// ── Safe $el proxy ──\n// Allowlist of properties exposed on the $el magic. Everything else\n// (ownerDocument, parentNode, innerHTML, …) returns undefined so that\n// attacker-authored expressions cannot escape to window/document.\n\nconst SAFE_EL_PROPS = new Set([\n // Identity & attributes\n 'id', 'className', 'tagName', 'nodeName',\n 'getAttribute', 'setAttribute', 'removeAttribute', 'hasAttribute', 'toggleAttribute',\n 'dataset', 'classList',\n // Content\n 'textContent', 'innerText',\n // Form elements\n 'value', 'checked', 'disabled', 'selected', 'type', 'name', 'placeholder',\n 'readOnly', 'required', 'min', 'max', 'step', 'pattern',\n // Dimensions & position\n 'getBoundingClientRect', 'offsetWidth', 'offsetHeight',\n 'offsetTop', 'offsetLeft', 'clientWidth', 'clientHeight',\n 'scrollWidth', 'scrollHeight', 'scrollTop', 'scrollLeft',\n // Style\n 'style', 'hidden',\n // Focus & interaction\n 'focus', 'blur', 'click', 'scrollIntoView', 'scrollTo',\n // Traversal (safe — returns elements, not window/document)\n 'closest', 'matches', 'querySelector', 'querySelectorAll',\n 'children', 'childElementCount', 'firstElementChild', 'lastElementChild',\n 'nextElementSibling', 'previousElementSibling',\n]);\n\nfunction createSafeElProxy(el: Element): Element {\n return new Proxy(el, {\n get(target, prop) {\n if (typeof prop === 'symbol') return Reflect.get(target, prop);\n if (!SAFE_EL_PROPS.has(prop)) return undefined;\n const val = Reflect.get(target, prop);\n return typeof val === 'function' ? val.bind(target) : val;\n },\n set(target, prop, value) {\n if (typeof prop === 'symbol') return false;\n if (!SAFE_EL_PROPS.has(prop)) return false;\n return Reflect.set(target, prop, value);\n },\n });\n}\n\nfunction bindElement(el: Element, scope: Scope, disposers: (() => void)[]): void {\n // Inject per-element magics: $el and $dispatch\n // Each element gets its own child scope so $el resolves to the correct element.\n const elMagics: Record<string, unknown> = {\n $el: createSafeElProxy(el),\n $dispatch: (name: string, detail?: unknown) => {\n el.dispatchEvent(new CustomEvent(name, {\n bubbles: true,\n composed: true, // crosses Shadow DOM boundaries (important for <forma-stage>)\n detail,\n }));\n },\n };\n scope = createChildScope(scope, elMagics);\n\n // When the server provides a directive map, we know exactly which directives\n // this element has. Skip getAttribute calls for directives it doesn't have.\n // `known` is null when no map is available (fallback: check everything).\n const known = getDirectives(el);\n\n // data-computed=\"name = expr\" or \"a = expr1; b = expr2\"\n const computedAttr = (!known || known.has('data-computed')) ? el.getAttribute('data-computed') : null;\n if (computedAttr) {\n // Split multi-statement computed: \"a = expr1; b = expr2; c = expr3\"\n // Uses lookahead to split at \"; identifier =\" boundaries without\n // breaking arrow functions (=>) or comparisons (===, ==).\n const parts = computedAttr.split(/;\\s*(?=\\w+\\s*=[^=])/);\n for (const part of parts) {\n const trimmed = part.trim();\n if (!trimmed) continue;\n const match = trimmed.match(RE_COMPUTED);\n if (match) {\n const name = match[1]!;\n const expr = match[2]!;\n // Remove the computed name from getters before building evaluator\n // to prevent self-referential cycle (computed reading itself)\n const prevGetter = scope.getters[name];\n delete scope.getters[name];\n const evaluate = buildEvaluator(`{${expr}}`, scope);\n const getter = createComputed(evaluate);\n scope.getters[name] = getter;\n // Keep the original setter so manual overrides still work\n if (!prevGetter) {\n // If there was no initial state entry, remove the setter too\n delete scope.setters[name];\n }\n }\n }\n }\n\n // data-text=\"{expr}\"\n const textExpr = (!known || known.has('data-text')) ? el.getAttribute('data-text') : null;\n if (textExpr) {\n const evaluate = buildEvaluator(textExpr, scope);\n const dispose = internalEffect(() => {\n setElementTextFast(el, toTextValue(evaluate()));\n });\n disposers.push(dispose);\n }\n\n // data-show=\"{expr}\"\n const showExpr = (!known || known.has('data-show')) ? el.getAttribute('data-show') : null;\n if (showExpr) {\n const evaluate = buildEvaluator(showExpr, scope);\n const transition = parseTransitionSpec(el);\n if (_debug) {\n const tag = el.tagName.toLowerCase();\n const cls = el.className ? `.${String(el.className).split(' ')[0]}` : '';\n dbg(`bindElement: data-show=\"${showExpr}\" on <${tag}${cls}>`);\n }\n let initialized = false;\n const dispose = internalEffect(() => {\n const visible = !!evaluate();\n if (_debug) dbg(`data-show effect: \"${showExpr}\" → ${visible}`);\n applyShowVisibility(el as HTMLElement, visible, transition, !initialized);\n initialized = true;\n });\n disposers.push(dispose);\n if (transition) {\n disposers.push(() => clearTransitionState(el as HTMLElement));\n }\n }\n\n // data-if=\"{expr}\" — conditional DOM insertion/removal with optional transitions\n const ifExpr = (!known || known.has('data-if')) ? el.getAttribute('data-if') : null;\n if (ifExpr) {\n const evaluate = buildEvaluator(ifExpr, scope);\n const transition = parseTransitionSpec(el);\n const placeholder = document.createComment('forma-if');\n const parent = el.parentNode;\n let inserted = true;\n let initialized = false;\n\n const dispose = internalEffect(() => {\n const show = !!evaluate();\n\n if (show && !inserted) {\n // Cancel any in-flight leave\n clearTransitionState(el as HTMLElement);\n el.removeAttribute('data-forma-leaving');\n if (initialized && transition) {\n transitionInsert(el as HTMLElement, parent!, placeholder, transition);\n } else {\n parent?.insertBefore(el, placeholder);\n }\n inserted = true;\n } else if (!show && inserted) {\n if (initialized && transition) {\n transitionRemove(el as HTMLElement, transition, () => {\n if (el.parentNode) {\n parent?.insertBefore(placeholder, el);\n el.remove();\n }\n });\n } else {\n parent?.insertBefore(placeholder, el);\n el.remove();\n }\n inserted = false;\n }\n initialized = true;\n });\n\n disposers.push(dispose);\n if (transition) {\n disposers.push(() => clearTransitionState(el as HTMLElement));\n }\n }\n\n // data-model=\"{prop}\"\n const modelExpr = (!known || known.has('data-model')) ? el.getAttribute('data-model') : null;\n if (modelExpr) {\n const prop = modelExpr.replace(RE_STRIP_BRACES, '').trim();\n const getter = scope.getters[prop];\n const setter = scope.setters[prop];\n if (getter && setter) {\n const input = el as HTMLInputElement;\n const dispose = internalEffect(() => {\n const val = getter();\n if (input.type === 'checkbox') {\n input.checked = !!val;\n } else {\n input.value = String(val ?? '');\n }\n });\n disposers.push(dispose);\n const event = input.type === 'checkbox' ? 'change' : 'input';\n const onModelInput = () => {\n if (input.type === 'checkbox') {\n setter(input.checked);\n } else if (input.type === 'number' || input.type === 'range') {\n setter(Number(input.value));\n } else {\n setter(input.value);\n }\n };\n input.addEventListener(event, onModelInput);\n disposers.push(() => {\n input.removeEventListener(event, onModelInput);\n });\n }\n }\n\n // Single-pass over attributes for data-on:*, data-class:*, data-bind:*\n // When directive map is available, skip the loop entirely if none of these are present.\n const hasColonDirectives = !known || hasAnyPrefix(known, 'data-on:', 'data-class:', 'data-bind:');\n const attrs = el.attributes;\n if (hasColonDirectives) for (let i = 0; i < attrs.length; i++) {\n const attr = attrs[i]!;\n const name = attr.name;\n\n if (name.startsWith('data-on:')) {\n const event = name.slice(8); // 'data-on:'.length === 8\n const built = buildHandler(attr.value, scope);\n const handler = built.handler;\n if (_debug) {\n const tag = el.tagName.toLowerCase();\n const id = el.id ? `#${el.id}` : '';\n const cls = el.className ? `.${String(el.className).split(' ')[0]}` : '';\n dbg(`bindElement: data-on:${event}=\"${attr.value}\" on <${tag}${id}${cls}>`);\n }\n if (!built.supported) {\n el.setAttribute('data-forma-handler-error', 'unsupported');\n } else if (el.hasAttribute('data-forma-handler-error')) {\n el.removeAttribute('data-forma-handler-error');\n }\n if (_debug) {\n const attrVal = attr.value;\n const tracedHandler = (e: Event) => {\n dbg(`HANDLER FIRED: data-on:${event}=\"${attrVal}\"`, 'isTrusted:', e.isTrusted);\n handler(e);\n };\n el.addEventListener(event, tracedHandler);\n disposers.push(() => { el.removeEventListener(event, tracedHandler); });\n } else {\n el.addEventListener(event, handler);\n disposers.push(() => { el.removeEventListener(event, handler); });\n }\n } else if (name.startsWith('data-class:')) {\n const cls = name.slice(11); // 'data-class:'.length === 11\n const evaluate = buildEvaluator(attr.value, scope);\n const dispose = internalEffect(() => {\n el.classList.toggle(cls, !!evaluate());\n });\n disposers.push(dispose);\n } else if (name.startsWith('data-bind:')) {\n const attrName = name.slice(10); // 'data-bind:'.length === 10\n const evaluate = buildEvaluator(attr.value, scope);\n const dispose = internalEffect(() => {\n const val = evaluate();\n if (val == null || val === false) {\n el.removeAttribute(attrName);\n } else {\n el.setAttribute(attrName, String(val));\n }\n });\n disposers.push(dispose);\n }\n }\n\n // data-persist=\"{prop}\"\n const persistExpr = (!known || known.has('data-persist')) ? el.getAttribute('data-persist') : null;\n if (persistExpr) {\n const prop = persistExpr.replace(RE_STRIP_BRACES, '').trim();\n const getter = scope.getters[prop];\n const setter = scope.setters[prop];\n if (getter && setter) {\n const key = 'forma:' + prop;\n try {\n const saved = localStorage.getItem(key);\n if (saved !== null) setter(JSON.parse(saved));\n } catch { /* ignore parse errors */ }\n const dispose = internalEffect(() => {\n try { localStorage.setItem(key, JSON.stringify(getter())); } catch { /* quota */ }\n });\n disposers.push(dispose);\n }\n }\n\n // data-list=\"{expr}\" — keyed reconciliation with LIS\n const listExpr = (!known || known.has('data-list')) ? el.getAttribute('data-list') : null;\n if (listExpr) {\n const evaluate = buildEvaluator(listExpr, scope);\n const templateEl = el.children[0] as Element | undefined;\n if (templateEl) {\n const template = templateEl.cloneNode(true) as Element;\n // Remove original template from DOM\n el.removeChild(templateEl);\n\n // Detect key attribute: data-key=\"{item.id}\" -> extracts \"id\"\n const keyAttr = template.getAttribute('data-key');\n const keyProp = keyAttr\n ? keyAttr.replace(RE_STRIP_ITEM_BRACES, '').trim()\n : null;\n\n // Parse transition spec from the list container element\n const listTransition = parseTransitionSpec(el);\n\n let oldItems: unknown[] = [];\n let oldNodes: Node[] = [];\n\n // For index-based keying (no data-key), we wrap items in objects\n // that carry their index so the keyFn can extract it without a\n // second argument. For property-based keying, items pass through raw.\n interface IndexWrapped { __idx: number; __item: unknown }\n\n /** Dispose all bindings stored on a clone element */\n function disposeCloneBindings(node: Node): void {\n const el = node as any;\n if (Array.isArray(el.__formaDisposers)) {\n for (const d of el.__formaDisposers) {\n try { d(); } catch { /* ensure all disposers run */ }\n }\n delete el.__formaDisposers;\n }\n }\n\n /** Clone template, bind directives via child scope */\n function createBoundClone(item: unknown, index: number): Element {\n const clone = cloneWithTemplateData(template, item);\n const childScope = createChildScope(scope, { item, index });\n const itemDisposers: (() => void)[] = [];\n bindElement(clone, childScope, itemDisposers);\n for (const desc of Array.from(clone.querySelectorAll('*'))) {\n bindElement(desc, childScope, itemDisposers);\n }\n (clone as any).__formaDisposers = itemDisposers;\n return clone;\n }\n\n /** Dispose old bindings and rebind with fresh data */\n function updateBoundClone(node: Node, item: unknown, index: number): void {\n disposeCloneBindings(node);\n updateTemplateData(node as Element, item);\n const childScope = createChildScope(scope, { item, index });\n const itemDisposers: (() => void)[] = [];\n bindElement(node as Element, childScope, itemDisposers);\n for (const desc of Array.from((node as Element).querySelectorAll('*'))) {\n bindElement(desc, childScope, itemDisposers);\n }\n (node as any).__formaDisposers = itemDisposers;\n }\n\n // Build transition hooks for reconcileList (only when transition attrs present)\n const listHooks: ListTransitionHooks | undefined = listTransition ? {\n onInsert: (node: Node) => {\n const htmlEl = node as HTMLElement;\n if (!htmlEl.setAttribute) return; // text node guard\n const state = getTransitionState(htmlEl);\n state.token += 1;\n const token = state.token;\n if (state.cancel) state.cancel();\n state.cancel = runTransitionPhase(\n htmlEl,\n {\n base: listTransition.enter,\n from: listTransition.enterFrom,\n to: listTransition.enterTo,\n durationMs: listTransition.enterDurationMs,\n },\n () => {\n const current = getTransitionState(htmlEl);\n if (current.token === token) current.cancel = null;\n },\n );\n },\n onBeforeRemove: (node: Node, done: () => void) => {\n const htmlEl = node as HTMLElement;\n if (!htmlEl.setAttribute) { done(); return; } // text node guard\n disposeCloneBindings(node);\n transitionRemove(htmlEl, listTransition, () => {\n done();\n });\n },\n } : undefined;\n\n const dispose = internalEffect(() => {\n const rawItems = evaluate();\n if (!Array.isArray(rawItems)) {\n // Remove all — dispose bindings first\n for (const n of oldNodes) {\n disposeCloneBindings(n);\n el.removeChild(n);\n }\n oldItems = [];\n oldNodes = [];\n return;\n }\n\n // Cancel any in-flight leave animations before reconciliation\n if (listTransition) {\n const leavingNodes = el.querySelectorAll('[data-forma-leaving]');\n for (const ln of Array.from(leavingNodes)) {\n clearTransitionState(ln as HTMLElement);\n ln.removeAttribute('data-forma-leaving');\n if (ln.parentNode) ln.parentNode.removeChild(ln);\n }\n }\n\n // Snapshot old nodes before reconciliation to detect removals\n const prevNodes = new Set(oldNodes);\n\n if (keyProp) {\n // ── Property-based keying ──\n const result = reconcileList(\n el,\n oldItems,\n rawItems,\n oldNodes,\n (item: unknown) => String((item as Record<string, unknown>)?.[keyProp] ?? ''),\n (item: unknown) => {\n const idx = rawItems.indexOf(item);\n return createBoundClone(item, idx);\n },\n (node: Node, item: unknown) => {\n const idx = rawItems.indexOf(item);\n updateBoundClone(node, item, idx);\n },\n undefined, // beforeNode\n listHooks,\n );\n // Dispose bindings on nodes that were removed by reconcileList\n const nextNodes = new Set(result.nodes);\n for (const n of prevNodes) {\n if (!nextNodes.has(n)) {\n // Skip nodes mid-leave — onBeforeRemove already disposed them\n if ((n as Element).hasAttribute?.('data-forma-leaving')) continue;\n disposeCloneBindings(n);\n }\n }\n oldItems = result.items;\n oldNodes = result.nodes;\n } else {\n // ── Index-based keying ──\n // Wrap items so each carries its index as the key.\n const wrapped: IndexWrapped[] = rawItems.map((item, i) => ({ __idx: i, __item: item }));\n const oldWrapped = oldItems as IndexWrapped[];\n\n const result = reconcileList<IndexWrapped>(\n el,\n oldWrapped,\n wrapped,\n oldNodes,\n (w: IndexWrapped) => w.__idx,\n (w: IndexWrapped) => createBoundClone(w.__item, w.__idx),\n (node: Node, w: IndexWrapped) => updateBoundClone(node, w.__item, w.__idx),\n undefined, // beforeNode\n listHooks,\n );\n // Dispose bindings on nodes that were removed by reconcileList\n const nextNodes = new Set(result.nodes);\n for (const n of prevNodes) {\n if (!nextNodes.has(n)) {\n // Skip nodes mid-leave — onBeforeRemove already disposed them\n if ((n as Element).hasAttribute?.('data-forma-leaving')) continue;\n disposeCloneBindings(n);\n }\n }\n oldItems = result.items;\n oldNodes = result.nodes;\n }\n });\n disposers.push(dispose);\n }\n }\n\n // data-fetch=\"[METHOD] url → prop [|loading:prop] [|error:prop] [|poll:ms]\"\n const fetchExpr = (!known || known.has('data-fetch')) ? el.getAttribute('data-fetch') : null;\n if (fetchExpr) {\n const arrowMatch = fetchExpr.match(RE_FETCH);\n if (arrowMatch) {\n const urlPart = arrowMatch[1]!.trim();\n const target = arrowMatch[2]!.trim();\n const modifiers = arrowMatch[3]?.trim() ?? '';\n\n let method = 'GET';\n let url = urlPart;\n const methodMatch = urlPart.match(RE_FETCH_METHOD);\n if (methodMatch) {\n method = methodMatch[1]!.toUpperCase();\n url = methodMatch[2]!.trim();\n }\n\n let loadingTarget: string | undefined;\n let errorTarget: string | undefined;\n let interval: number | undefined;\n for (const mod of modifiers.split('|').filter(Boolean)) {\n const [k, v] = mod.split(':').map(s => s.trim());\n if (k === 'loading') loadingTarget = v;\n else if (k === 'error') errorTarget = v;\n else if (k === 'poll') interval = parseInt(v ?? '0', 10);\n }\n\n // Create signals for target, loading, and error\n const [getTarget, setTarget] = createSignal<unknown>(null);\n scope.getters[target] = getTarget;\n scope.setters[target] = setTarget as Setter;\n if (loadingTarget) {\n const [gl, sl] = createSignal(false);\n scope.getters[loadingTarget] = gl;\n scope.setters[loadingTarget] = sl as Setter;\n }\n if (errorTarget) {\n const [ge, se] = createSignal<unknown>(null);\n scope.getters[errorTarget] = ge;\n scope.setters[errorTarget] = se as Setter;\n }\n\n const doFetch = () => {\n if (loadingTarget) scope.setters[loadingTarget]!(true);\n fetch(url, { method })\n .then(r => r.json())\n .then(data => {\n setTarget(data);\n if (loadingTarget) scope.setters[loadingTarget]!(false);\n })\n .catch(err => {\n if (errorTarget) scope.setters[errorTarget]!(err.message);\n if (loadingTarget) scope.setters[loadingTarget]!(false);\n });\n };\n\n // Register in $refetch registry if data-fetch-id is present\n const fetchId = el.getAttribute('data-fetch-id');\n if (fetchId) {\n _refetchRegistry.set(fetchId, doFetch);\n disposers.push(() => _refetchRegistry.delete(fetchId));\n }\n\n doFetch();\n if (interval && interval > 0) {\n const id = setInterval(doFetch, interval);\n disposers.push(() => clearInterval(id));\n }\n }\n }\n}\n\n// ── Scope mounting / unmounting (single data-forma-state element) ──\n\n/**\n * Mount a single `data-forma-state` element — creates signals, binds\n * all descendants, stores disposers on the element for cleanup.\n * Idempotent: skips elements that are already mounted.\n */\n/** CSS selector matching elements with at least one Forma directive.\n * Avoids scanning every descendant — only visits directive-bearing elements. */\nconst DIRECTIVE_SELECTOR = [\n '[data-text]', '[data-show]', '[data-if]', '[data-model]',\n '[data-computed]', '[data-persist]', '[data-list]', '[data-fetch]',\n '[data-bind\\\\:*]', '[data-class\\\\:*]', '[data-on\\\\:*]',\n // Catch-all for colon-prefixed data attrs that the escaped selectors miss in some engines\n '[data-transition]',\n].join(',');\n\n/** Fast check: does this element have any Forma directive attribute? */\nfunction hasDirective(el: Element): boolean {\n const attrs = el.attributes;\n for (let i = 0; i < attrs.length; i++) {\n const name = attrs[i]!.name;\n if (name.startsWith('data-text') || name.startsWith('data-show') ||\n name.startsWith('data-if') || name.startsWith('data-model') ||\n name.startsWith('data-computed') || name.startsWith('data-persist') ||\n name.startsWith('data-list') || name.startsWith('data-fetch') ||\n name.startsWith('data-on:') || name.startsWith('data-class:') ||\n name.startsWith('data-bind:') || name.startsWith('data-transition')) {\n return true;\n }\n }\n return false;\n}\n\n// ── Pre-compiled Directive Map ──\n//\n// When the server sends a directive_map sidecar (data-forma-id → directive names),\n// the runtime uses it in two ways:\n//\n// 1. mountScope(): targeted CSS selector queries only directive-bearing elements\n// instead of querySelectorAll('*') + attribute scan on every descendant.\n//\n// 2. bindElement(): skips getAttribute calls for directives the element doesn't\n// have, avoiding unnecessary work for elements with only 1-2 directives.\n\n/** Full map: data-forma-id → Set of directive attribute names. */\nlet _directiveMap: Map<string, Set<string>> | null = null;\n\n/**\n * Load a pre-compiled directive map from the server.\n * Keys are data-forma-id values, values are arrays of directive attribute names.\n */\nfunction setDirectiveMap(map: Record<string, string[]> | null): void {\n if (!map || Object.keys(map).length === 0) {\n _directiveMap = null;\n return;\n }\n _directiveMap = new Map();\n for (const id in map) {\n _directiveMap.set(id, new Set(map[id]!));\n }\n}\n\n/**\n * Build a CSS selector that targets only elements with known directives.\n * Returns null when the map has too many entries (selector would be huge)\n * or when no map is available.\n */\nfunction buildDirectiveSelector(): string | null {\n if (!_directiveMap || _directiveMap.size === 0) return null;\n // Cap at 200 IDs to avoid pathologically long selectors.\n // Above that, querySelectorAll('*') + Set check is likely faster.\n if (_directiveMap.size > 200) return null;\n const parts: string[] = [];\n for (const id of _directiveMap.keys()) {\n parts.push(`[data-forma-id=\"${id}\"]`);\n }\n return parts.join(',');\n}\n\n/** Get the directive set for an element, or null if unknown. */\nfunction getDirectives(el: Element): Set<string> | null {\n if (!_directiveMap) return null;\n const id = el.getAttribute('data-forma-id');\n if (!id) return null;\n return _directiveMap.get(id) ?? null;\n}\n\n/** Check if any entry in a Set starts with one of the given prefixes. */\nfunction hasAnyPrefix(set: Set<string>, ...prefixes: string[]): boolean {\n for (const entry of set) {\n for (const prefix of prefixes) {\n if (entry.startsWith(prefix)) return true;\n }\n }\n return false;\n}\n\nfunction mountScope(root: Element): void {\n // Idempotency guard — never double-bind\n if ((root as any).__formaDisposers) {\n if (_debug) dbg('mountScope: SKIPPED (already mounted)');\n return;\n }\n\n const scope = initScope(root);\n const disposers: (() => void)[] = [];\n\n // Bind the root itself\n bindElement(root, scope, disposers);\n\n // Bind only directive-bearing descendants (skip inert elements).\n // When the server provides a directive map, we build a targeted CSS selector\n // that queries only elements with known directives — no querySelectorAll('*').\n let boundCount = 0;\n const selector = buildDirectiveSelector();\n if (selector) {\n // Fast path: query only elements the server told us have directives\n const targets = root.querySelectorAll(selector);\n for (let i = 0; i < targets.length; i++) {\n bindElement(targets[i]!, scope, disposers);\n boundCount++;\n }\n } else {\n // Fallback: scan all descendants and check attributes\n const descendants = root.querySelectorAll('*');\n for (let i = 0; i < descendants.length; i++) {\n const el = descendants[i]!;\n if (hasDirective(el)) {\n bindElement(el, scope, disposers);\n boundCount++;\n }\n }\n }\n\n // Store disposers on the root element for cleanup\n (root as any).__formaDisposers = disposers;\n // Expose scope for devtools (State Inspector panel)\n (root as any).__formaScope = scope;\n (root as any).__formaInitialState = root.getAttribute('data-forma-state') ?? '{}';\n if (_debug) dbg('mountScope: DONE —', boundCount, 'elements bound,', disposers.length, 'disposers', selector ? '(targeted)' : '(full scan)');\n}\n\n/**\n * Unmount a single `data-forma-state` element — disposes all effects,\n * intervals, and event listeners. Safe to call on already-unmounted elements.\n */\nfunction unmountScope(root: Element): void {\n const disposers = (root as any).__formaDisposers as (() => void)[] | undefined;\n if (disposers) {\n for (const d of disposers) {\n try { d(); } catch { /* ensure all disposers run */ }\n }\n delete (root as any).__formaDisposers;\n delete (root as any).__formaScope;\n delete (root as any).__formaInitialState;\n }\n}\n\n// ── MutationObserver — auto-discovery of new data-forma-state elements ──\n//\n// Cost: O(addedNodes) per mutation batch. Never re-scans the whole document.\n// The observer only fires for childList mutations (nodes added/removed) and\n// attribute mutations on the `data-forma-state` attribute specifically.\n\nlet _observer: MutationObserver | null = null;\nconst ELEMENT_NODE = 1;\nconst MUTATION_CHUNK_SIZE = 40;\nlet _pendingMutations: MutationRecord[] = [];\nlet _drainingMutations = false;\n\nfunction processMutation(mutation: MutationRecord): void {\n // ── Removed nodes: clean up disposers to prevent memory leaks ──\n for (let i = 0; i < mutation.removedNodes.length; i++) {\n const node = mutation.removedNodes[i]!;\n if (node.nodeType !== ELEMENT_NODE) continue;\n const el = node as Element;\n if (el.hasAttribute('data-forma-state')) {\n if (_debug) dbg('MutationObserver: REMOVED scope');\n unmountScope(el);\n }\n const removed = el.querySelectorAll('[data-forma-state]');\n for (let j = 0; j < removed.length; j++) {\n unmountScope(removed[j]!);\n }\n }\n\n // ── Added nodes: auto-mount new scopes ──\n for (let i = 0; i < mutation.addedNodes.length; i++) {\n const node = mutation.addedNodes[i]!;\n if (node.nodeType !== ELEMENT_NODE) continue;\n const el = node as Element;\n if (el.closest('[data-forma-leaving]')) continue;\n if (el.hasAttribute('data-forma-state')) {\n if (_debug) dbg('MutationObserver: ADDED scope via mutation');\n mountScope(el);\n }\n const added = el.querySelectorAll('[data-forma-state]');\n if (_debug && added.length > 0) {\n dbg('MutationObserver: found', added.length, 'nested scope(s) in added subtree');\n }\n for (let j = 0; j < added.length; j++) {\n const desc = added[j]!;\n if (desc.closest('[data-forma-leaving]')) continue;\n mountScope(desc);\n }\n }\n\n // ── Attribute change: data-forma-state added/removed/changed ──\n if (mutation.type === 'attributes' && mutation.attributeName === 'data-forma-state') {\n const target = mutation.target as Element;\n // Always unmount first (cleans up old bindings)\n unmountScope(target);\n // Re-mount if the attribute still exists (value may have changed)\n if (target.hasAttribute('data-forma-state')) {\n mountScope(target);\n }\n }\n}\n\nasync function drainMutationQueue(): Promise<void> {\n try {\n while (_pendingMutations.length > 0) {\n const batch = _pendingMutations.splice(0, MUTATION_CHUNK_SIZE);\n for (let i = 0; i < batch.length; i++) {\n processMutation(batch[i]!);\n }\n if (_pendingMutations.length > 0) {\n await yieldToMain();\n }\n }\n } finally {\n _drainingMutations = false;\n // Handle races where new mutations were queued after the while-check.\n if (_pendingMutations.length > 0 && !_drainingMutations) {\n _drainingMutations = true;\n void drainMutationQueue();\n }\n }\n}\n\nfunction handleMutations(mutations: MutationRecord[]): void {\n if (_debug) dbg('MutationObserver: queued', mutations.length, 'mutation(s)');\n _pendingMutations.push(...mutations);\n if (_drainingMutations) return;\n _drainingMutations = true;\n void drainMutationQueue();\n}\n\nfunction startObserver(): void {\n if (_observer) return;\n _observer = new MutationObserver(handleMutations);\n const target = document.body || document.documentElement;\n if (target) {\n _observer.observe(target, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['data-forma-state'],\n });\n }\n}\n\nfunction stopObserver(): void {\n if (_observer) {\n _observer.disconnect();\n _observer = null;\n }\n}\n\n// ── Main init ──\n\nfunction initRuntime(): void {\n if (_autoContainment) {\n applyContainmentHints(document, { skipIfAlreadySet: true });\n }\n const stateRoots = document.querySelectorAll('[data-forma-state]');\n if (_debug) dbg('initRuntime: found', stateRoots.length, 'scope(s)');\n for (const root of Array.from(stateRoots)) {\n mountScope(root);\n }\n // Start auto-discovery after initial scan\n startObserver();\n if (_debug) dbg('initRuntime: MutationObserver started');\n}\n\n/** Dispose all FormaJS scopes — clears effects, intervals, event listeners, and stops the observer. */\nfunction destroyRuntime(): void {\n stopObserver();\n const stateRoots = document.querySelectorAll('[data-forma-state]');\n for (const root of Array.from(stateRoots)) {\n unmountScope(root);\n }\n}\n\n/**\n * Mount a specific element or subtree — scans for `data-forma-state`\n * elements and initializes their reactive bindings.\n *\n * Use this for manual control when injecting HTML dynamically.\n * With the MutationObserver active, this is usually not needed.\n *\n * @param el - The root element to scan (checks itself and all descendants).\n */\nfunction mount(el: Element): void {\n if (el.hasAttribute('data-forma-state')) {\n mountScope(el);\n }\n const descendants = el.querySelectorAll('[data-forma-state]');\n for (const desc of Array.from(descendants)) {\n mountScope(desc);\n }\n}\n\n/**\n * Unmount a specific element or subtree — disposes all reactive bindings\n * for `data-forma-state` elements within.\n *\n * @param el - The root element to clean up (checks itself and all descendants).\n */\nfunction unmount(el: Element): void {\n if (el.hasAttribute('data-forma-state')) {\n unmountScope(el);\n }\n const descendants = el.querySelectorAll('[data-forma-state]');\n for (const desc of Array.from(descendants)) {\n unmountScope(desc);\n }\n}\n\n// Auto-init in browser contexts on DOMContentLoaded (or immediately if already loaded).\nif (typeof document !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', initRuntime);\n } else {\n initRuntime();\n }\n}\n\n/** Enable/disable debug logging. Also toggleable via window.__FORMA_DEBUG = true */\nfunction setDebug(on: boolean): void { _debug = on; }\n/** Set unsafe-eval mode. `locked-off` is hardened and non-toggleable via setUnsafeEval. */\nfunction setUnsafeEvalMode(mode: UnsafeEvalMode): void {\n if (_unsafeEvalMode === mode) return;\n _unsafeEvalMode = mode;\n if (mode === 'locked-off') _allowUnsafeEval = false;\n if (mode === 'locked-on') _allowUnsafeEval = true;\n if (mode === 'mutable') _allowUnsafeEval = true;\n // Rebuild caches whenever policy changes.\n scopeExpressionCache = new WeakMap<Scope, Map<string, () => unknown>>();\n scopeHandlerCache = new WeakMap<Scope, Map<string, HandlerBuildResult>>();\n}\n/** Enable/disable unsafe `new Function` fallback for complex expressions. */\nfunction setUnsafeEval(on: boolean): void {\n if (_unsafeEvalMode !== 'mutable') {\n dbg(\n `setUnsafeEval ignored (mode=${_unsafeEvalMode}); unsafe fallback is locked`,\n );\n return;\n }\n if (_allowUnsafeEval === on) return;\n _allowUnsafeEval = on;\n // Rebuild handlers/evaluators after mode change so cached blocked results\n // don't persist when toggling trusted mode at runtime.\n scopeExpressionCache = new WeakMap<Scope, Map<string, () => unknown>>();\n scopeHandlerCache = new WeakMap<Scope, Map<string, HandlerBuildResult>>();\n}\n/** Get current unsafe-eval policy mode. */\nfunction getUnsafeEvalMode(): UnsafeEvalMode { return _unsafeEvalMode; }\n/** Enable/disable runtime diagnostics for unsupported expressions/handlers. */\nfunction setDiagnostics(on: boolean): void { _diagnosticsEnabled = on; }\n\n/** Runtime diagnostics captured while parsing/binding templates. */\nfunction getDiagnostics(): RuntimeDiagnostic[] {\n return Array.from(diagnostics.values()).map(d => ({ ...d }));\n}\n\n/** Clear runtime diagnostics collected so far. */\nfunction clearDiagnostics(): void {\n diagnostics.clear();\n}\n\n// ── DevTools API — State Inspector ──\n\ninterface ScopeDescriptor {\n element: Element;\n id: string;\n values: Record<string, { value: unknown; type: string }>;\n initialJSON: string;\n}\n\n/**\n * DevTools: enumerate all active scopes and their current signal values.\n * Only called when the State Inspector panel is open — zero overhead otherwise.\n */\nfunction getScopes(): ScopeDescriptor[] {\n const roots = document.querySelectorAll('[data-forma-state]');\n const result: ScopeDescriptor[] = [];\n\n for (const root of Array.from(roots)) {\n if (root.closest('[data-forma-leaving]')) continue;\n const scope = (root as any).__formaScope as Scope | undefined;\n const initialJSON = (root as any).__formaInitialState as string | undefined;\n if (!scope) continue;\n\n const values: Record<string, { value: unknown; type: string }> = {};\n for (const key of Object.keys(scope.getters)) {\n const val = scope.getters[key]!();\n values[key] = { value: val, type: typeof val };\n }\n\n result.push({\n element: root,\n id: root.getAttribute('data-forma-id') || root.id || root.tagName.toLowerCase(),\n values,\n initialJSON: initialJSON ?? '{}',\n });\n }\n return result;\n}\n\n/**\n * DevTools: set a state value on a specific scope element.\n * Triggers normal reactive effects (data-show, data-text, etc.).\n */\nfunction setScopeValue(element: Element, key: string, value: unknown): void {\n const scope = (element as any).__formaScope as Scope | undefined;\n if (!scope?.setters[key]) return;\n batch(() => { scope.setters[key]!(value); });\n}\n\n/**\n * DevTools: reset all values on a scope to their initial JSON state.\n */\nfunction resetScope(element: Element): void {\n const scope = (element as any).__formaScope as Scope | undefined;\n const initialJSON = (element as any).__formaInitialState as string | undefined;\n if (!scope || !initialJSON) return;\n\n const initial = parseState(initialJSON);\n batch(() => {\n for (const [key, val] of Object.entries(initial)) {\n scope.setters[key]?.(val);\n }\n });\n}\n\n// ── Reconciler ──\n\nlet _reconciler: ((container: Element, html: string) => void) | null = null;\n\nfunction getReconciler() {\n if (!_reconciler) {\n _reconciler = createReconciler({\n mountScope,\n unmountScope,\n disconnectObserver() {\n if (_observer) {\n _observer.disconnect();\n }\n },\n reconnectObserver() {\n if (_observer) {\n const target = document.body || document.documentElement;\n if (target) {\n _observer.observe(target, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['data-forma-state'],\n });\n }\n }\n },\n batch,\n });\n }\n return _reconciler;\n}\n\n/** Reconcile a container's DOM against a new HTML string. */\nfunction reconcile(container: Element, html: string): void {\n getReconciler()(container, html);\n}\n\nexport {\n initRuntime,\n destroyRuntime,\n mount,\n unmount,\n reconcile,\n setDebug,\n setUnsafeEvalMode,\n getUnsafeEvalMode,\n setUnsafeEval,\n yieldToMain,\n applyContainmentHints,\n setDirectiveMap,\n setDiagnostics,\n getDiagnostics,\n clearDiagnostics,\n getScopes,\n setScopeValue,\n resetScope,\n};\n","export const ReactiveFlags = {\n None: 0,\n Mutable: 1,\n Watching: 2,\n RecursedCheck: 4,\n Recursed: 8,\n Dirty: 16,\n Pending: 32,\n};\nexport function createReactiveSystem({ update, notify, unwatched, }) {\n return {\n link,\n unlink,\n propagate,\n checkDirty,\n shallowPropagate,\n };\n function link(dep, sub, version) {\n const prevDep = sub.depsTail;\n if (prevDep !== undefined && prevDep.dep === dep) {\n return;\n }\n const nextDep = prevDep !== undefined ? prevDep.nextDep : sub.deps;\n if (nextDep !== undefined && nextDep.dep === dep) {\n nextDep.version = version;\n sub.depsTail = nextDep;\n return;\n }\n const prevSub = dep.subsTail;\n if (prevSub !== undefined && prevSub.version === version && prevSub.sub === sub) {\n return;\n }\n const newLink = sub.depsTail\n = dep.subsTail\n = {\n version,\n dep,\n sub,\n prevDep,\n nextDep,\n prevSub,\n nextSub: undefined,\n };\n if (nextDep !== undefined) {\n nextDep.prevDep = newLink;\n }\n if (prevDep !== undefined) {\n prevDep.nextDep = newLink;\n }\n else {\n sub.deps = newLink;\n }\n if (prevSub !== undefined) {\n prevSub.nextSub = newLink;\n }\n else {\n dep.subs = newLink;\n }\n }\n function unlink(link, sub = link.sub) {\n const dep = link.dep;\n const prevDep = link.prevDep;\n const nextDep = link.nextDep;\n const nextSub = link.nextSub;\n const prevSub = link.prevSub;\n if (nextDep !== undefined) {\n nextDep.prevDep = prevDep;\n }\n else {\n sub.depsTail = prevDep;\n }\n if (prevDep !== undefined) {\n prevDep.nextDep = nextDep;\n }\n else {\n sub.deps = nextDep;\n }\n if (nextSub !== undefined) {\n nextSub.prevSub = prevSub;\n }\n else {\n dep.subsTail = prevSub;\n }\n if (prevSub !== undefined) {\n prevSub.nextSub = nextSub;\n }\n else if ((dep.subs = nextSub) === undefined) {\n unwatched(dep);\n }\n return nextDep;\n }\n function propagate(link) {\n let next = link.nextSub;\n let stack;\n top: do {\n const sub = link.sub;\n let flags = sub.flags;\n if (!(flags & (4 | 8 | 16 | 32))) {\n sub.flags = flags | 32;\n }\n else if (!(flags & (4 | 8))) {\n flags = 0;\n }\n else if (!(flags & 4)) {\n sub.flags = (flags & ~8) | 32;\n }\n else if (!(flags & (16 | 32)) && isValidLink(link, sub)) {\n sub.flags = flags | (8 | 32);\n flags &= 1;\n }\n else {\n flags = 0;\n }\n if (flags & 2) {\n notify(sub);\n }\n if (flags & 1) {\n const subSubs = sub.subs;\n if (subSubs !== undefined) {\n const nextSub = (link = subSubs).nextSub;\n if (nextSub !== undefined) {\n stack = { value: next, prev: stack };\n next = nextSub;\n }\n continue;\n }\n }\n if ((link = next) !== undefined) {\n next = link.nextSub;\n continue;\n }\n while (stack !== undefined) {\n link = stack.value;\n stack = stack.prev;\n if (link !== undefined) {\n next = link.nextSub;\n continue top;\n }\n }\n break;\n } while (true);\n }\n function checkDirty(link, sub) {\n let stack;\n let checkDepth = 0;\n let dirty = false;\n top: do {\n const dep = link.dep;\n const flags = dep.flags;\n if (sub.flags & 16) {\n dirty = true;\n }\n else if ((flags & (1 | 16)) === (1 | 16)) {\n if (update(dep)) {\n const subs = dep.subs;\n if (subs.nextSub !== undefined) {\n shallowPropagate(subs);\n }\n dirty = true;\n }\n }\n else if ((flags & (1 | 32)) === (1 | 32)) {\n if (link.nextSub !== undefined || link.prevSub !== undefined) {\n stack = { value: link, prev: stack };\n }\n link = dep.deps;\n sub = dep;\n ++checkDepth;\n continue;\n }\n if (!dirty) {\n const nextDep = link.nextDep;\n if (nextDep !== undefined) {\n link = nextDep;\n continue;\n }\n }\n while (checkDepth--) {\n const firstSub = sub.subs;\n const hasMultipleSubs = firstSub.nextSub !== undefined;\n if (hasMultipleSubs) {\n link = stack.value;\n stack = stack.prev;\n }\n else {\n link = firstSub;\n }\n if (dirty) {\n if (update(sub)) {\n if (hasMultipleSubs) {\n shallowPropagate(firstSub);\n }\n sub = link.sub;\n continue;\n }\n dirty = false;\n }\n else {\n sub.flags &= ~32;\n }\n sub = link.sub;\n const nextDep = link.nextDep;\n if (nextDep !== undefined) {\n link = nextDep;\n continue top;\n }\n }\n return dirty;\n } while (true);\n }\n function shallowPropagate(link) {\n do {\n const sub = link.sub;\n const flags = sub.flags;\n if ((flags & (32 | 16)) === 32) {\n sub.flags = flags | 16;\n if ((flags & (2 | 4)) === 2) {\n notify(sub);\n }\n }\n } while ((link = link.nextSub) !== undefined);\n }\n function isValidLink(checkLink, sub) {\n let link = sub.depsTail;\n while (link !== undefined) {\n if (link === checkLink) {\n return true;\n }\n link = link.prevDep;\n }\n return false;\n }\n}\n","import { createReactiveSystem } from './system.mjs';\nlet cycle = 0;\nlet batchDepth = 0;\nlet notifyIndex = 0;\nlet queuedLength = 0;\nlet activeSub;\nconst queued = [];\nconst { link, unlink, propagate, checkDirty, shallowPropagate, } = createReactiveSystem({\n update(node) {\n if (node.depsTail !== undefined) {\n return updateComputed(node);\n }\n else {\n return updateSignal(node);\n }\n },\n notify(effect) {\n let insertIndex = queuedLength;\n let firstInsertedIndex = insertIndex;\n do {\n queued[insertIndex++] = effect;\n effect.flags &= ~2;\n effect = effect.subs?.sub;\n if (effect === undefined || !(effect.flags & 2)) {\n break;\n }\n } while (true);\n queuedLength = insertIndex;\n while (firstInsertedIndex < --insertIndex) {\n const left = queued[firstInsertedIndex];\n queued[firstInsertedIndex++] = queued[insertIndex];\n queued[insertIndex] = left;\n }\n },\n unwatched(node) {\n if (!(node.flags & 1)) {\n effectScopeOper.call(node);\n }\n else if (node.depsTail !== undefined) {\n node.depsTail = undefined;\n node.flags = 1 | 16;\n purgeDeps(node);\n }\n },\n});\nexport function getActiveSub() {\n return activeSub;\n}\nexport function setActiveSub(sub) {\n const prevSub = activeSub;\n activeSub = sub;\n return prevSub;\n}\nexport function getBatchDepth() {\n return batchDepth;\n}\nexport function startBatch() {\n ++batchDepth;\n}\nexport function endBatch() {\n if (!--batchDepth) {\n flush();\n }\n}\nexport function isSignal(fn) {\n return fn.name === 'bound ' + signalOper.name;\n}\nexport function isComputed(fn) {\n return fn.name === 'bound ' + computedOper.name;\n}\nexport function isEffect(fn) {\n return fn.name === 'bound ' + effectOper.name;\n}\nexport function isEffectScope(fn) {\n return fn.name === 'bound ' + effectScopeOper.name;\n}\nexport function signal(initialValue) {\n return signalOper.bind({\n currentValue: initialValue,\n pendingValue: initialValue,\n subs: undefined,\n subsTail: undefined,\n flags: 1,\n });\n}\nexport function computed(getter) {\n return computedOper.bind({\n value: undefined,\n subs: undefined,\n subsTail: undefined,\n deps: undefined,\n depsTail: undefined,\n flags: 0,\n getter: getter,\n });\n}\nexport function effect(fn) {\n const e = {\n fn,\n subs: undefined,\n subsTail: undefined,\n deps: undefined,\n depsTail: undefined,\n flags: 2 | 4,\n };\n const prevSub = setActiveSub(e);\n if (prevSub !== undefined) {\n link(e, prevSub, 0);\n }\n try {\n e.fn();\n }\n finally {\n activeSub = prevSub;\n e.flags &= ~4;\n }\n return effectOper.bind(e);\n}\nexport function effectScope(fn) {\n const e = {\n deps: undefined,\n depsTail: undefined,\n subs: undefined,\n subsTail: undefined,\n flags: 0,\n };\n const prevSub = setActiveSub(e);\n if (prevSub !== undefined) {\n link(e, prevSub, 0);\n }\n try {\n fn();\n }\n finally {\n activeSub = prevSub;\n }\n return effectScopeOper.bind(e);\n}\nexport function trigger(fn) {\n const sub = {\n deps: undefined,\n depsTail: undefined,\n flags: 2,\n };\n const prevSub = setActiveSub(sub);\n try {\n fn();\n }\n finally {\n activeSub = prevSub;\n let link = sub.deps;\n while (link !== undefined) {\n const dep = link.dep;\n link = unlink(link, sub);\n const subs = dep.subs;\n if (subs !== undefined) {\n sub.flags = 0;\n propagate(subs);\n shallowPropagate(subs);\n }\n }\n if (!batchDepth) {\n flush();\n }\n }\n}\nfunction updateComputed(c) {\n ++cycle;\n c.depsTail = undefined;\n c.flags = 1 | 4;\n const prevSub = setActiveSub(c);\n try {\n const oldValue = c.value;\n return oldValue !== (c.value = c.getter(oldValue));\n }\n finally {\n activeSub = prevSub;\n c.flags &= ~4;\n purgeDeps(c);\n }\n}\nfunction updateSignal(s) {\n s.flags = 1;\n return s.currentValue !== (s.currentValue = s.pendingValue);\n}\nfunction run(e) {\n const flags = e.flags;\n if (flags & 16\n || (flags & 32\n && checkDirty(e.deps, e))) {\n ++cycle;\n e.depsTail = undefined;\n e.flags = 2 | 4;\n const prevSub = setActiveSub(e);\n try {\n e.fn();\n }\n finally {\n activeSub = prevSub;\n e.flags &= ~4;\n purgeDeps(e);\n }\n }\n else {\n e.flags = 2;\n }\n}\nfunction flush() {\n try {\n while (notifyIndex < queuedLength) {\n const effect = queued[notifyIndex];\n queued[notifyIndex++] = undefined;\n run(effect);\n }\n }\n finally {\n while (notifyIndex < queuedLength) {\n const effect = queued[notifyIndex];\n queued[notifyIndex++] = undefined;\n effect.flags |= 2 | 8;\n }\n notifyIndex = 0;\n queuedLength = 0;\n }\n}\nfunction computedOper() {\n const flags = this.flags;\n if (flags & 16\n || (flags & 32\n && (checkDirty(this.deps, this)\n || (this.flags = flags & ~32, false)))) {\n if (updateComputed(this)) {\n const subs = this.subs;\n if (subs !== undefined) {\n shallowPropagate(subs);\n }\n }\n }\n else if (!flags) {\n this.flags = 1 | 4;\n const prevSub = setActiveSub(this);\n try {\n this.value = this.getter();\n }\n finally {\n activeSub = prevSub;\n this.flags &= ~4;\n }\n }\n const sub = activeSub;\n if (sub !== undefined) {\n link(this, sub, cycle);\n }\n return this.value;\n}\nfunction signalOper(...value) {\n if (value.length) {\n if (this.pendingValue !== (this.pendingValue = value[0])) {\n this.flags = 1 | 16;\n const subs = this.subs;\n if (subs !== undefined) {\n propagate(subs);\n if (!batchDepth) {\n flush();\n }\n }\n }\n }\n else {\n if (this.flags & 16) {\n if (updateSignal(this)) {\n const subs = this.subs;\n if (subs !== undefined) {\n shallowPropagate(subs);\n }\n }\n }\n let sub = activeSub;\n while (sub !== undefined) {\n if (sub.flags & (1 | 2)) {\n link(this, sub, cycle);\n break;\n }\n sub = sub.subs?.sub;\n }\n return this.currentValue;\n }\n}\nfunction effectOper() {\n effectScopeOper.call(this);\n}\nfunction effectScopeOper() {\n this.depsTail = undefined;\n this.flags = 0;\n purgeDeps(this);\n const sub = this.subs;\n if (sub !== undefined) {\n unlink(sub);\n }\n}\nfunction purgeDeps(sub) {\n const depsTail = sub.depsTail;\n let dep = depsTail !== undefined ? depsTail.nextDep : sub.deps;\n while (dep !== undefined) {\n dep = unlink(dep, sub);\n }\n}\n","/**\n * Forma Reactive - Signal\n *\n * Fine-grained reactive primitive backed by alien-signals.\n * API: createSignal returns [getter, setter] tuple following SolidJS conventions.\n *\n * TC39 Signals equivalent: Signal.State\n */\n\nimport { signal as createRawSignal, setActiveSub } from 'alien-signals';\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport type SignalGetter<T> = () => T;\nexport type SignalSetter<T> = (v: T | ((prev: T) => T)) => void;\n\nexport interface SignalOptions<T> {\n /** Debug name — attached to getter in dev mode for devtools inspection. */\n name?: string;\n /**\n * Custom equality check. When provided, the setter will read the current\n * value and only update the signal if `equals(prev, next)` returns `false`.\n *\n * Default: none (alien-signals uses strict inequality `!==` internally).\n *\n * ```ts\n * const [pos, setPos] = createSignal(\n * { x: 0, y: 0 },\n * { equals: (a, b) => a.x === b.x && a.y === b.y },\n * );\n *\n * setPos({ x: 0, y: 0 }); // skipped — equals returns true\n * setPos({ x: 1, y: 0 }); // applied — equals returns false\n * ```\n */\n equals?: (prev: T, next: T) => boolean;\n}\n\n/**\n * Wrap a value so the setter treats it as a literal value, not a functional updater.\n *\n * When `T` is itself a function type, passing a function to the setter is\n * ambiguous -- it looks like a functional update (`prev => next`). Use\n * `value()` to disambiguate:\n *\n * ```ts\n * const [getFn, setFn] = createSignal<() => void>(() => console.log('a'));\n *\n * // BUG: interpreted as a functional update -- calls the arrow with prev\n * // setFn(() => console.log('b'));\n *\n * // Correct: wraps in a thunk so the setter stores it as-is\n * setFn(value(() => console.log('b')));\n * ```\n */\nexport function value<T>(v: T): () => T {\n return () => v;\n}\n\ntype RawSignal<T> = {\n (): T;\n (value: T): void;\n};\n\nfunction applySignalSet<T>(\n s: RawSignal<T>,\n v: T | ((prev: T) => T),\n equals?: (prev: T, next: T) => boolean,\n): void {\n if (typeof v !== 'function') {\n if (equals) {\n // Read current value without tracking\n const prevSub = setActiveSub(undefined);\n const prev = s();\n setActiveSub(prevSub);\n if (equals(prev, v)) return; // skip — values are equal\n }\n s(v);\n return;\n }\n\n // Functional update: read prev without tracking\n const prevSub = setActiveSub(undefined);\n const prev = s();\n setActiveSub(prevSub);\n const next = (v as (prev: T) => T)(prev);\n if (equals && equals(prev, next)) return; // skip — values are equal\n s(next);\n}\n\n/**\n * Create a reactive signal.\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * console.log(count()); // 0\n * setCount(1);\n * setCount(prev => prev + 1);\n * ```\n *\n * With custom equality:\n *\n * ```ts\n * const [pos, setPos] = createSignal(\n * { x: 0, y: 0 },\n * { equals: (a, b) => a.x === b.x && a.y === b.y },\n * );\n * ```\n */\nexport function createSignal<T>(initialValue: T, options?: SignalOptions<T>): [get: SignalGetter<T>, set: SignalSetter<T>] {\n const s = createRawSignal<T>(initialValue) as RawSignal<T>;\n const getter = s as unknown as SignalGetter<T>;\n const eq = options?.equals;\n const setter: SignalSetter<T> = (v: T | ((prev: T) => T)) => applySignalSet(s, v, eq);\n\n return [getter, setter];\n}\n","/**\n * Forma Reactive - Root\n *\n * Explicit reactive ownership scope. All effects created inside a root\n * are automatically disposed when the root is torn down.\n *\n * Uses alien-signals' `effectScope` under the hood for native graph-level\n * effect tracking, with a userland disposer list for non-effect cleanup\n * (e.g., event listeners, DOM references, timers).\n */\n\nimport { effectScope as rawEffectScope } from 'alien-signals';\n\n// ---------------------------------------------------------------------------\n// Root scope tracking\n// ---------------------------------------------------------------------------\n\nlet currentRoot: RootScope | null = null;\nconst rootStack: (RootScope | null)[] = [];\n\ninterface RootScope {\n /** Userland disposers (event listeners, DOM refs, timers, etc.) */\n disposers: (() => void)[];\n /** alien-signals effect scope dispose — tears down all reactive effects */\n scopeDispose: (() => void) | null;\n}\n\n/**\n * Create a reactive root scope.\n *\n * All effects created (via `createEffect`) inside the callback are tracked\n * at both the reactive graph level (via alien-signals effectScope) and the\n * userland level (via registerDisposer). The returned `dispose` function\n * tears down everything.\n *\n * ```ts\n * const dispose = createRoot(() => {\n * createEffect(() => console.log(count()));\n * createEffect(() => console.log(name()));\n * });\n * // later: dispose() stops both effects\n * ```\n */\nexport function createRoot<T>(fn: (dispose: () => void) => T): T {\n const scope: RootScope = { disposers: [], scopeDispose: null };\n\n rootStack.push(currentRoot);\n currentRoot = scope;\n\n const dispose = () => {\n // Dispose alien-signals effect scope first (reactive graph cleanup)\n if (scope.scopeDispose) {\n try { scope.scopeDispose(); } catch { /* ensure userland disposers still run */ }\n scope.scopeDispose = null;\n }\n // Then run userland disposers\n for (const d of scope.disposers) {\n try { d(); } catch { /* ensure all disposers run */ }\n }\n scope.disposers.length = 0;\n };\n\n let result: T;\n try {\n // Wrap in alien-signals effectScope for native effect tracking\n scope.scopeDispose = rawEffectScope(() => {\n result = fn(dispose);\n });\n } finally {\n currentRoot = rootStack.pop() ?? null;\n }\n\n return result!;\n}\n\n/**\n * @internal — called by createEffect to register disposers in the current root.\n */\nexport function registerDisposer(dispose: () => void): void {\n if (currentRoot) {\n currentRoot.disposers.push(dispose);\n }\n}\n\n/**\n * @internal — check if we're inside a root scope.\n */\nexport function hasActiveRoot(): boolean {\n return currentRoot !== null;\n}\n","/**\n * Forma Reactive - Effect\n *\n * Side-effectful reactive computation that auto-tracks signal dependencies.\n * Backed by alien-signals for automatic dependency tracking.\n *\n * TC39 Signals equivalent: Signal.subtle.Watcher (effect is a userland concept)\n */\n\nimport { effect as rawEffect } from 'alien-signals';\nimport { hasActiveRoot, registerDisposer } from './root.js';\nimport { setCleanupCollector } from './cleanup.js';\nimport { reportError } from './dev.js';\n\n// ---------------------------------------------------------------------------\n// Cleanup array pool — avoids allocating a new array every effect re-run\n// ---------------------------------------------------------------------------\n\nconst POOL_SIZE = 32;\nconst MAX_REENTRANT_RUNS = 100;\nconst pool: (() => void)[][] = [];\nfor (let i = 0; i < POOL_SIZE; i++) pool.push([]);\nlet poolIdx = POOL_SIZE;\n\nfunction acquireArray(): (() => void)[] {\n if (poolIdx > 0) {\n const arr = pool[--poolIdx]!;\n arr.length = 0;\n return arr;\n }\n return [];\n}\n\nfunction releaseArray(arr: (() => void)[]): void {\n arr.length = 0;\n if (poolIdx < POOL_SIZE) {\n pool[poolIdx++] = arr;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Unified cleanup runner — single function for both re-run and dispose paths\n// ---------------------------------------------------------------------------\n\nfunction runCleanup(fn: (() => void) | undefined): void {\n if (fn === undefined) return;\n try {\n fn();\n } catch (e) {\n reportError(e, 'effect cleanup');\n }\n}\n\nfunction runCleanups(bag: (() => void)[] | undefined): void {\n if (bag === undefined) return;\n for (let i = 0; i < bag.length; i++) {\n try { bag[i]!(); } catch (e) { reportError(e, 'effect cleanup'); }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactive effect that auto-tracks signal dependencies.\n *\n * The provided function runs immediately and re-runs whenever any signal it\n * reads changes. If the function returns a cleanup function, that cleanup is\n * called before each re-run and on disposal.\n *\n * Additionally, `onCleanup()` can be called inside the effect to register\n * cleanup functions composably.\n *\n * Returns a dispose function that stops the effect.\n */\n/**\n * @internal — Lightweight effect for Forma's internal DOM bindings.\n *\n * Bypasses createEffect's cleanup infrastructure (pool, collector, error\n * reporting, engine compression) since internal effects never use\n * onCleanup() or return cleanup functions. This saves ~4 function calls\n * per effect creation and per re-run.\n *\n * ONLY use for effects that:\n * 1. Never call onCleanup()\n * 2. Never return a cleanup function\n * 3. Contain simple \"read signal → write DOM\" logic\n */\nexport function internalEffect(fn: () => void): () => void {\n const dispose = rawEffect(fn);\n if (hasActiveRoot()) {\n registerDisposer(dispose);\n }\n return dispose;\n}\n\nexport function createEffect(fn: () => void | (() => void)): () => void {\n const shouldRegister = hasActiveRoot();\n\n // Most effects have zero or one cleanup. Track the single-cleanup case\n // without array allocation; only promote to pooled array when needed.\n let cleanup: (() => void) | undefined;\n let cleanupBag: (() => void)[] | undefined;\n let nextCleanup: (() => void) | undefined;\n let nextCleanupBag: (() => void)[] | undefined;\n\n const addCleanup = (cb: () => void) => {\n if (nextCleanupBag !== undefined) {\n nextCleanupBag.push(cb);\n return;\n }\n if (nextCleanup !== undefined) {\n const bag = acquireArray();\n bag.push(nextCleanup, cb);\n nextCleanup = undefined;\n nextCleanupBag = bag;\n return;\n }\n nextCleanup = cb;\n };\n\n // \"Engine Compression\" exploit: most effects never use cleanup (onCleanup()\n // or return value). After the first clean run, we know this effect is\n // \"cleanup-free\" and can skip the entire cleanup infrastructure on re-runs.\n // This saves 4 function calls per re-run: acquireArray, setCleanupCollector,\n // releaseArray, and bag inspection. Like the engine compression ratio exploit —\n // the \"rules\" say we should always prepare for cleanup, but we measure at\n // \"room temperature\" (first run) and exploit the gap.\n let skipCleanupInfra = false;\n let firstRun = true;\n let running = false;\n let rerunRequested = false;\n\n const runOnce = () => {\n // Run and clear previous cleanups (only if any exist).\n if (cleanup !== undefined) {\n runCleanup(cleanup);\n cleanup = undefined;\n }\n if (cleanupBag !== undefined) {\n runCleanups(cleanupBag);\n releaseArray(cleanupBag);\n cleanupBag = undefined;\n }\n\n // Ultra-fast path: this effect has proven it doesn't use cleanup.\n // Skip acquireArray + setCleanupCollector + bag checks + releaseArray.\n if (skipCleanupInfra) {\n try { fn(); } catch (e) { reportError(e, 'effect'); }\n return;\n }\n\n nextCleanup = undefined;\n nextCleanupBag = undefined;\n\n // Full path: install collector for onCleanup() calls.\n const prevCollector = setCleanupCollector(addCleanup);\n\n try {\n const result = fn();\n\n if (typeof result === 'function') {\n addCleanup(result as () => void);\n }\n\n // Hot path: no cleanups registered or returned — enable ultra-fast path.\n if (nextCleanup === undefined && nextCleanupBag === undefined) {\n // First clean run → enable ultra-fast path for all subsequent runs\n if (firstRun) skipCleanupInfra = true;\n return;\n }\n\n if (nextCleanupBag !== undefined) {\n cleanupBag = nextCleanupBag;\n } else {\n cleanup = nextCleanup;\n }\n } catch (e) {\n reportError(e, 'effect');\n\n if (nextCleanupBag !== undefined) {\n cleanupBag = nextCleanupBag;\n } else {\n cleanup = nextCleanup;\n }\n } finally {\n setCleanupCollector(prevCollector);\n firstRun = false;\n }\n };\n\n const safeFn = () => {\n if (running) {\n rerunRequested = true;\n return;\n }\n\n running = true;\n try {\n let reentrantRuns = 0;\n do {\n rerunRequested = false;\n runOnce();\n if (rerunRequested) {\n reentrantRuns++;\n if (reentrantRuns >= MAX_REENTRANT_RUNS) {\n reportError(\n new Error(`createEffect exceeded ${MAX_REENTRANT_RUNS} re-entrant runs`),\n 'effect',\n );\n rerunRequested = false;\n }\n }\n } while (rerunRequested);\n } finally {\n running = false;\n }\n };\n\n const dispose = rawEffect(safeFn);\n\n // Wrap dispose to also run final cleanups\n let disposed = false;\n const wrappedDispose = () => {\n if (disposed) return;\n disposed = true;\n dispose();\n if (cleanup !== undefined) {\n runCleanup(cleanup);\n cleanup = undefined;\n }\n if (cleanupBag !== undefined) {\n runCleanups(cleanupBag);\n releaseArray(cleanupBag);\n cleanupBag = undefined;\n }\n };\n\n // Register in current root scope (if any)\n if (shouldRegister) {\n registerDisposer(wrappedDispose);\n }\n\n return wrappedDispose;\n}\n","/**\n * Forma Reactive - Computed\n *\n * Lazy, cached derived value that participates in the reactive graph.\n * Backed by alien-signals for automatic dependency tracking\n * and cache invalidation.\n *\n * TC39 Signals equivalent: Signal.Computed\n */\n\nimport { computed as rawComputed } from 'alien-signals';\n\n/**\n * Create a lazy, cached computed value.\n *\n * Note: Unlike SolidJS's createComputed (which is an eager synchronous\n * side effect), this is a lazy cached derivation — equivalent to\n * SolidJS's createMemo. Both createComputed and createMemo in FormaJS\n * are identical.\n *\n * The getter receives the previous value as an argument, enabling\n * efficient diffing patterns without a separate signal:\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * const doubled = createComputed(() => count() * 2);\n * console.log(doubled()); // 0\n * setCount(5);\n * console.log(doubled()); // 10\n * ```\n *\n * With previous value (for diffing):\n *\n * ```ts\n * const changes = createComputed((prev) => {\n * const next = items();\n * if (prev) console.log(`changed from ${prev.length} to ${next.length} items`);\n * return next;\n * });\n * ```\n */\nexport function createComputed<T>(fn: (previousValue?: T) => T): () => T {\n return rawComputed(fn);\n}\n","/**\n * Forma Reactive - Batch\n *\n * Groups multiple signal updates and defers effect execution until the\n * outermost batch completes. Prevents intermediate re-renders.\n * Backed by alien-signals.\n *\n * TC39 Signals: no built-in batch — this is a userland optimization.\n */\n\nimport { startBatch, endBatch } from 'alien-signals';\n\n/**\n * Group multiple signal updates so that effects only run once after all\n * updates have been applied.\n *\n * ```ts\n * batch(() => {\n * setA(1);\n * setB(2);\n * // effects that depend on A and B won't run yet\n * });\n * // effects run here, once\n * ```\n *\n * Batches are nestable — only the outermost batch triggers the flush.\n */\nexport function batch(fn: () => void): void {\n startBatch();\n try {\n fn();\n } finally {\n endBatch();\n }\n}\n","/**\n * Forma DOM - List\n *\n * Keyed list reconciliation with Longest Increasing Subsequence (LIS).\n * The LIS tells us the maximum set of DOM nodes that can stay in place;\n * only the remaining nodes need to be moved. This minimises DOM operations\n * to exactly `n - LIS_length` moves — provably optimal.\n *\n * Algorithm used by ivi, Inferno, and (with variations) Solid, Vue 3, Svelte.\n *\n * Uses comment-node markers instead of a wrapper <div>, so the list can be\n * placed inside <table>, <ul>, <select>, etc. without breaking semantics.\n *\n * Total module budget: <2KB minified.\n */\n\nimport { createSignal, internalEffect, untrack, __DEV__ } from '../reactive';\nimport { hydrating } from './hydrate.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ReconcileResult<T> {\n nodes: Node[];\n items: T[];\n}\n\nexport interface ListTransitionHooks {\n onInsert?: (node: Node) => void;\n onBeforeRemove?: (node: Node, done: () => void) => void;\n}\n\ninterface CachedItem<T> {\n element: HTMLElement;\n item: T;\n getIndex: () => number;\n setIndex: (v: number) => void;\n}\n\nexport interface CreateListOptions {\n /**\n * How to handle same-key items whose object identity changed.\n * - 'none' (default): keep the existing row node for maximum throughput.\n * - 'rerender': re-render changed rows and patch static row DOM in place.\n */\n updateOnItemChange?: 'none' | 'rerender';\n}\n\n// ---------------------------------------------------------------------------\n// LIS — O(n log n) via patience sorting + binary search\n// ---------------------------------------------------------------------------\n\n/**\n * Find the longest increasing subsequence.\n * Returns indices into the input array.\n * O(n log n) time, O(n) space.\n */\nexport function longestIncreasingSubsequence(arr: number[]): number[] {\n const n = arr.length;\n if (n === 0) return [];\n\n // Pre-allocate typed arrays — avoids V8 array growth overhead on push\n const tails = new Int32Array(n);\n const tailIndices = new Int32Array(n);\n const predecessor = new Int32Array(n).fill(-1);\n let tailsLen = 0;\n\n for (let i = 0; i < n; i++) {\n const val = arr[i]!;\n\n // Binary search: leftmost tail >= val\n let lo = 0, hi = tailsLen;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (tails[mid]! < val) lo = mid + 1;\n else hi = mid;\n }\n\n tails[lo] = val;\n tailIndices[lo] = i;\n if (lo > 0) predecessor[i] = tailIndices[lo - 1]!;\n if (lo >= tailsLen) tailsLen++;\n }\n\n // Reconstruct — return plain array since callers expect number[]\n const result = new Array<number>(tailsLen);\n let idx = tailIndices[tailsLen - 1]!;\n for (let i = tailsLen - 1; i >= 0; i--) {\n result[i] = idx;\n idx = predecessor[idx]!;\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// reconcileList — low-level keyed reconciler\n// ---------------------------------------------------------------------------\n\n/** Below this threshold, use flat array scan instead of Map for better cache locality. */\nconst SMALL_LIST_THRESHOLD = 32;\nconst ABORT_SYM = Symbol.for('forma-abort');\nconst CACHE_SYM = Symbol.for('forma-attr-cache');\nconst DYNAMIC_CHILD_SYM = Symbol.for('forma-dynamic-child');\n\nfunction canPatchStaticElement(target: Node, source: Node): target is HTMLElement {\n return target instanceof HTMLElement\n && source instanceof HTMLElement\n && target.tagName === source.tagName\n && !(target as any)[ABORT_SYM]\n && !(target as any)[CACHE_SYM]\n && !(target as any)[DYNAMIC_CHILD_SYM]\n && !(source as any)[ABORT_SYM]\n && !(source as any)[CACHE_SYM]\n && !(source as any)[DYNAMIC_CHILD_SYM];\n}\n\nfunction patchStaticElement(target: HTMLElement, source: HTMLElement): void {\n // Sync attributes (events/reactive bindings are excluded by canPatchStaticElement).\n const sourceAttrNames = new Set<string>();\n for (const attr of Array.from(source.attributes)) {\n sourceAttrNames.add(attr.name);\n if (target.getAttribute(attr.name) !== attr.value) {\n target.setAttribute(attr.name, attr.value);\n }\n }\n for (const attr of Array.from(target.attributes)) {\n if (!sourceAttrNames.has(attr.name)) {\n target.removeAttribute(attr.name);\n }\n }\n\n // Move freshly rendered children into the existing keyed node.\n target.replaceChildren(...Array.from(source.childNodes));\n}\n\n/**\n * Small-list reconciler: uses flat arrays + indexOf instead of Map/Set.\n * For < 32 items, linear scan is faster than hash computation overhead.\n */\nfunction reconcileSmall<T>(\n parent: Node,\n oldItems: T[],\n newItems: T[],\n oldNodes: Node[],\n keyFn: (item: T) => string | number,\n createFn: (item: T) => Node,\n updateFn: (node: Node, item: T) => void,\n beforeNode?: Node | null,\n hooks?: ListTransitionHooks,\n): ReconcileResult<T> {\n const oldLen = oldItems.length;\n const newLen = newItems.length;\n\n // Build flat arrays for old keys/nodes — better cache locality than Map\n const oldKeys: (string | number)[] = new Array(oldLen);\n for (let i = 0; i < oldLen; i++) {\n oldKeys[i] = keyFn(oldItems[i]!);\n }\n\n // Classify each new item: find matching old index via linear scan\n const oldIndices = new Array<number>(newLen);\n const oldUsed = new Uint8Array(oldLen); // 0 = unused, 1 = used\n\n for (let i = 0; i < newLen; i++) {\n const key = keyFn(newItems[i]!);\n let found = -1;\n for (let j = 0; j < oldLen; j++) {\n if (!oldUsed[j] && oldKeys[j] === key) {\n found = j;\n oldUsed[j] = 1;\n break;\n }\n }\n oldIndices[i] = found;\n }\n\n // Remove old items not reused\n for (let i = 0; i < oldLen; i++) {\n if (!oldUsed[i]) {\n if (hooks?.onBeforeRemove) {\n const node = oldNodes[i]!;\n hooks.onBeforeRemove(node, () => {\n if (node.parentNode) node.parentNode.removeChild(node);\n });\n } else {\n parent.removeChild(oldNodes[i]!);\n }\n }\n }\n\n // Fast path: same keys, same order -> just update, 0 DOM moves\n if (oldLen === newLen) {\n let allSameOrder = true;\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== i) {\n allSameOrder = false;\n break;\n }\n }\n if (allSameOrder) {\n const nodes = new Array<Node>(newLen);\n for (let i = 0; i < newLen; i++) {\n const node = oldNodes[i]!;\n updateFn(node, newItems[i]!);\n nodes[i] = node;\n }\n return { nodes, items: newItems };\n }\n }\n\n // LIS for minimum moves (still needed even for small lists)\n const reusedIndices: number[] = [];\n const reusedPositions: number[] = [];\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== -1) {\n reusedIndices.push(oldIndices[i]!);\n reusedPositions.push(i);\n }\n }\n\n const lisOfReused = longestIncreasingSubsequence(reusedIndices);\n // Use Uint8Array as a bitmap instead of Set for small lists\n const lisFlags = new Uint8Array(newLen);\n for (const li of lisOfReused) {\n lisFlags[reusedPositions[li]!] = 1;\n }\n\n // Build result: walk right-to-left for stable insertBefore targets\n const newNodes = new Array<Node>(newLen);\n let nextSibling: Node | null = beforeNode ?? null;\n\n for (let i = newLen - 1; i >= 0; i--) {\n let node: Node;\n let isNew = false;\n\n if (oldIndices[i] === -1) {\n node = createFn(newItems[i]!);\n isNew = true;\n } else {\n node = oldNodes[oldIndices[i]!]!;\n updateFn(node, newItems[i]!);\n\n if (lisFlags[i]) {\n newNodes[i] = node;\n nextSibling = node;\n continue;\n }\n }\n\n if (nextSibling) {\n parent.insertBefore(node, nextSibling);\n } else {\n parent.appendChild(node);\n }\n\n if (isNew) hooks?.onInsert?.(node);\n\n newNodes[i] = node;\n nextSibling = node;\n }\n\n return { nodes: newNodes, items: newItems };\n}\n\n/**\n * Reconcile a DOM parent's children to match a new array of items.\n * Uses keyed reconciliation with LIS for minimum DOM operations.\n *\n * For small lists (< 32 items), uses a flat array scan path that avoids\n * Map/Set hash overhead and provides better cache locality.\n *\n * @param parent - The container DOM element\n * @param oldItems - Previous array (from last reconciliation)\n * @param newItems - New array to render\n * @param oldNodes - Previous DOM nodes array\n * @param keyFn - Extracts a unique key from each item\n * @param createFn - Creates a new DOM node for an item\n * @param updateFn - Updates an existing DOM node with new item data\n * @param beforeNode - Optional boundary marker. When provided, new nodes are\n * inserted before this node instead of appended to parent.\n * This allows the reconciler to operate within a range\n * delimited by comment markers.\n * @returns Object with new nodes array and items array for next call\n */\nexport function reconcileList<T>(\n parent: Node,\n oldItems: T[],\n newItems: T[],\n oldNodes: Node[],\n keyFn: (item: T) => string | number,\n createFn: (item: T) => Node,\n updateFn: (node: Node, item: T) => void,\n beforeNode?: Node | null,\n hooks?: ListTransitionHooks,\n): ReconcileResult<T> {\n const oldLen = oldItems.length;\n const newLen = newItems.length;\n\n // --- Trivial: new is empty -> remove all ---\n if (newLen === 0) {\n for (let i = 0; i < oldLen; i++) {\n if (hooks?.onBeforeRemove) {\n const node = oldNodes[i]!;\n hooks.onBeforeRemove(node, () => {\n if (node.parentNode) node.parentNode.removeChild(node);\n });\n } else {\n parent.removeChild(oldNodes[i]!);\n }\n }\n return { nodes: [], items: [] };\n }\n\n // --- Trivial: old is empty -> create all ---\n if (oldLen === 0) {\n const nodes = new Array<Node>(newLen);\n for (let i = 0; i < newLen; i++) {\n const node = createFn(newItems[i]!);\n if (beforeNode) {\n parent.insertBefore(node, beforeNode);\n } else {\n parent.appendChild(node);\n }\n hooks?.onInsert?.(node);\n nodes[i] = node;\n }\n return { nodes, items: newItems };\n }\n\n // --- Small list path: flat array scan, no Map/Set overhead ---\n if (oldLen < SMALL_LIST_THRESHOLD) {\n return reconcileSmall(parent, oldItems, newItems, oldNodes, keyFn, createFn, updateFn, beforeNode, hooks);\n }\n\n // --- Large list path: Map-based approach ---\n const oldKeyMap = new Map<string | number, number>();\n for (let i = 0; i < oldLen; i++) {\n oldKeyMap.set(keyFn(oldItems[i]!), i);\n }\n\n // --- Classify each new item: reuse or create ---\n // Use Uint8Array bitmap instead of Set for O(1) lookup without hash overhead\n const oldIndices = new Array<number>(newLen); // -1 means new item\n const oldUsed = new Uint8Array(oldLen);\n\n for (let i = 0; i < newLen; i++) {\n const key = keyFn(newItems[i]!);\n const oldIdx = oldKeyMap.get(key);\n if (oldIdx !== undefined) {\n oldIndices[i] = oldIdx;\n oldUsed[oldIdx] = 1;\n } else {\n oldIndices[i] = -1;\n }\n }\n\n // --- Remove old items not in new array ---\n for (let i = 0; i < oldLen; i++) {\n if (!oldUsed[i]) {\n if (hooks?.onBeforeRemove) {\n const node = oldNodes[i]!;\n hooks.onBeforeRemove(node, () => {\n if (node.parentNode) node.parentNode.removeChild(node);\n });\n } else {\n parent.removeChild(oldNodes[i]!);\n }\n }\n }\n\n // --- Fast path: same keys, same order -> just update, 0 DOM moves ---\n if (oldLen === newLen) {\n let allSameOrder = true;\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== i) {\n allSameOrder = false;\n break;\n }\n }\n if (allSameOrder) {\n const nodes = new Array<Node>(newLen);\n for (let i = 0; i < newLen; i++) {\n const node = oldNodes[i]!;\n updateFn(node, newItems[i]!);\n nodes[i] = node;\n }\n return { nodes, items: newItems };\n }\n }\n\n // --- Find LIS of old indices (reused items only) ---\n const reusedIndices: number[] = [];\n const reusedPositions: number[] = []; // position in new array\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== -1) {\n reusedIndices.push(oldIndices[i]!);\n reusedPositions.push(i);\n }\n }\n\n const lisOfReused = longestIncreasingSubsequence(reusedIndices);\n // Use Uint8Array bitmap instead of Set for O(1) lookup without hash overhead\n const lisFlags = new Uint8Array(newLen);\n for (const li of lisOfReused) {\n lisFlags[reusedPositions[li]!] = 1;\n }\n\n // --- Build result: walk right-to-left for stable insertBefore targets ---\n const newNodes = new Array<Node>(newLen);\n let nextSibling: Node | null = beforeNode ?? null;\n\n for (let i = newLen - 1; i >= 0; i--) {\n let node: Node;\n let isNew = false;\n\n if (oldIndices[i] === -1) {\n // NEW: create and insert\n node = createFn(newItems[i]!);\n isNew = true;\n } else {\n // REUSE: update content\n node = oldNodes[oldIndices[i]!]!;\n updateFn(node, newItems[i]!);\n\n if (lisFlags[i]) {\n // LIS item: already in correct relative position, don't move\n newNodes[i] = node;\n nextSibling = node;\n continue;\n }\n }\n\n // Insert/move into position\n if (nextSibling) {\n parent.insertBefore(node, nextSibling);\n } else {\n parent.appendChild(node);\n }\n\n if (isNew) hooks?.onInsert?.(node);\n\n newNodes[i] = node;\n nextSibling = node;\n }\n\n return { nodes: newNodes, items: newItems };\n}\n\n// ---------------------------------------------------------------------------\n// createList — high-level reactive API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactively-bound list of DOM elements with keyed reconciliation.\n *\n * Returns a `DocumentFragment` containing two comment markers\n * (`<!--forma-list-start-->` and `<!--forma-list-end-->`) that delimit the\n * list's range in the DOM. All managed elements live between these markers.\n *\n * This avoids a wrapper `<div>` which would break `<table>`, `<ul>`,\n * `<select>` semantics and pollute the DOM.\n *\n * When the `items` signal changes, only the minimal set of DOM mutations is\n * performed using the LIS algorithm:\n * - New keys: create elements via `renderFn`\n * - Removed keys: remove elements from DOM\n * - Moved keys: reorder elements using minimum moves (n - LIS)\n * - Same keys: keep row nodes and update index signals\n * (or re-render row content when `updateOnItemChange: 'rerender'`)\n *\n * @param items Signal getter returning the current array of items.\n * @param keyFn Extracts a unique key from each item.\n * @param renderFn Renders a single item. Receives the item and a reactive index getter.\n * @returns A DocumentFragment to insert into the DOM. The fragment includes\n * start/end comment markers and any initial list items.\n *\n * ```ts\n * const frag = createList(\n * todos,\n * (t) => t.id,\n * (todo, index) => h('li', null, () => `${index() + 1}. ${todo.text}`),\n * );\n * container.appendChild(frag);\n * ```\n */\nexport function createList<T>(\n items: () => T[],\n keyFn: (item: T) => string | number,\n renderFn: (item: T, index: () => number) => HTMLElement,\n options?: CreateListOptions,\n): DocumentFragment {\n if (hydrating) {\n return { type: 'list', items, keyFn, renderFn, options } as unknown as DocumentFragment;\n }\n\n const startMarker = document.createComment('forma-list-start');\n const endMarker = document.createComment('forma-list-end');\n\n const fragment = document.createDocumentFragment();\n fragment.appendChild(startMarker);\n fragment.appendChild(endMarker);\n\n // Cache: key -> { element, item, setIndex }\n let cache = new Map<string | number, CachedItem<T>>();\n let currentNodes: Node[] = [];\n let currentItems: T[] = [];\n const updateOnItemChange = options?.updateOnItemChange ?? 'none';\n\n internalEffect(() => {\n const newItems = items();\n\n // The parent is discovered lazily: once the fragment has been inserted\n // into the live DOM the markers have a parentNode.\n const parent = startMarker.parentNode;\n if (!parent) {\n // Markers are not yet in the DOM — nothing to reconcile.\n // This can happen if the effect fires synchronously before mount.\n return;\n }\n\n // Edge case: non-array\n if (!Array.isArray(newItems)) {\n if (__DEV__) {\n console.warn('[forma] createList: value is not an array, treating as empty');\n }\n // Remove all nodes between the markers\n for (const node of currentNodes) {\n if (node.parentNode === parent) parent.removeChild(node);\n }\n cache = new Map();\n currentNodes = [];\n currentItems = [];\n return;\n }\n\n // Filter nullish items — avoid array allocation when no nulls found (common case)\n let cleanItems: T[] = newItems;\n for (let i = 0; i < newItems.length; i++) {\n if (newItems[i] == null) {\n cleanItems = newItems.filter(item => item != null);\n break;\n }\n }\n\n // Dev-mode duplicate key detection\n if (__DEV__) {\n const seen = new Set<string | number>();\n for (const item of cleanItems) {\n const key = keyFn(item);\n if (seen.has(key)) {\n console.warn('[forma] createList: duplicate key detected:', key);\n }\n seen.add(key);\n }\n }\n\n const updateRow = updateOnItemChange === 'rerender'\n ? (node: Node, item: T): void => {\n const key = keyFn(item);\n const cached = cache.get(key);\n if (!cached) return;\n if (cached.item === item) return;\n cached.item = item;\n\n if (!(node instanceof HTMLElement)) return;\n if ((node as any)[ABORT_SYM] || (node as any)[CACHE_SYM] || (node as any)[DYNAMIC_CHILD_SYM]) {\n return;\n }\n\n const next = untrack(() => renderFn(item, cached.getIndex));\n if (canPatchStaticElement(node, next)) {\n patchStaticElement(node, next);\n cached.element = node;\n }\n }\n : (_node: Node, item: T): void => {\n const key = keyFn(item);\n const cached = cache.get(key);\n if (cached) cached.item = item;\n };\n\n const result = reconcileList<T>(\n parent,\n currentItems,\n cleanItems,\n currentNodes,\n keyFn,\n // createFn: create element + cache entry\n (item) => {\n const key = keyFn(item);\n const [getIndex, setIndex] = createSignal(0);\n // Prevent child effects created during render from being nested under\n // the reconciler effect, which can stall their updates on reorders.\n const element = untrack(() => renderFn(item, getIndex));\n cache.set(key, { element, item, getIndex, setIndex });\n return element;\n },\n updateRow,\n // beforeNode: insert items before the end marker\n endMarker,\n );\n\n // Rebuild cache + update index signals in a single pass.\n // Avoids .map() array allocation + Set construction from the previous approach.\n const newCache = new Map<string | number, CachedItem<T>>();\n for (let i = 0; i < cleanItems.length; i++) {\n const key = keyFn(cleanItems[i]!);\n const cached = cache.get(key);\n if (cached) {\n cached.setIndex(i);\n newCache.set(key, cached);\n }\n }\n cache = newCache;\n\n currentNodes = result.nodes;\n currentItems = result.items;\n });\n\n return fragment;\n}\n","/**\n * Forma Reconciler — DOM diffing and patching engine.\n *\n * Replaces morphdom with a purpose-built reconciler that understands\n * Forma's directive system (data-forma-state, data-list, data-if, etc.).\n *\n * Usage:\n * const rec = createReconciler({ mountScope, unmountScope, ... });\n * rec(container, htmlString);\n *\n * Scope modes for data-forma-state elements matched by data-forma-id:\n * PRESERVE — same data-module + same state shape → patch attrs, keep bindings\n * RESET — same data-module + different state shape → unmount, patch, remount\n * REPLACE — different data-module → remove old, insert new, mount fresh\n */\n\n// ── Types ─────────────────────────────────────────────────────────────\n\nexport interface ReconcilerConfig {\n mountScope: (el: Element) => void;\n unmountScope: (el: Element) => void;\n disconnectObserver: () => void;\n reconnectObserver: () => void;\n batch: (fn: () => void) => void;\n}\n\ntype ScopeMode = 'PRESERVE' | 'RESET' | 'REPLACE';\n\n// ── Attribute helpers ─────────────────────────────────────────────────\n\n/** Check if an element has data-bind:X targeting a specific attribute */\nfunction getBindTargets(el: Element): Set<string> {\n const targets = new Set<string>();\n const attrs = el.attributes;\n for (let i = 0; i < attrs.length; i++) {\n const name = attrs[i]!.name;\n if (name.startsWith('data-bind:')) {\n targets.add(name.slice(10));\n }\n }\n return targets;\n}\n\n/** Check if an element owns its subtree (data-list or data-if) */\nfunction ownsSubtree(el: Element): boolean {\n return el.hasAttribute('data-list') || el.hasAttribute('data-if');\n}\n\n// ── State shape comparison ────────────────────────────────────────────\n\nfunction getStateKeys(json: string): string[] {\n try {\n const obj = JSON.parse(json);\n return Object.keys(obj).sort();\n } catch {\n return [];\n }\n}\n\nfunction sameShape(keysA: string[], keysB: string[]): boolean {\n if (keysA.length !== keysB.length) return false;\n for (let i = 0; i < keysA.length; i++) {\n if (keysA[i] !== keysB[i]) return false;\n }\n return true;\n}\n\n// ── Scope mode determination ──────────────────────────────────────────\n\nfunction determineScopeMode(liveEl: Element, newEl: Element): ScopeMode {\n const liveModule = liveEl.getAttribute('data-module');\n const newModule = newEl.getAttribute('data-module');\n\n if (liveModule !== newModule) return 'REPLACE';\n\n // Compare state shape: use __formaInitialState (set at mount time) for the\n // live element, and the raw attribute for the new element.\n const liveInitialState = (liveEl as any).__formaInitialState as string | undefined;\n const liveStateJSON = liveInitialState ?? liveEl.getAttribute('data-forma-state') ?? '{}';\n const newStateJSON = newEl.getAttribute('data-forma-state') ?? '{}';\n\n const liveKeys = getStateKeys(liveStateJSON);\n const newKeys = getStateKeys(newStateJSON);\n\n if (sameShape(liveKeys, newKeys)) return 'PRESERVE';\n return 'RESET';\n}\n\n// ── HTML parsing ──────────────────────────────────────────────────────\n\n/** Reused template element — avoids creating a new one per reconcile call. */\nlet _parseTemplate: HTMLTemplateElement | null = null;\n\nfunction parseHTML(html: string): DocumentFragment {\n if (!_parseTemplate) _parseTemplate = document.createElement('template');\n _parseTemplate.innerHTML = html;\n // content is consumed (moved) by the caller, so template is empty after\n return _parseTemplate.content;\n}\n\n// ── Attribute patching ────────────────────────────────────────────────\n\nfunction patchAttributes(liveEl: Element, newEl: Element): void {\n const bindTargets = getBindTargets(liveEl);\n const hasDataShow = liveEl.hasAttribute('data-show');\n const hasDataModel = liveEl.hasAttribute('data-model');\n\n // Check for class directives without Array.from allocation\n let liveHasClassDirectives = false;\n const liveAttrs = liveEl.attributes;\n for (let i = 0; i < liveAttrs.length; i++) {\n if (liveAttrs[i]!.name.startsWith('data-class:')) {\n liveHasClassDirectives = true;\n break;\n }\n }\n\n // Set/update attributes from newEl\n const newAttrs = newEl.attributes;\n for (let i = 0; i < newAttrs.length; i++) {\n const attr = newAttrs[i]!;\n // Skip directive-owned attributes\n if (attr.name === 'style' && hasDataShow) continue;\n if (attr.name === 'class' && liveHasClassDirectives) continue;\n if ((attr.name === 'value' || attr.name === 'checked') && hasDataModel) continue;\n if (bindTargets.has(attr.name)) continue;\n\n const liveVal = liveEl.getAttribute(attr.name);\n if (liveVal !== attr.value) {\n liveEl.setAttribute(attr.name, attr.value);\n }\n }\n\n // Remove attributes that are no longer present in newEl\n // Iterate backwards since removeAttribute shifts indices\n for (let i = liveAttrs.length - 1; i >= 0; i--) {\n const attr = liveAttrs[i]!;\n if (!newEl.hasAttribute(attr.name)) {\n if (attr.name === 'style' && hasDataShow) continue;\n if (attr.name === 'class' && liveHasClassDirectives) continue;\n if ((attr.name === 'value' || attr.name === 'checked') && hasDataModel) continue;\n if (bindTargets.has(attr.name)) continue;\n\n liveEl.removeAttribute(attr.name);\n }\n }\n}\n\n// ── Text node patching ────────────────────────────────────────────────\n\nfunction patchTextNodes(liveEl: Element, newEl: Element): void {\n // data-text directive owns this element's text content — don't overwrite\n if (liveEl.hasAttribute('data-text')) return;\n\n const liveTexts: Text[] = [];\n const newTexts: { node: Text; index: number }[] = [];\n\n for (const child of Array.from(liveEl.childNodes)) {\n if (child.nodeType === Node.TEXT_NODE) liveTexts.push(child as Text);\n }\n for (let i = 0; i < newEl.childNodes.length; i++) {\n const child = newEl.childNodes[i];\n if (child.nodeType === Node.TEXT_NODE) newTexts.push({ node: child as Text, index: i });\n }\n\n // Fast path: same count, just patch content\n if (liveTexts.length === newTexts.length) {\n for (let i = 0; i < liveTexts.length; i++) {\n if (liveTexts[i].textContent !== newTexts[i].node.textContent) {\n liveTexts[i].textContent = newTexts[i].node.textContent;\n }\n }\n return;\n }\n\n // Count mismatch: reuse live text nodes in order, insert/remove as needed\n const usedLive = new Set<Text>();\n let liveIdx = 0;\n\n for (const { node: newText, index: newChildIdx } of newTexts) {\n if (liveIdx < liveTexts.length) {\n // Reuse existing text node\n const liveText = liveTexts[liveIdx]!;\n liveIdx++;\n usedLive.add(liveText);\n if (liveText.textContent !== newText.textContent) {\n liveText.textContent = newText.textContent;\n }\n } else {\n // Insert new text node at correct position\n const ref = findTextInsertionRef(liveEl, newEl, newChildIdx);\n liveEl.insertBefore(document.createTextNode(newText.textContent ?? ''), ref);\n }\n }\n\n // Remove unused live text nodes\n for (const lt of liveTexts) {\n if (!usedLive.has(lt) && lt.parentNode === liveEl) {\n liveEl.removeChild(lt);\n }\n }\n}\n\n/** Find the insertion reference node for a text node being inserted into liveEl. */\nfunction findTextInsertionRef(liveEl: Element, newEl: Element, newIdx: number): Node | null {\n for (let j = newIdx + 1; j < newEl.childNodes.length; j++) {\n const sibling = newEl.childNodes[j];\n if (sibling.nodeType === Node.ELEMENT_NODE) {\n const key = (sibling as Element).getAttribute('data-forma-id');\n if (key) {\n const match = liveEl.querySelector(`[data-forma-id=\"${CSS.escape(key)}\"]`);\n if (match && match.parentElement === liveEl) return match;\n }\n }\n }\n return null;\n}\n\n// ── Recursive element diffing ─────────────────────────────────────────\n\nfunction diffChildren(\n liveParent: Element,\n newParent: Element,\n config: ReconcilerConfig,\n): void {\n // Skip directive-owned subtrees\n if (ownsSubtree(liveParent)) return;\n\n // Patch text nodes at this level\n patchTextNodes(liveParent, newParent);\n\n // Collect child elements (ignore text nodes for structural diff)\n const liveChildren = Array.from(liveParent.children);\n const newChildren = Array.from(newParent.children);\n\n // Build keyed maps for data-forma-id elements\n const liveKeyed = new Map<string, Element>();\n const liveUnkeyed: Element[] = [];\n for (const child of liveChildren) {\n if (child.hasAttribute('data-forma-leaving')) continue;\n const key = child.getAttribute('data-forma-id');\n if (key) {\n liveKeyed.set(key, child);\n } else {\n liveUnkeyed.push(child);\n }\n }\n\n let unkeyedIdx = 0;\n\n // Walk new children in order\n const usedLiveElements = new Set<Element>();\n\n for (const newChild of newChildren) {\n const key = newChild.getAttribute('data-forma-id');\n let liveMatch: Element | undefined;\n\n if (key) {\n liveMatch = liveKeyed.get(key);\n } else {\n // Match unkeyed elements by position and tag\n while (unkeyedIdx < liveUnkeyed.length) {\n const candidate = liveUnkeyed[unkeyedIdx];\n unkeyedIdx++;\n if (candidate.tagName === newChild.tagName && !usedLiveElements.has(candidate)) {\n liveMatch = candidate;\n break;\n }\n }\n }\n\n if (liveMatch) {\n usedLiveElements.add(liveMatch);\n\n // Check if this is a data-forma-state scope element\n if (liveMatch.hasAttribute('data-forma-state') && newChild.hasAttribute('data-forma-state')) {\n const mode = determineScopeMode(liveMatch, newChild);\n\n switch (mode) {\n case 'PRESERVE':\n // Patch attributes only, keep reactive bindings alive\n patchAttributes(liveMatch, newChild);\n // Recurse into non-directive-owned children\n diffChildren(liveMatch, newChild, config);\n break;\n\n case 'RESET':\n // Unmount old scope, patch DOM, mount fresh\n config.unmountScope(liveMatch);\n patchAttributes(liveMatch, newChild);\n // Replace inner content\n replaceInnerContent(liveMatch, newChild);\n config.mountScope(liveMatch);\n break;\n\n case 'REPLACE': {\n // Full element swap\n config.unmountScope(liveMatch);\n const replacement = newChild.cloneNode(true) as Element;\n liveParent.replaceChild(replacement, liveMatch);\n config.mountScope(replacement);\n usedLiveElements.delete(liveMatch);\n liveMatch = replacement;\n usedLiveElements.add(replacement);\n break;\n }\n }\n } else {\n // Non-scope element: patch attrs and recurse\n patchAttributes(liveMatch, newChild);\n diffChildren(liveMatch, newChild, config);\n }\n\n // Ensure element is in the correct position\n // Find where it should be relative to previousSibling\n ensurePosition(liveParent, liveMatch, newChild, newChildren);\n } else {\n // New element — insert it\n const clone = newChild.cloneNode(true) as Element;\n // Find insertion point\n const insertionRef = findInsertionPoint(liveParent, newChild, newChildren);\n liveParent.insertBefore(clone, insertionRef);\n usedLiveElements.add(clone);\n\n // Mount any scopes in the new element\n if (clone.hasAttribute('data-forma-state')) {\n config.mountScope(clone);\n }\n const nestedScopes = clone.querySelectorAll('[data-forma-state]');\n for (const nested of Array.from(nestedScopes)) {\n config.mountScope(nested);\n }\n }\n }\n\n // Remove live children that are no longer in new children\n for (const child of liveChildren) {\n if (!usedLiveElements.has(child)) {\n // Guard: element may already be detached (e.g. after REPLACE)\n if (child.parentElement !== liveParent) continue;\n // Guard: element is mid-leave transition — its transition will remove it\n if (child.hasAttribute('data-forma-leaving')) continue;\n // Unmount any scopes\n if (child.hasAttribute('data-forma-state')) {\n config.unmountScope(child);\n }\n const nestedScopes = child.querySelectorAll('[data-forma-state]');\n for (const nested of Array.from(nestedScopes)) {\n config.unmountScope(nested);\n }\n liveParent.removeChild(child);\n }\n }\n}\n\n/** Replace inner content of live element with content from new element */\nfunction replaceInnerContent(liveEl: Element, newEl: Element): void {\n // Remove all children\n while (liveEl.firstChild) {\n liveEl.removeChild(liveEl.firstChild);\n }\n // Clone and append all children from new element\n for (const child of Array.from(newEl.childNodes)) {\n liveEl.appendChild(child.cloneNode(true));\n }\n}\n\n/** Ensure a live element is at the correct position */\nfunction ensurePosition(\n parent: Element,\n liveEl: Element,\n _newEl: Element,\n newChildren: Element[],\n): void {\n const newIdx = newChildren.indexOf(_newEl);\n const liveChildElements = Array.from(parent.children);\n const currentIdx = liveChildElements.indexOf(liveEl);\n\n if (currentIdx !== newIdx) {\n // Find the element that should come after this one\n const nextNewChild = newChildren[newIdx + 1];\n if (nextNewChild) {\n const nextKey = nextNewChild.getAttribute('data-forma-id');\n if (nextKey) {\n // Find this element in live DOM\n const nextLive = parent.querySelector(`[data-forma-id=\"${CSS.escape(nextKey)}\"]`);\n if (nextLive && nextLive.parentElement === parent) {\n parent.insertBefore(liveEl, nextLive);\n return;\n }\n }\n }\n // Append to end\n parent.appendChild(liveEl);\n }\n}\n\n/** Find the correct insertion point for a new element */\nfunction findInsertionPoint(\n parent: Element,\n newChild: Element,\n newChildren: Element[],\n): Node | null {\n const newIdx = newChildren.indexOf(newChild);\n\n // Look for the next sibling in the new children that exists in the live DOM\n for (let i = newIdx + 1; i < newChildren.length; i++) {\n const key = newChildren[i].getAttribute('data-forma-id');\n if (key) {\n const existing = parent.querySelector(`[data-forma-id=\"${CSS.escape(key)}\"]`);\n if (existing && existing.parentElement === parent) {\n return existing;\n }\n }\n }\n\n return null; // Append to end\n}\n\n// ── Factory ───────────────────────────────────────────────────────────\n\nexport function createReconciler(config: ReconcilerConfig) {\n /** Last HTML string that was successfully reconciled into this container.\n * Used to skip reconciliation when the HTML hasn't changed. */\n let _lastHtml = '';\n\n return function reconcile(container: Element, html: string): void {\n const trimmed = html.trim();\n if (!trimmed) return;\n\n // Fast path: skip reconciliation entirely when HTML is identical\n if (trimmed === _lastHtml && container.hasChildNodes()) return;\n _lastHtml = trimmed;\n\n // Disconnect observer to prevent double-mount during patching\n config.disconnectObserver();\n\n try {\n // ── Fast path: empty container ──\n if (!container.hasChildNodes() || container.children.length === 0) {\n container.innerHTML = trimmed;\n\n // Mount all data-forma-state scopes\n config.batch(() => {\n const scopes = container.querySelectorAll('[data-forma-state]');\n for (const scope of Array.from(scopes)) {\n config.mountScope(scope);\n }\n });\n\n return;\n }\n\n // ── Parse new HTML into a DocumentFragment ──\n const fragment = parseHTML(trimmed);\n const templateContainer = document.createElement('div');\n templateContainer.appendChild(fragment);\n\n // ── Full-replacement fast path ──\n // When there is zero data-forma-id overlap between live and new children,\n // skip the diff entirely — dispose all live scopes, innerHTML, mount fresh.\n // This handles module-switch scenarios cleanly and avoids issues with\n // corrupted HTML confusing the diff.\n const liveKeys = new Set<string>();\n for (const child of Array.from(container.children)) {\n if (child.hasAttribute('data-forma-leaving')) continue;\n const key = child.getAttribute('data-forma-id');\n if (key) liveKeys.add(key);\n }\n let hasOverlap = false;\n if (liveKeys.size > 0) {\n for (const child of Array.from(templateContainer.children)) {\n const key = child.getAttribute('data-forma-id');\n if (key && liveKeys.has(key)) { hasOverlap = true; break; }\n }\n }\n\n if (liveKeys.size > 0 && !hasOverlap) {\n // Full replacement: unmount all live scopes, replace content, mount new\n config.batch(() => {\n const liveScopes = container.querySelectorAll('[data-forma-state]');\n for (const scope of Array.from(liveScopes)) {\n config.unmountScope(scope);\n }\n container.innerHTML = trimmed;\n const newScopes = container.querySelectorAll('[data-forma-state]');\n for (const scope of Array.from(newScopes)) {\n config.mountScope(scope);\n }\n });\n return;\n }\n\n // ── Diff and patch ──\n config.batch(() => {\n diffChildren(container, templateContainer, config);\n });\n } finally {\n // Always reconnect observer, even if an error occurred\n config.reconnectObserver();\n }\n };\n}\n"],"mappings":"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","names":["runtime_exports","__export","applyContainmentHints","clearDiagnostics","destroyRuntime","getDiagnostics","getScopes","getUnsafeEvalMode","initRuntime","mount","reconcile","resetScope","setDebug","setDiagnostics","setDirectiveMap","setScopeValue","setUnsafeEval","setUnsafeEvalMode","unmount","yieldToMain","createReactiveSystem","update","notify","unwatched","link","unlink","propagate","checkDirty","shallowPropagate","dep","sub","version","prevDep","nextDep","prevSub","newLink","nextSub","next","stack","top","flags","isValidLink","subSubs","checkDepth","dirty","subs","firstSub","hasMultipleSubs","checkLink","cycle","batchDepth","notifyIndex","queuedLength","activeSub","queued","link","unlink","propagate","checkDirty","shallowPropagate","createReactiveSystem","node","updateComputed","updateSignal","effect","insertIndex","firstInsertedIndex","left","purgeDeps","effectScopeOper","setActiveSub","sub","prevSub","activeSub","startBatch","batchDepth","endBatch","flush","signal","initialValue","signalOper","computed","getter","computedOper","effect","fn","e","prevSub","setActiveSub","link","activeSub","effectOper","updateComputed","c","cycle","prevSub","setActiveSub","oldValue","activeSub","purgeDeps","updateSignal","s","run","flags","checkDirty","flush","notifyIndex","queuedLength","effect","queued","computedOper","subs","shallowPropagate","sub","link","signalOper","value","propagate","batchDepth","effectOper","effectScopeOper","unlink","depsTail","dep","applySignalSet","s","v","equals","prevSub","setActiveSub","prev","next","createSignal","initialValue","options","signal","getter","eq","currentRoot","registerDisposer","dispose","currentRoot","hasActiveRoot","POOL_SIZE","pool","i","POOL_SIZE","internalEffect","fn","dispose","effect","hasActiveRoot","registerDisposer","createComputed","fn","computed","batch","fn","startBatch","endBatch","longestIncreasingSubsequence","arr","n","tails","tailIndices","predecessor","tailsLen","i","val","lo","hi","mid","result","idx","SMALL_LIST_THRESHOLD","reconcileSmall","parent","oldItems","newItems","oldNodes","keyFn","createFn","updateFn","beforeNode","hooks","oldLen","newLen","oldKeys","i","oldIndices","oldUsed","key","found","j","node","allSameOrder","nodes","reusedIndices","reusedPositions","lisOfReused","longestIncreasingSubsequence","lisFlags","li","newNodes","nextSibling","isNew","reconcileList","SMALL_LIST_THRESHOLD","oldKeyMap","oldIdx","getBindTargets","el","targets","attrs","i","name","ownsSubtree","getStateKeys","json","obj","sameShape","keysA","keysB","determineScopeMode","liveEl","newEl","liveModule","newModule","liveStateJSON","newStateJSON","liveKeys","newKeys","_parseTemplate","parseHTML","html","patchAttributes","bindTargets","hasDataShow","hasDataModel","liveHasClassDirectives","liveAttrs","newAttrs","attr","patchTextNodes","liveTexts","newTexts","child","usedLive","liveIdx","newText","newChildIdx","liveText","ref","findTextInsertionRef","lt","newIdx","j","sibling","key","match","diffChildren","liveParent","newParent","config","liveChildren","newChildren","liveKeyed","liveUnkeyed","unkeyedIdx","usedLiveElements","newChild","liveMatch","candidate","replaceInnerContent","replacement","ensurePosition","clone","insertionRef","findInsertionPoint","nestedScopes","nested","parent","_newEl","nextNewChild","nextKey","nextLive","existing","createReconciler","_lastHtml","container","trimmed","scopes","scope","fragment","templateContainer","hasOverlap","liveScopes","newScopes","_refetchRegistry","$refetch","id","fn","_debug","dbg","createChildScope","parent","locals","localGetters","key","target","prop","_unsafeEvalMode","_allowUnsafeEval","_diagnosticsEnabled","args","diagnostics","parseBooleanFlag","raw","normalized","parseUnsafeEvalMode","readRuntimeConfig","config","globalConfig","parsed","script","unsafeFromAttr","modeFromAttr","lockFromAttr","diagnosticsFromAttr","containmentFromAttr","reportDiagnostic","kind","expr","reason","now","existing","detail","buildUnsafeEvalMode","runtimeConfig","configUnsafeMode","_autoContainment","getScheduler","candidate","yieldToMain","scheduler","resolve","applyContainmentHints","root","options","selector","nodes","applied","i","el","contain","contentVisibility","containIntrinsicSize","skipExisting","changed","containCurrent","contentVisCurrent","containSizeCurrent","RE_STRING_SINGLE","RE_STRING_DOUBLE","RE_NUMBER","RE_IDENTIFIER","RE_DOT_ACCESS","RE_BRACKET","RE_TERNARY","RE_NULLISH","RE_AND","RE_OR","RE_COMPARISON","RE_MUL","RE_ADD","RE_TEMPLATE_LIT","RE_TEMPLATE_INTERP","RE_GROUP_METHOD_CALL","RE_STRIP_BRACES","RE_DIGIT_ONLY","RE_POST_INCR","RE_PRE_INCR","RE_TOGGLE","RE_ASSIGN","RE_COMPOUND","RE_IF_PREFIX","RE_COMPUTED","RE_FETCH","RE_FETCH_METHOD","RE_STRIP_ITEM_BRACES","RE_EVENT_REF","RE_REFETCH_CALL","TRANSITION_STATE_SYM","EXPRESSION_CACHE_MAX","expressionCache","cacheExpression","key","factory","first","scopeExpressionCache","scopeHandlerCache","compiledTemplateCache","COMPILED_TEMPLATE_CACHE_MAX","cacheCompiledTemplate","template","UNSAFE_METHOD_NAMES","BLOCKED_METHOD_REGEXES","result","name","escaped","findBlockedMethod","expr","cleaned","dotRe","bracketRe","bracketContents","extractBracketContents","content","fragments","joined","f","results","depth","start","TEXT_BINDING_SYM","toTextValue","value","setElementTextFast","el","next","cache","node","splitCallArgs","raw","out","inSingle","inDouble","i","ch","readBalancedSegment","input","open","close","inTemplate","splitTopLevelStatements","depthParen","depthBrace","depthBracket","stmt","tail","consumeStatement","block","body","rest","parseIfHandler","scope","idx","condSegment","condExpr","parseExpression","thenStmt","thenHandler","parseHandler","elseHandler","elseStmt","e","batch","unwrapOuterParens","segment","inner","compileTemplate","text","cached","statics","dynamics","lastIndex","re","m","templateTexts","evaluateCompiledTemplate","compiled","item","result","i","key","cloneWithTemplateData","template","clone","walker","node","text","compileTemplate","templateTexts","cloneAttributeTemplates","updateTemplateData","el","templateAttrs","DIRECTIVE_ATTR_PREFIXES","isDirectiveAttr","name","prefix","splitClassTokens","raw","parseDurationTokenMs","token","parseClassTokensAndDuration","classes","durationMs","parsed","uniqueTokens","tokens","parseCssTimeListMs","part","ms","maxCombinedTimingsMs","durations","delays","len","max","d","delay","resolveTransitionDurationMs","explicitMs","cs","trans","anim","getTransitionState","existing","TRANSITION_STATE_SYM","created","clearTransitionState","state","parseTransitionSpec","a","base","enter","leave","enterFrom","enterTo","leaveFrom","leaveTo","durationBoth","enterDuration","leaveDuration","removeClasses","cls","addClasses","runTransitionPhase","phaseClasses","onDone","cleanupClasses","done","timeoutId","raf1","raf2","finish","transitionInsert","parent","ref","spec","current","transitionRemove","applyShowVisibility","visible","transition","initial","all","entries","attr","parseChainedAccess","expr","scope","pos","identMatch","rootName","steps","optional","nameMatch","UNSAFE_METHOD_NAMES","balanced","readBalancedSegment","argsRaw","argFns","arg","splitCallArgs","parseExpression","rootExpr","val","step","method","args","fn","cachedFactory","expressionCache","parseExpressionUncached","cacheExpression","RE_IDENTIFIER","s","RE_STRING_SINGLE","RE_STRING_DOUBLE","RE_NUMBER","dotMatch","RE_DOT_ACCESS","p1","p2","unwrapped","unwrapOuterParens","chainResult","groupedCallMatch","RE_GROUP_METHOD_CALL","baseRaw","methodName","baseExpr","inner","bracketMatch","RE_BRACKET","objExpr","rawKey","RE_DIGIT_ONLY","elements","elementFns","allParsed","ternaryMatch","RE_TERNARY","cond","then","els","nullishMatch","RE_NULLISH","left","right","orMatch","RE_OR","andMatch","RE_AND","compMatch","RE_COMPARISON","op","l","r","addMatch","RE_ADD","mulMatch","RE_MUL","tmplMatch","RE_TEMPLATE_LIT","staticParts","dynamicFns","lastIndex","re","RE_TEMPLATE_INTERP","m","getScopeCache","cache","scoped","cspExpressionHint","buildEvaluator","cleaned","RE_STRIP_BRACES","scopeExpressionCache","cached","cspFn","_allowUnsafeEval","dbg","reportDiagnostic","blocked","blockedMethod","findBlockedMethod","msg","proxy","_","g","unsafe","failed","parseHandler","normalized","ifHandler","parseIfHandler","stmts","splitTopLevelStatements","handlers","h","e","batch","single","incrMatch","RE_POST_INCR","preIncrMatch","RE_PRE_INCR","toggleMatch","RE_TOGGLE","assignMatch","RE_ASSIGN","valExpr","_debug","compoundMatch","RE_COMPOUND","refetchMatch","RE_REFETCH_CALL","fetchId","$refetch","buildHandler","seg","scopeHandlerCache","value","FORBIDDEN_STATE_KEYS","parseState","initScope","stateEl","keys","getters","setters","get","set","createSignal","SAFE_EL_PROPS","createSafeElProxy","target","prop","bindElement","disposers","elMagics","detail","createChildScope","known","getDirectives","computedAttr","parts","trimmed","match","RE_COMPUTED","prevGetter","evaluate","getter","createComputed","textExpr","dispose","internalEffect","setElementTextFast","toTextValue","showExpr","tag","initialized","ifExpr","placeholder","inserted","show","modelExpr","setter","input","event","onModelInput","hasColonDirectives","hasAnyPrefix","attrs","built","handler","id","attrVal","tracedHandler","attrName","persistExpr","saved","listExpr","templateEl","disposeCloneBindings","createBoundClone","index","childScope","itemDisposers","desc","updateBoundClone","keyAttr","keyProp","RE_STRIP_ITEM_BRACES","listTransition","oldItems","oldNodes","listHooks","htmlEl","rawItems","n","leavingNodes","ln","prevNodes","reconcileList","idx","nextNodes","wrapped","w","fetchExpr","arrowMatch","RE_FETCH","urlPart","modifiers","url","methodMatch","RE_FETCH_METHOD","loadingTarget","errorTarget","interval","mod","k","v","getTarget","setTarget","gl","sl","ge","se","doFetch","data","err","_refetchRegistry","DIRECTIVE_SELECTOR","hasDirective","_directiveMap","setDirectiveMap","map","buildDirectiveSelector","prefixes","entry","mountScope","root","boundCount","selector","targets","descendants","unmountScope","_observer","ELEMENT_NODE","MUTATION_CHUNK_SIZE","_pendingMutations","_drainingMutations","processMutation","mutation","removed","j","added","drainMutationQueue","yieldToMain","handleMutations","mutations","startObserver","stopObserver","initRuntime","_autoContainment","applyContainmentHints","stateRoots","destroyRuntime","mount","unmount","setDebug","on","setUnsafeEvalMode","mode","_unsafeEvalMode","setUnsafeEval","getUnsafeEvalMode","setDiagnostics","_diagnosticsEnabled","getDiagnostics","diagnostics","clearDiagnostics","getScopes","roots","initialJSON","values","setScopeValue","element","resetScope","_reconciler","getReconciler","createReconciler","reconcile","container","html"]}
1
+ {"version":3,"sources":["../src/runtime.ts","../node_modules/alien-signals/esm/system.mjs","../node_modules/alien-signals/esm/index.mjs","../src/reactive/signal.ts","../src/reactive/root.ts","../src/reactive/effect.ts","../src/reactive/computed.ts","../src/reactive/batch.ts","../src/dom/list.ts","../src/dom/reconcile.ts"],"sourcesContent":["/**\n * FormaJS HTML Runtime\n *\n * Declarative reactive UI via data-* attributes, powered by fine-grained\n * signals (alien-signals 3.x). Combined into a single, CSP-safe runtime\n * with zero build step required.\n *\n * Design inspirations:\n * Alpine.js — data-* directive model, progressive enhancement\n * SolidJS — fine-grained signals, [getter, setter] tuple, real DOM\n * Qwik — deferred hydration triggers (idle, interaction, visible)\n * Astro — islands architecture, independent interactive regions\n * Hotwire — server-driven UI, reconciler with scope modes\n * Lit — root element access during hydration, (el, props) pattern\n *\n * ┌─────────────────────────────────────────────────────────────────────┐\n * │ Yes, this file is 3,188 lines. It's a monolith on purpose. │\n * │ │\n * │ The HTML Runtime is a self-contained unit: expression parser, │\n * │ handler compiler, transition system, DOM scanner, and observer │\n * │ all share mutable state (debug flags, caches, eval mode). Keeping │\n * │ them in one file avoids circular imports, simplifies the build │\n * │ (single IIFE for CDN), and means `grep` always finds what you │\n * │ need. The sections are clearly marked — use the map below. │\n * │ │\n * │ Will it be split someday? Maybe. But today it works, it's tested │\n * │ (799 tests), and it ships at 15KB gzipped. If you're reading this │\n * │ and judging the line count — fair. But read the code first. :) │\n * └─────────────────────────────────────────────────────────────────────┘\n *\n * Usage (CDN — this file compiles to dist/formajs-runtime.global.js):\n * <script src=\"https://unpkg.com/@getforma/core/dist/formajs-runtime.global.js\"></script>\n * <div data-forma-state='{\"count\": 0}'>\n * <p data-text=\"{count}\"></p>\n * <button data-on:click=\"{count++}\">+1</button>\n * </div>\n *\n * Build outputs from this source file:\n * dist/runtime.js ESM (import '@getforma/core/runtime')\n * dist/runtime.cjs CommonJS (require)\n * dist/formajs-runtime.global.js IIFE for <script> tags (auto-inits)\n * dist/runtime-hardened.js ESM, unsafe-eval locked off\n * dist/formajs-runtime-hardened.global.js IIFE, unsafe-eval locked off\n *\n * ── FILE MAP ──────────────────────────────────────────────────────────\n *\n * Line ~31-71 Core types & scope (Getter, Setter, Scope, createChildScope)\n * Line ~73-253 Configuration & diagnostics (debug, CSP modes, containment)\n * Line ~254-344 Performance utilities (yieldToMain, containment hints)\n * Line ~346-534 Regexes, caches, security blocklist (findBlockedMethod)\n * Line ~536-923 Parsing utilities (splitCallArgs, readBalancedSegment, if-handler)\n * Line ~925-1049 Template compilation (data-list templates)\n * Line ~1051-1396 CSS Transitions (parse, run, enter/leave phases)\n * Line ~1398-1809 CSP-safe expression parser (chained access, operators, literals)\n * Line ~1811-2091 Evaluator & handler builder (CSP path + new Function fallback)\n * Line ~2093-2184 State initialization & safe $el proxy\n * Line ~2186-2682 bindElement() — the central directive processor\n * Line ~2684-2952 MutationObserver, directive map, mountScope/unmountScope\n * Line ~2954-3064 Init/destroy, mount/unmount, public API setters\n * Line ~3066-3188 DevTools API, reconciler bridge, exports\n *\n * ── SUPPORTED DIRECTIVES ──────────────────────────────────────────────\n *\n * State & Reactivity:\n * data-forma-state='{\"key\": val}' Declare reactive state (valid JSON)\n * data-computed=\"name = expr\" Derived value (lazy, cached)\n * data-persist=\"{prop}\" Sync state to localStorage\n *\n * Content Binding:\n * data-text=\"{expr}\" Bind text content\n * data-show=\"{expr}\" Toggle visibility (display: none)\n * data-if=\"{expr}\" Conditional render (remove/insert DOM)\n * data-model=\"{prop}\" Two-way input binding\n * data-list=\"{expr}\" List rendering (keyed reconciliation)\n *\n * Attributes & Classes:\n * data-on:event=\"{expr}\" Event handler (e.g. data-on:click)\n * data-class:name=\"{expr}\" Conditional CSS class\n * data-bind:attr=\"{expr}\" Dynamic attribute binding\n *\n * Transitions (for data-show and data-if):\n * data-transition:enter=\"classes\" Classes during enter phase\n * data-transition:enter-from=\"classes\" Classes at enter start\n * data-transition:enter-to=\"classes\" Classes at enter end\n * data-transition:leave=\"classes\" Classes during leave phase\n * data-transition:leave-from=\"classes\" Classes at leave start\n * data-transition:leave-to=\"classes\" Classes at leave end\n *\n * Data Fetching:\n * data-fetch=\"GET /url → prop\" Fetch data into state\n * data-fetch=\"POST /url → prop\" POST with state as body\n * data-fetch-id=\"name\" Register for $refetch('name')\n *\n * Configuration (on <script> tag):\n * data-forma-unsafe-eval=\"true\" Enable new Function() fallback\n * data-forma-diagnostics=\"true\" Enable expression diagnostics\n * data-forma-auto-containment=\"true\" Enable CSS containment hints\n *\n * ── MAGIC VARIABLES ──────────────────────────────────────────────────\n *\n * Available in all expressions and handlers:\n * $el The current DOM element (safe proxy — see createSafeElProxy)\n * $dispatch Fire a CustomEvent: $dispatch('name', detail?)\n * Events bubble and cross Shadow DOM (composed: true)\n * $event The DOM event object (in data-on:* handlers only)\n * event Alias for $event (also in data-on:* handlers)\n * $refetch Re-trigger a data-fetch: $refetch('fetch-id')\n */\nimport { createSignal, internalEffect, createComputed, batch } from './reactive';\nimport { reconcileList, type ListTransitionHooks } from './dom/list';\nimport { createReconciler } from './dom/reconcile';\n\ntype Getter = () => unknown;\ntype Setter = (v: unknown) => void;\n\ninterface Scope {\n getters: Record<string, Getter>;\n setters: Record<string, Setter>;\n}\n\n// ── $refetch registry ──\n// Maps data-fetch-id values to their doFetch() functions so handlers can\n// trigger imperative refetches via $refetch('id').\nconst _refetchRegistry = new Map<string, () => void>();\n\nfunction $refetch(id: string): void {\n const fn = _refetchRegistry.get(id);\n if (fn) {\n fn();\n } else if (_debug) {\n dbg(`$refetch: no data-fetch with id \"${id}\" found`);\n }\n}\n\nfunction createChildScope(parent: Scope, locals: Record<string, unknown>): Scope {\n const localGetters: Record<string, Getter> = Object.create(null);\n for (const key of Object.keys(locals)) {\n localGetters[key] = () => locals[key];\n }\n\n return {\n getters: new Proxy(parent.getters, {\n get(target, prop: string) {\n if (prop in localGetters) return localGetters[prop];\n return target[prop];\n },\n has(target, prop: string) {\n return prop in localGetters || prop in target;\n },\n }),\n setters: parent.setters,\n };\n}\n\n// ── Debug logger — enable via FormaRuntime.debug = true or window.__FORMA_DEBUG = true ──\nlet _debug = false;\ntype UnsafeEvalMode = 'mutable' | 'locked-off' | 'locked-on';\nlet _unsafeEvalMode: UnsafeEvalMode = 'mutable';\nlet _allowUnsafeEval = false;\nlet _diagnosticsEnabled = true;\nfunction dbg(...args: unknown[]): void {\n if (_debug || (typeof window !== 'undefined' && (window as any).__FORMA_DEBUG)) {\n console.log('[FormaJS]', ...args);\n }\n}\n\ninterface RuntimeConfig {\n allowUnsafeEval?: boolean;\n unsafeEvalMode?: UnsafeEvalMode;\n lockUnsafeEval?: boolean;\n diagnostics?: boolean;\n autoContainment?: boolean;\n}\n\ninterface RuntimeDiagnostic {\n kind: 'handler-unsupported' | 'expression-unsupported';\n expr: string;\n reason: string;\n count: number;\n firstSeenAt: number;\n lastSeenAt: number;\n}\n\nconst diagnostics = new Map<string, RuntimeDiagnostic>();\n\nfunction parseBooleanFlag(raw: string | null | undefined): boolean | undefined {\n if (raw == null) return undefined;\n const normalized = raw.trim().toLowerCase();\n if (normalized === '1' || normalized === 'true' || normalized === 'on' || normalized === 'yes') return true;\n if (normalized === '0' || normalized === 'false' || normalized === 'off' || normalized === 'no') return false;\n return undefined;\n}\n\nfunction parseUnsafeEvalMode(raw: string | null | undefined): UnsafeEvalMode | undefined {\n if (raw == null) return undefined;\n const normalized = raw.trim().toLowerCase();\n if (normalized === 'mutable') return 'mutable';\n if (normalized === 'locked-off' || normalized === 'off' || normalized === 'disabled') {\n return 'locked-off';\n }\n if (normalized === 'locked-on' || normalized === 'on' || normalized === 'enabled') {\n return 'locked-on';\n }\n return undefined;\n}\n\nfunction readRuntimeConfig(): RuntimeConfig {\n const config: RuntimeConfig = {};\n\n if (typeof window !== 'undefined') {\n const globalConfig = (window as any).__FORMA_RUNTIME_CONFIG as RuntimeConfig | undefined;\n if (globalConfig) {\n if (typeof globalConfig.allowUnsafeEval === 'boolean') {\n config.allowUnsafeEval = globalConfig.allowUnsafeEval;\n }\n if (typeof globalConfig.unsafeEvalMode === 'string') {\n const parsed = parseUnsafeEvalMode(globalConfig.unsafeEvalMode);\n if (parsed) config.unsafeEvalMode = parsed;\n }\n if (typeof globalConfig.lockUnsafeEval === 'boolean') {\n config.lockUnsafeEval = globalConfig.lockUnsafeEval;\n }\n if (typeof globalConfig.diagnostics === 'boolean') {\n config.diagnostics = globalConfig.diagnostics;\n }\n if (typeof globalConfig.autoContainment === 'boolean') {\n config.autoContainment = globalConfig.autoContainment;\n }\n }\n }\n\n if (typeof document !== 'undefined') {\n const script = document.currentScript as HTMLScriptElement | null;\n if (script) {\n const unsafeFromAttr = parseBooleanFlag(script.getAttribute('data-forma-unsafe-eval'));\n if (unsafeFromAttr !== undefined) {\n config.allowUnsafeEval = unsafeFromAttr;\n }\n const modeFromAttr = parseUnsafeEvalMode(\n script.getAttribute('data-forma-unsafe-eval-mode'),\n );\n if (modeFromAttr !== undefined) {\n config.unsafeEvalMode = modeFromAttr;\n }\n const lockFromAttr = parseBooleanFlag(script.getAttribute('data-forma-lock-unsafe-eval'));\n if (lockFromAttr !== undefined) {\n config.lockUnsafeEval = lockFromAttr;\n }\n const diagnosticsFromAttr = parseBooleanFlag(script.getAttribute('data-forma-diagnostics'));\n if (diagnosticsFromAttr !== undefined) {\n config.diagnostics = diagnosticsFromAttr;\n }\n const containmentFromAttr = parseBooleanFlag(script.getAttribute('data-forma-auto-containment'));\n if (containmentFromAttr !== undefined) {\n config.autoContainment = containmentFromAttr;\n }\n }\n }\n\n return config;\n}\n\nfunction reportDiagnostic(\n kind: RuntimeDiagnostic['kind'],\n expr: string,\n reason: string,\n): void {\n if (!_diagnosticsEnabled) return;\n\n const key = `${kind}|${reason}|${expr}`;\n const now = Date.now();\n const existing = diagnostics.get(key);\n\n if (existing) {\n existing.count += 1;\n existing.lastSeenAt = now;\n } else {\n diagnostics.set(key, {\n kind,\n expr,\n reason,\n count: 1,\n firstSeenAt: now,\n lastSeenAt: now,\n });\n console.warn(`[FormaJS] ${reason}: ${expr}`);\n }\n\n try {\n if (typeof window !== 'undefined') {\n const detail = {\n kind,\n expr,\n reason,\n count: diagnostics.get(key)?.count ?? 1,\n };\n window.dispatchEvent(new CustomEvent('formajs:diagnostic', { detail }));\n }\n } catch {\n // Ignore event dispatch failures\n }\n}\n\ndeclare const __FORMA_UNSAFE_EVAL_MODE__: string | undefined;\nconst buildUnsafeEvalMode = parseUnsafeEvalMode(\n typeof __FORMA_UNSAFE_EVAL_MODE__ === 'string'\n ? __FORMA_UNSAFE_EVAL_MODE__\n : undefined,\n);\n\nif (buildUnsafeEvalMode) {\n _unsafeEvalMode = buildUnsafeEvalMode;\n if (_unsafeEvalMode === 'locked-off') _allowUnsafeEval = false;\n if (_unsafeEvalMode === 'locked-on') _allowUnsafeEval = true;\n if (_unsafeEvalMode === 'mutable') _allowUnsafeEval = true;\n}\n\nconst runtimeConfig = readRuntimeConfig();\nconst configUnsafeMode = runtimeConfig.lockUnsafeEval\n ? 'locked-off'\n : runtimeConfig.unsafeEvalMode;\nif (configUnsafeMode) {\n _unsafeEvalMode = configUnsafeMode;\n if (_unsafeEvalMode === 'locked-off') _allowUnsafeEval = false;\n if (_unsafeEvalMode === 'locked-on') _allowUnsafeEval = true;\n}\nif (\n _unsafeEvalMode === 'mutable'\n && typeof runtimeConfig.allowUnsafeEval === 'boolean'\n) {\n _allowUnsafeEval = runtimeConfig.allowUnsafeEval;\n}\nif (typeof runtimeConfig.diagnostics === 'boolean') {\n _diagnosticsEnabled = runtimeConfig.diagnostics;\n}\nconst _autoContainment = runtimeConfig.autoContainment === true;\n\ninterface SchedulerLike {\n yield?: () => Promise<unknown>;\n postTask?: (\n callback: () => void,\n options?: { priority?: 'user-blocking' | 'user-visible' | 'background' },\n ) => Promise<unknown>;\n}\n\nfunction getScheduler(): SchedulerLike | undefined {\n const candidate = (globalThis as any)?.scheduler as SchedulerLike | undefined;\n if (!candidate) return undefined;\n if (typeof candidate.yield === 'function' || typeof candidate.postTask === 'function') {\n return candidate;\n }\n return undefined;\n}\n\n/** Yield control to keep the main thread responsive during large batches. */\nasync function yieldToMain(): Promise<void> {\n const scheduler = getScheduler();\n if (scheduler?.yield) {\n await scheduler.yield();\n return;\n }\n if (scheduler?.postTask) {\n await scheduler.postTask(() => {}, { priority: 'background' });\n return;\n }\n await new Promise<void>((resolve) => setTimeout(resolve, 0));\n}\n\ninterface ContainmentHintsOptions {\n selector?: string;\n contain?: string;\n contentVisibility?: string;\n containIntrinsicSize?: string;\n skipIfAlreadySet?: boolean;\n}\n\n/** Apply CSS containment hints to opt-in containers for lower layout/paint cost. */\nfunction applyContainmentHints(\n root: ParentNode = document,\n options: ContainmentHintsOptions = {},\n): number {\n const selector = options.selector ?? '[data-forma-contain]';\n if (!selector) return 0;\n if (typeof (root as ParentNode).querySelectorAll !== 'function') return 0;\n\n const nodes = root.querySelectorAll(selector);\n let applied = 0;\n for (let i = 0; i < nodes.length; i++) {\n const el = nodes[i] as HTMLElement;\n if (!el?.style) continue;\n\n const contain = el.getAttribute('data-forma-contain') ?? options.contain ?? 'layout style paint';\n const contentVisibility = el.getAttribute('data-forma-content-visibility')\n ?? options.contentVisibility\n ?? 'auto';\n const containIntrinsicSize = el.getAttribute('data-forma-contain-intrinsic-size')\n ?? options.containIntrinsicSize\n ?? 'auto 800px';\n const skipExisting = options.skipIfAlreadySet === true;\n let changed = false;\n\n const containCurrent = el.style.getPropertyValue('contain');\n const contentVisCurrent = el.style.getPropertyValue('content-visibility');\n const containSizeCurrent = el.style.getPropertyValue('contain-intrinsic-size');\n\n if (contain !== 'off' && (!skipExisting || !containCurrent)) {\n el.style.setProperty('contain', contain);\n changed = true;\n }\n if (contentVisibility !== 'off' && (!skipExisting || !contentVisCurrent)) {\n el.style.setProperty('content-visibility', contentVisibility);\n changed = true;\n }\n if (containIntrinsicSize !== 'off' && (!skipExisting || !containSizeCurrent)) {\n el.style.setProperty('contain-intrinsic-size', containIntrinsicSize);\n changed = true;\n }\n\n if (changed) applied++;\n }\n\n if (_debug && applied > 0) {\n dbg('applyContainmentHints: applied to', applied, 'element(s)');\n }\n return applied;\n}\n\n// ── Pre-compiled regexes (avoid re-creation in hot paths) ──\n\nconst RE_STRING_SINGLE = /^'[^']*'$/;\nconst RE_STRING_DOUBLE = /^\"[^\"]*\"$/;\nconst RE_NUMBER = /^-?\\d+(\\.\\d+)?$/;\nconst RE_IDENTIFIER = /^[a-zA-Z_$]\\w*$/;\nconst RE_DOT_ACCESS = /^(\\w+)\\.(\\w+)$/;\nconst RE_DEEP_DOT = /^(\\w+)\\.(\\w+)\\.(\\w+)(?:\\.(\\w+))?$/;\nconst RE_BRACKET = /^(\\w+)\\[(\\d+|'[^']*'|\"[^\"]*\")\\]$/;\nconst RE_TERNARY = /^(.+?)\\s*\\?\\s*(.+?)\\s*:\\s*(.+)$/;\nconst RE_NULLISH = /^(.+?)\\s*\\?\\?\\s*(.+)$/;\nconst RE_AND = /^(.+?)\\s*&&\\s*(.+)$/;\nconst RE_OR = /^(.+?)\\s*\\|\\|\\s*(.+)$/;\nconst RE_COMPARISON = /^(.+?)\\s*(===|!==|==|!=|>=|<=|>|<)\\s*(.+)$/;\nconst RE_MUL = /^(.+?)\\s*([*/%])\\s*(.+)$/;\nconst RE_ADD = /^(.+?)\\s*([+-])\\s*(.+)$/;\nconst RE_TEMPLATE_LIT = /^`([^`]*)`$/;\nconst RE_TEMPLATE_INTERP = /\\$\\{([^}]+)\\}/g;\nconst RE_METHOD_CALL = /^(\\w+)\\.(\\w+)\\((.*)\\)$/;\nconst RE_GROUP_METHOD_CALL = /^\\((.+)\\)\\.(\\w+)\\((.*)\\)$/;\nconst RE_STRIP_BRACES = /^\\{|\\}$/g;\nconst RE_ITEM_TEMPLATE = /\\{item\\.?(\\w*)\\}/g;\nconst RE_DIGIT_ONLY = /^\\d+$/;\nconst RE_POST_INCR = /^(\\w+)(\\+\\+|--)$/;\nconst RE_PRE_INCR = /^(\\+\\+|--)(\\w+)$/;\nconst RE_TOGGLE = /^(\\w+)\\s*=\\s*!(\\w+)$/;\nconst RE_ASSIGN = /^(\\w+)\\s*=\\s*(.+)$/;\nconst RE_COMPOUND = /^(\\w+)\\s*(\\+=|-=|\\*=|\\/=)\\s*(.+)$/;\nconst RE_IF_PREFIX = /^if\\b/;\n// RE_UNQUOTED_KEYS removed in v0.5.0 — relaxed JSON parsing corrupted URLs\n// and string values containing colons. Use valid JSON in data-forma-state.\nconst RE_COMPUTED = /^(\\w+)\\s*=\\s*(.+)$/;\nconst RE_FETCH = /^(.+?)(?:→|->)\\s*(\\S+)(.*)$/;\nconst RE_FETCH_METHOD = /^(GET|POST|PUT|PATCH|DELETE)\\s+(.+)$/i;\nconst RE_STRIP_ITEM_BRACES = /^\\{item\\.?|\\}$/g;\n// Detect expressions referencing DOM event parameters — these can't be resolved\n// through scope getters and must fall through to the new Function handler path.\nconst RE_EVENT_REF = /\\bevent\\s*[.([]|\\$event\\b/;\nconst RE_REFETCH_CALL = /^\\$refetch\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)$/;\n\ninterface TransitionSpec {\n enter: string[];\n enterFrom: string[];\n enterTo: string[];\n leave: string[];\n leaveFrom: string[];\n leaveTo: string[];\n enterDurationMs?: number;\n leaveDurationMs?: number;\n}\n\ninterface ElementTransitionState {\n token: number;\n cancel: (() => void) | null;\n}\n\nconst TRANSITION_STATE_SYM = Symbol.for('forma-transition-state');\n\n// ── Expression factory cache ──\n// Maps expression string -> factory function that takes a scope and returns a getter.\n// This avoids re-parsing the same expression pattern across different scopes.\ntype ExpressionFactory = (scope: Scope) => (() => unknown) | null;\nconst EXPRESSION_CACHE_MAX = 2048;\nconst expressionCache = new Map<string, ExpressionFactory>();\nfunction cacheExpression(key: string, factory: ExpressionFactory): void {\n if (expressionCache.size >= EXPRESSION_CACHE_MAX) {\n // Evict oldest entry (first inserted)\n const first = expressionCache.keys().next().value;\n if (first !== undefined) expressionCache.delete(first);\n }\n expressionCache.set(key, factory);\n}\nlet scopeExpressionCache = new WeakMap<Scope, Map<string, () => unknown>>();\n\ninterface HandlerBuildResult {\n handler: (e: Event) => void;\n supported: boolean;\n}\n\nlet scopeHandlerCache = new WeakMap<Scope, Map<string, HandlerBuildResult>>();\n\n// ── Compiled template cache ──\n// Pre-splits template text into static/dynamic segments for fast re-evaluation.\ninterface CompiledTemplate {\n statics: string[];\n dynamics: string[]; // expression strings between {item.xxx}\n hasItemRef: boolean;\n}\n\nconst compiledTemplateCache = new Map<string, CompiledTemplate>();\nconst COMPILED_TEMPLATE_CACHE_MAX = 2048;\nfunction cacheCompiledTemplate(key: string, template: CompiledTemplate): void {\n if (compiledTemplateCache.size >= COMPILED_TEMPLATE_CACHE_MAX) {\n // Evict oldest entry (first inserted)\n const first = compiledTemplateCache.keys().next().value;\n if (first !== undefined) compiledTemplateCache.delete(first);\n }\n compiledTemplateCache.set(key, template);\n}\nconst UNSAFE_METHOD_NAMES = new Set([\n 'constructor', '__proto__', 'prototype',\n '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__',\n 'eval', 'Function',\n]);\n\n/**\n * Pre-compiled regexes for each blocked method name — avoids re-creating\n * RegExp objects on every call.\n */\nconst BLOCKED_METHOD_REGEXES: Array<{ name: string; dotRe: RegExp; bracketRe: RegExp }> = (() => {\n const result: Array<{ name: string; dotRe: RegExp; bracketRe: RegExp }> = [];\n for (const name of UNSAFE_METHOD_NAMES) {\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n result.push({\n name,\n // Match as property access (.name) or bare identifier at start\n dotRe: new RegExp(`(?:^|\\\\.)${escaped}(?:\\\\s*\\\\(|\\\\s*$|[^\\\\w$])`, 'm'),\n // Match bracket access with single quotes, double quotes, or backticks\n bracketRe: new RegExp(`\\\\[\\\\s*(?:'${escaped}'|\"${escaped}\"|` + '`' + escaped + '`' + `)\\\\s*\\\\]`),\n });\n }\n return result;\n})();\n\n/**\n * Scan an expression string for any UNSAFE_METHOD_NAMES usage.\n * Uses word-boundary matching to avoid false positives on substrings\n * (e.g. \"constructorValue\" should not match \"constructor\").\n *\n * Before scanning:\n * 1. Strips JS block comments and line comments\n * 2. Normalizes whitespace around dots (e.g. \"x . constructor\" → \"x.constructor\")\n * 3. Checks bracket access with static string literals and backtick templates\n * 4. Detects string concatenation inside brackets that could produce a blocked name\n *\n * Returns the matched blocked name, or null if clean.\n */\nfunction findBlockedMethod(expr: string): string | null {\n // Strip block comments (/* ... */)\n let cleaned = expr.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n // Strip line comments (// ... to end of line)\n cleaned = cleaned.replace(/\\/\\/[^\\n]*/g, '');\n // Normalize whitespace around dots: \"x . constructor\" → \"x.constructor\"\n cleaned = cleaned.replace(/\\s*\\.\\s*/g, '.');\n\n for (const { name, dotRe, bracketRe } of BLOCKED_METHOD_REGEXES) {\n if (dotRe.test(cleaned)) return name;\n if (bracketRe.test(cleaned)) return name;\n }\n\n // Layer 2: detect string concatenation inside brackets that could produce\n // a blocked name. Extract all bracket contents and check if concatenated\n // string fragments could form a blocked name.\n // e.g. x['constr' + 'uctor'] → extract 'constr' and 'uctor' → 'constructor'\n if (cleaned.includes('[')) {\n const bracketContents = extractBracketContents(cleaned);\n for (const content of bracketContents) {\n // Only check contents with concatenation operators\n if (!content.includes('+')) continue;\n // Extract all string literal fragments and join them\n const fragments = content.match(/['\"`]([^'\"`]*?)['\"`]/g);\n if (!fragments) continue;\n const joined = fragments.map(f => f.slice(1, -1)).join('');\n if (UNSAFE_METHOD_NAMES.has(joined)) return joined;\n }\n }\n\n return null;\n}\n\n/** Extract the contents of all bracket access expressions (between [ and ]). */\nfunction extractBracketContents(expr: string): string[] {\n const results: string[] = [];\n let depth = 0;\n let start = -1;\n for (let i = 0; i < expr.length; i++) {\n if (expr[i] === '[') {\n if (depth === 0) start = i + 1;\n depth++;\n } else if (expr[i] === ']') {\n depth--;\n if (depth === 0 && start >= 0) {\n results.push(expr.slice(start, i));\n start = -1;\n }\n }\n }\n return results;\n}\n\nconst TEXT_BINDING_SYM = Symbol.for('forma-text-binding-cache');\n\ninterface TextBindingCache {\n initialized: boolean;\n last: string;\n node: Text | null;\n}\n\nfunction toTextValue(value: unknown): string {\n if (value == null) return '';\n if (typeof value === 'string') return value;\n if (typeof value === 'symbol') return value.toString();\n return String(value);\n}\n\nfunction setElementTextFast(el: Element, next: string): void {\n let cache = (el as any)[TEXT_BINDING_SYM] as TextBindingCache | undefined;\n if (!cache) {\n cache = { initialized: false, last: '', node: null };\n (el as any)[TEXT_BINDING_SYM] = cache;\n }\n\n if (cache.initialized && cache.last === next) return;\n\n // Reuse direct text-node writes when this element is a single text child.\n let node = cache.node;\n if (!node || node.parentNode !== el || el.childNodes.length !== 1 || el.firstChild !== node) {\n if (el.childNodes.length === 1 && el.firstChild?.nodeType === Node.TEXT_NODE) {\n node = el.firstChild as Text;\n cache.node = node;\n } else {\n el.textContent = next;\n const first = el.firstChild;\n cache.node = (first && first.nodeType === Node.TEXT_NODE && el.childNodes.length === 1)\n ? (first as Text)\n : null;\n cache.last = next;\n cache.initialized = true;\n return;\n }\n }\n\n node.data = next;\n cache.last = next;\n cache.initialized = true;\n}\n\nfunction splitCallArgs(raw: string): string[] {\n const out: string[] = [];\n if (raw.trim() === '') return out;\n\n let depth = 0;\n let inSingle = false;\n let inDouble = false;\n let escaped = false;\n let start = 0;\n\n for (let i = 0; i < raw.length; i++) {\n const ch = raw[i]!;\n\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (ch === '\\\\') {\n escaped = true;\n continue;\n }\n\n if (inSingle) {\n if (ch === '\\'') inSingle = false;\n continue;\n }\n if (inDouble) {\n if (ch === '\"') inDouble = false;\n continue;\n }\n\n if (ch === '\\'') {\n inSingle = true;\n continue;\n }\n if (ch === '\"') {\n inDouble = true;\n continue;\n }\n\n if (ch === '(') {\n depth++;\n continue;\n }\n if (ch === ')') {\n if (depth > 0) depth--;\n continue;\n }\n\n if (ch === ',' && depth === 0) {\n out.push(raw.slice(start, i).trim());\n start = i + 1;\n }\n }\n\n out.push(raw.slice(start).trim());\n return out.filter(Boolean);\n}\n\nfunction readBalancedSegment(\n input: string,\n start: number,\n open: string,\n close: string,\n): { inner: string; end: number } | null {\n if (input[start] !== open) return null;\n\n let depth = 0;\n let inSingle = false;\n let inDouble = false;\n let inTemplate = false;\n let escaped = false;\n\n for (let i = start; i < input.length; i++) {\n const ch = input[i]!;\n\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (ch === '\\\\' && (inSingle || inDouble || inTemplate)) {\n escaped = true;\n continue;\n }\n\n if (inSingle) {\n if (ch === '\\'') inSingle = false;\n continue;\n }\n if (inDouble) {\n if (ch === '\"') inDouble = false;\n continue;\n }\n if (inTemplate) {\n if (ch === '`') inTemplate = false;\n continue;\n }\n\n if (ch === '\\'') {\n inSingle = true;\n continue;\n }\n if (ch === '\"') {\n inDouble = true;\n continue;\n }\n if (ch === '`') {\n inTemplate = true;\n continue;\n }\n\n if (ch === open) {\n depth++;\n continue;\n }\n if (ch === close) {\n depth--;\n if (depth === 0) {\n return {\n inner: input.slice(start + 1, i),\n end: i,\n };\n }\n }\n }\n\n return null;\n}\n\nfunction splitTopLevelStatements(raw: string): string[] {\n const input = raw.trim();\n if (!input) return [];\n\n const out: string[] = [];\n let depthParen = 0;\n let depthBrace = 0;\n let depthBracket = 0;\n let inSingle = false;\n let inDouble = false;\n let inTemplate = false;\n let escaped = false;\n let start = 0;\n\n for (let i = 0; i < input.length; i++) {\n const ch = input[i]!;\n\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (ch === '\\\\' && (inSingle || inDouble || inTemplate)) {\n escaped = true;\n continue;\n }\n\n if (inSingle) {\n if (ch === '\\'') inSingle = false;\n continue;\n }\n if (inDouble) {\n if (ch === '\"') inDouble = false;\n continue;\n }\n if (inTemplate) {\n if (ch === '`') inTemplate = false;\n continue;\n }\n\n if (ch === '\\'') {\n inSingle = true;\n continue;\n }\n if (ch === '\"') {\n inDouble = true;\n continue;\n }\n if (ch === '`') {\n inTemplate = true;\n continue;\n }\n\n if (ch === '(') depthParen++;\n else if (ch === ')' && depthParen > 0) depthParen--;\n else if (ch === '{') depthBrace++;\n else if (ch === '}' && depthBrace > 0) depthBrace--;\n else if (ch === '[') depthBracket++;\n else if (ch === ']' && depthBracket > 0) depthBracket--;\n\n if (ch === ';' && depthParen === 0 && depthBrace === 0 && depthBracket === 0) {\n const stmt = input.slice(start, i).trim();\n if (stmt) out.push(stmt);\n start = i + 1;\n }\n }\n\n const tail = input.slice(start).trim();\n if (tail) out.push(tail);\n return out;\n}\n\nfunction consumeStatement(raw: string): { body: string; rest: string } | null {\n const input = raw.trim();\n if (!input) return null;\n\n if (input.startsWith('{')) {\n const block = readBalancedSegment(input, 0, '{', '}');\n if (!block) return null;\n const body = block.inner.trim();\n let rest = input.slice(block.end + 1).trim();\n if (rest.startsWith(';')) rest = rest.slice(1).trim();\n return { body, rest };\n }\n\n let depthParen = 0;\n let depthBrace = 0;\n let depthBracket = 0;\n let inSingle = false;\n let inDouble = false;\n let inTemplate = false;\n let escaped = false;\n\n for (let i = 0; i < input.length; i++) {\n const ch = input[i]!;\n\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (ch === '\\\\' && (inSingle || inDouble || inTemplate)) {\n escaped = true;\n continue;\n }\n\n if (inSingle) {\n if (ch === '\\'') inSingle = false;\n continue;\n }\n if (inDouble) {\n if (ch === '\"') inDouble = false;\n continue;\n }\n if (inTemplate) {\n if (ch === '`') inTemplate = false;\n continue;\n }\n\n if (ch === '\\'') {\n inSingle = true;\n continue;\n }\n if (ch === '\"') {\n inDouble = true;\n continue;\n }\n if (ch === '`') {\n inTemplate = true;\n continue;\n }\n\n if (ch === '(') depthParen++;\n else if (ch === ')' && depthParen > 0) depthParen--;\n else if (ch === '{') depthBrace++;\n else if (ch === '}' && depthBrace > 0) depthBrace--;\n else if (ch === '[') depthBracket++;\n else if (ch === ']' && depthBracket > 0) depthBracket--;\n\n if (ch === ';' && depthParen === 0 && depthBrace === 0 && depthBracket === 0) {\n return {\n body: input.slice(0, i).trim(),\n rest: input.slice(i + 1).trim(),\n };\n }\n }\n\n return {\n body: input,\n rest: '',\n };\n}\n\nfunction parseIfHandler(expr: string, scope: Scope): ((e: Event) => void) | null {\n const input = expr.trim();\n if (!RE_IF_PREFIX.test(input)) return null;\n\n // If the expression references DOM event parameters (`event`, `$event`),\n // bail out — these aren't in scope getters and must use new Function.\n if (RE_EVENT_REF.test(input)) return null;\n\n let idx = 2;\n while (idx < input.length && /\\s/.test(input[idx]!)) idx++;\n if (input[idx] !== '(') return null;\n\n const condSegment = readBalancedSegment(input, idx, '(', ')');\n if (!condSegment) return null;\n\n const condExpr = parseExpression(condSegment.inner.trim(), scope);\n if (!condExpr) return null;\n\n let rest = input.slice(condSegment.end + 1).trim();\n const thenStmt = consumeStatement(rest);\n if (!thenStmt || !thenStmt.body) return null;\n\n const thenHandler = parseHandler(thenStmt.body, scope);\n if (!thenHandler) return null;\n\n rest = thenStmt.rest.trim();\n let elseHandler: ((e: Event) => void) | null = null;\n if (rest.startsWith('else')) {\n rest = rest.slice('else'.length).trim();\n const elseStmt = consumeStatement(rest);\n if (!elseStmt || !elseStmt.body) return null;\n elseHandler = parseHandler(elseStmt.body, scope);\n if (!elseHandler) return null;\n rest = elseStmt.rest.trim();\n }\n\n if (rest.length > 0) return null;\n\n return (e: Event) => {\n batch(() => {\n if (condExpr()) thenHandler(e);\n else elseHandler?.(e);\n });\n };\n}\n\nfunction unwrapOuterParens(raw: string): string {\n let expr = raw.trim();\n while (expr.startsWith('(')) {\n const segment = readBalancedSegment(expr, 0, '(', ')');\n if (!segment || segment.end !== expr.length - 1) break;\n const inner = segment.inner.trim();\n if (!inner) break;\n expr = inner;\n }\n return expr;\n}\n\nfunction compileTemplate(text: string): CompiledTemplate {\n const cached = compiledTemplateCache.get(text);\n if (cached) return cached;\n\n const statics: string[] = [];\n const dynamics: string[] = [];\n let lastIndex = 0;\n // Use a fresh regex each time since it has the 'g' flag\n const re = /\\{item\\.?(\\w*)\\}/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n statics.push(text.slice(lastIndex, m.index));\n dynamics.push(m[1]!); // the key after \"item.\" (empty string means whole item)\n lastIndex = re.lastIndex;\n }\n statics.push(text.slice(lastIndex));\n\n const result: CompiledTemplate = {\n statics,\n dynamics,\n hasItemRef: dynamics.length > 0,\n };\n cacheCompiledTemplate(text, result);\n return result;\n}\n\n// ── Template text caching for data-list ──\n\n/** Maps text nodes to their compiled template (pre-split static/dynamic segments). */\nconst templateTexts = new WeakMap<Node, CompiledTemplate>();\n\n/**\n * Resolve template placeholders in a text string using pre-compiled template.\n * Concatenates static segments with evaluated dynamic segments.\n */\nfunction resolveTemplate(text: string, item: unknown): string {\n const compiled = compileTemplate(text);\n return evaluateCompiledTemplate(compiled, item);\n}\n\n/**\n * Evaluate a pre-compiled template against an item.\n * Only evaluates dynamic parts and concatenates with static segments.\n */\nfunction evaluateCompiledTemplate(compiled: CompiledTemplate, item: unknown): string {\n if (!compiled.hasItemRef) return compiled.statics[0]!;\n let result = compiled.statics[0]!;\n for (let i = 0; i < compiled.dynamics.length; i++) {\n const key = compiled.dynamics[i]!;\n if (!key) {\n result += typeof item === 'object' ? JSON.stringify(item) : String(item ?? '');\n } else {\n result += String((item as Record<string, unknown>)?.[key] ?? '');\n }\n result += compiled.statics[i + 1] ?? '';\n }\n return result;\n}\n\n/**\n * Clone a template element and apply item data to all text node placeholders.\n * Stores the original template text in a WeakMap so updates can re-apply without re-cloning.\n */\nfunction cloneWithTemplateData(template: Element, item: unknown): Element {\n const clone = template.cloneNode(true) as Element;\n const walker = document.createTreeWalker(clone, NodeFilter.SHOW_TEXT);\n while (walker.nextNode()) {\n const node = walker.currentNode;\n const text = node.textContent ?? '';\n if (text.includes('{item')) {\n const compiled = compileTemplate(text);\n templateTexts.set(node, compiled); // Store compiled template\n node.textContent = evaluateCompiledTemplate(compiled, item);\n }\n }\n // Also process attributes (e.g. data-key, href, src, etc.)\n cloneAttributeTemplates(clone, item);\n return clone;\n}\n\n/**\n * Update an existing cloned element's text nodes with new item data.\n * Uses the cached original template patterns from the WeakMap.\n */\nfunction updateTemplateData(el: Element, item: unknown): void {\n const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);\n while (walker.nextNode()) {\n const node = walker.currentNode;\n const compiled = templateTexts.get(node);\n if (compiled) {\n node.textContent = evaluateCompiledTemplate(compiled, item);\n }\n }\n}\n\n/** WeakMap for caching compiled attribute templates */\nconst templateAttrs = new WeakMap<Element, Array<{ attr: string; compiled: CompiledTemplate }>>();\n\n/**\n * Process attribute templates on a cloned element and its descendants.\n * Pre-compiles patterns and resolves them with item data.\n */\n/** Directive attribute names/prefixes that bindElement processes — these must NOT be\n * template-interpolated by cloneAttributeTemplates because their values will be\n * evaluated by the reactive binding system using the child scope. */\nconst DIRECTIVE_ATTR_PREFIXES = [\n 'data-list', 'data-show', 'data-text', 'data-if', 'data-model',\n 'data-on:', 'data-class:', 'data-bind:', 'data-computed', 'data-persist', 'data-fetch',\n 'data-transition', 'data-transition:',\n];\nfunction isDirectiveAttr(name: string): boolean {\n for (const prefix of DIRECTIVE_ATTR_PREFIXES) {\n if (name === prefix || name.startsWith(prefix)) return true;\n }\n return false;\n}\n\nfunction splitClassTokens(raw: string | null): string[] {\n if (!raw) return [];\n return raw\n .trim()\n .split(/\\s+/)\n .map((t) => t.trim())\n .filter(Boolean);\n}\n\nfunction parseDurationTokenMs(token: string): number | null {\n const t = token.trim().toLowerCase();\n if (t.endsWith('ms')) {\n const n = Number(t.slice(0, -2));\n return Number.isFinite(n) && n >= 0 ? n : null;\n }\n if (t.endsWith('s')) {\n const n = Number(t.slice(0, -1));\n return Number.isFinite(n) && n >= 0 ? n * 1000 : null;\n }\n return null;\n}\n\nfunction parseClassTokensAndDuration(raw: string | null): { classes: string[]; durationMs?: number } {\n const classes: string[] = [];\n let durationMs: number | undefined;\n for (const token of splitClassTokens(raw)) {\n const parsed = parseDurationTokenMs(token);\n if (parsed != null) {\n durationMs = parsed;\n } else {\n classes.push(token);\n }\n }\n return { classes, durationMs };\n}\n\nfunction uniqueTokens(tokens: string[]): string[] {\n return Array.from(new Set(tokens.filter(Boolean)));\n}\n\nfunction parseCssTimeListMs(raw: string): number[] {\n if (!raw) return [];\n return raw\n .split(',')\n .map((part) => parseDurationTokenMs(part.trim()))\n .filter((ms): ms is number => ms != null);\n}\n\nfunction maxCombinedTimingsMs(durations: number[], delays: number[]): number {\n if (durations.length === 0 && delays.length === 0) return 0;\n if (durations.length === 0) return Math.max(...delays, 0);\n if (delays.length === 0) return Math.max(...durations, 0);\n\n const len = Math.max(durations.length, delays.length);\n let max = 0;\n for (let i = 0; i < len; i++) {\n const d = durations[i % durations.length] ?? 0;\n const delay = delays[i % delays.length] ?? 0;\n if (d + delay > max) max = d + delay;\n }\n return max;\n}\n\nfunction resolveTransitionDurationMs(el: HTMLElement, explicitMs?: number): number {\n if (typeof explicitMs === 'number') return explicitMs;\n const cs = window.getComputedStyle(el);\n const trans = maxCombinedTimingsMs(\n parseCssTimeListMs(cs.transitionDuration),\n parseCssTimeListMs(cs.transitionDelay),\n );\n const anim = maxCombinedTimingsMs(\n parseCssTimeListMs(cs.animationDuration),\n parseCssTimeListMs(cs.animationDelay),\n );\n return Math.max(trans, anim);\n}\n\nfunction getTransitionState(el: HTMLElement): ElementTransitionState {\n const existing = (el as any)[TRANSITION_STATE_SYM] as ElementTransitionState | undefined;\n if (existing) return existing;\n const created: ElementTransitionState = { token: 0, cancel: null };\n (el as any)[TRANSITION_STATE_SYM] = created;\n return created;\n}\n\nfunction clearTransitionState(el: HTMLElement): void {\n const state = (el as any)[TRANSITION_STATE_SYM] as ElementTransitionState | undefined;\n if (state?.cancel) {\n state.cancel();\n }\n delete (el as any)[TRANSITION_STATE_SYM];\n}\n\nfunction parseTransitionSpec(el: Element): TransitionSpec | null {\n const hasTransitionAttr = el.hasAttribute('data-transition')\n || Array.from(el.attributes).some((a) => a.name.startsWith('data-transition:'));\n if (!hasTransitionAttr) return null;\n\n const base = parseClassTokensAndDuration(el.getAttribute('data-transition')).classes;\n\n const enter = parseClassTokensAndDuration(el.getAttribute('data-transition:enter'));\n const leave = parseClassTokensAndDuration(el.getAttribute('data-transition:leave'));\n const enterFrom = splitClassTokens(\n el.getAttribute('data-transition:enter-from')\n ?? el.getAttribute('data-transition:enter-start'),\n );\n const enterTo = splitClassTokens(\n el.getAttribute('data-transition:enter-to')\n ?? el.getAttribute('data-transition:enter-end'),\n );\n const leaveFrom = splitClassTokens(\n el.getAttribute('data-transition:leave-from')\n ?? el.getAttribute('data-transition:leave-start'),\n );\n const leaveTo = splitClassTokens(\n el.getAttribute('data-transition:leave-to')\n ?? el.getAttribute('data-transition:leave-end'),\n );\n\n const durationBoth = parseDurationTokenMs(el.getAttribute('data-transition:duration') ?? '');\n const enterDuration = parseDurationTokenMs(el.getAttribute('data-transition:duration-enter') ?? '')\n ?? enter.durationMs\n ?? durationBoth\n ?? undefined;\n const leaveDuration = parseDurationTokenMs(el.getAttribute('data-transition:duration-leave') ?? '')\n ?? leave.durationMs\n ?? durationBoth\n ?? undefined;\n\n return {\n enter: uniqueTokens([...base, ...enter.classes]),\n enterFrom: uniqueTokens(enterFrom),\n enterTo: uniqueTokens(enterTo),\n leave: uniqueTokens([...base, ...leave.classes]),\n leaveFrom: uniqueTokens(leaveFrom),\n leaveTo: uniqueTokens(leaveTo),\n enterDurationMs: enterDuration,\n leaveDurationMs: leaveDuration,\n };\n}\n\nfunction removeClasses(el: Element, classes: string[]): void {\n for (const cls of classes) {\n el.classList.remove(cls);\n }\n}\n\nfunction addClasses(el: Element, classes: string[]): void {\n for (const cls of classes) {\n el.classList.add(cls);\n }\n}\n\nfunction runTransitionPhase(\n el: HTMLElement,\n phaseClasses: { base: string[]; from: string[]; to: string[]; durationMs?: number },\n onDone: () => void,\n): () => void {\n const cleanupClasses = uniqueTokens([\n ...phaseClasses.base,\n ...phaseClasses.from,\n ...phaseClasses.to,\n ]);\n\n let done = false;\n let timeoutId: number | null = null;\n let raf1: number | null = null;\n let raf2: number | null = null;\n\n const finish = () => {\n if (done) return;\n done = true;\n if (timeoutId != null) window.clearTimeout(timeoutId);\n if (raf1 != null) cancelAnimationFrame(raf1);\n if (raf2 != null) cancelAnimationFrame(raf2);\n removeClasses(el, cleanupClasses);\n onDone();\n };\n\n addClasses(el, phaseClasses.base);\n addClasses(el, phaseClasses.from);\n removeClasses(el, phaseClasses.to);\n\n raf1 = requestAnimationFrame(() => {\n raf2 = requestAnimationFrame(() => {\n if (done) return;\n removeClasses(el, phaseClasses.from);\n addClasses(el, phaseClasses.to);\n\n const ms = resolveTransitionDurationMs(el, phaseClasses.durationMs);\n if (ms <= 0) {\n finish();\n return;\n }\n timeoutId = window.setTimeout(finish, ms + 25);\n });\n });\n\n return finish;\n}\n\n/**\n * Insert an element into the DOM and optionally run an enter transition.\n * The element is functional immediately — the animation is purely visual.\n */\nfunction transitionInsert(\n el: HTMLElement,\n parent: Node,\n ref: Node | null,\n spec: TransitionSpec | null,\n): void {\n parent.insertBefore(el, ref);\n if (!spec) return;\n\n const state = getTransitionState(el);\n state.token += 1;\n const token = state.token;\n if (state.cancel) state.cancel();\n\n state.cancel = runTransitionPhase(\n el,\n {\n base: spec.enter,\n from: spec.enterFrom,\n to: spec.enterTo,\n durationMs: spec.enterDurationMs,\n },\n () => {\n const current = getTransitionState(el);\n if (current.token === token) current.cancel = null;\n },\n );\n}\n\n/**\n * Run a leave transition on an element, then call onDone when complete.\n * Sets data-forma-leaving immediately so the element is excluded from diffs.\n * If no transition spec, calls onDone synchronously.\n */\nfunction transitionRemove(\n el: HTMLElement,\n spec: TransitionSpec | null,\n onDone: () => void,\n): void {\n // Guard: if already leaving, don't start another leave\n if (el.hasAttribute('data-forma-leaving')) {\n onDone();\n return;\n }\n\n if (!spec) {\n onDone();\n return;\n }\n\n el.setAttribute('data-forma-leaving', '');\n\n const state = getTransitionState(el);\n state.token += 1;\n const token = state.token;\n if (state.cancel) state.cancel();\n\n state.cancel = runTransitionPhase(\n el,\n {\n base: spec.leave,\n from: spec.leaveFrom,\n to: spec.leaveTo,\n durationMs: spec.leaveDurationMs,\n },\n () => {\n const current = getTransitionState(el);\n if (current.token === token) current.cancel = null;\n el.removeAttribute('data-forma-leaving');\n onDone();\n },\n );\n}\n\nfunction applyShowVisibility(\n el: HTMLElement,\n visible: boolean,\n transition: TransitionSpec | null,\n initial: boolean,\n): void {\n if (!transition || initial) {\n el.style.display = visible ? '' : 'none';\n if (transition) {\n removeClasses(el, uniqueTokens([\n ...transition.enter, ...transition.enterFrom, ...transition.enterTo,\n ...transition.leave, ...transition.leaveFrom, ...transition.leaveTo,\n ]));\n }\n return;\n }\n\n const state = getTransitionState(el);\n state.token += 1;\n const token = state.token;\n if (state.cancel) state.cancel();\n state.cancel = null;\n\n if (visible) {\n el.style.display = '';\n state.cancel = runTransitionPhase(\n el,\n {\n base: transition.enter,\n from: transition.enterFrom,\n to: transition.enterTo,\n durationMs: transition.enterDurationMs,\n },\n () => {\n const current = getTransitionState(el);\n if (current.token === token) current.cancel = null;\n },\n );\n return;\n }\n\n state.cancel = runTransitionPhase(\n el,\n {\n base: transition.leave,\n from: transition.leaveFrom,\n to: transition.leaveTo,\n durationMs: transition.leaveDurationMs,\n },\n () => {\n const current = getTransitionState(el);\n if (current.token !== token) return;\n el.style.display = 'none';\n current.cancel = null;\n },\n );\n}\n\nfunction cloneAttributeTemplates(el: Element, item: unknown): void {\n const all = [el, ...Array.from(el.querySelectorAll('*'))];\n for (const node of all) {\n const entries: Array<{ attr: string; compiled: CompiledTemplate }> = [];\n for (const attr of Array.from(node.attributes)) {\n // Skip directive attributes — they'll be evaluated by bindElement with the child scope\n if (isDirectiveAttr(attr.name)) continue;\n if (attr.value.includes('{item')) {\n const compiled = compileTemplate(attr.value);\n entries.push({ attr: attr.name, compiled });\n node.setAttribute(attr.name, evaluateCompiledTemplate(compiled, item));\n }\n }\n if (entries.length > 0) {\n templateAttrs.set(node, entries);\n }\n }\n}\n\n// ── Chained access / optional chaining parser ──\n\n/**\n * Represents a single step in a property/method chain.\n * - type 'prop': property access (`.name` or `?.name`)\n * - type 'call': method call (`.method(args)` or `?.method(args)`)\n */\ninterface ChainStep {\n type: 'prop' | 'call';\n name: string;\n optional: boolean; // true for `?.`\n argFns?: Array<() => unknown>; // only for 'call' type\n}\n\n/**\n * Parse an expression that starts with an identifier and is followed by\n * zero or more chain steps: `.prop`, `?.prop`, `.method(args)`, `?.method(args)`.\n * Returns null if the expression doesn't match this pattern.\n *\n * Handles: \"user.name\", \"user?.name\", \"str.trim().toUpperCase()\",\n * \"obj?.method()\", \"items.filter(x).map(y)\", \"a.b.c.d\" (any depth).\n */\nfunction parseChainedAccess(expr: string, scope: Scope): (() => unknown) | null {\n // Must start with an identifier (or Math)\n let pos = 0;\n const identMatch = expr.match(/^[a-zA-Z_$]\\w*/);\n if (!identMatch) return null;\n\n const rootName = identMatch[0]!;\n pos = rootName.length;\n\n // Must have at least one chain step after the identifier\n if (pos >= expr.length) return null;\n // Next char must be '.' or '?' (for '?.')\n if (expr[pos] !== '.' && !(expr[pos] === '?' && expr[pos + 1] === '.')) return null;\n\n const steps: ChainStep[] = [];\n\n while (pos < expr.length) {\n let optional = false;\n\n // Check for `?.` (optional chaining) or `.` (regular access)\n if (expr[pos] === '?' && expr[pos + 1] === '.') {\n optional = true;\n pos += 2;\n } else if (expr[pos] === '.') {\n pos += 1;\n } else {\n // Not a chain continuation — unexpected character\n return null;\n }\n\n // Parse property/method name\n const nameMatch = expr.slice(pos).match(/^\\w+/);\n if (!nameMatch) return null;\n const name = nameMatch[0]!;\n pos += name.length;\n\n if (UNSAFE_METHOD_NAMES.has(name)) return () => undefined;\n\n // Check if this is a method call: followed by `(`\n if (pos < expr.length && expr[pos] === '(') {\n const balanced = readBalancedSegment(expr, pos, '(', ')');\n if (!balanced) return null;\n\n const argsRaw = balanced.inner.trim();\n const argFns: Array<() => unknown> = [];\n for (const arg of splitCallArgs(argsRaw)) {\n const parsed = parseExpression(arg, scope);\n if (!parsed) return null;\n argFns.push(parsed);\n }\n\n steps.push({ type: 'call', name, optional, argFns });\n pos = balanced.end + 1;\n } else {\n steps.push({ type: 'prop', name, optional });\n }\n }\n\n // If we didn't consume the entire expression, this isn't a simple chain\n if (pos !== expr.length) return null;\n\n // If there are no steps, fall back (just an identifier)\n if (steps.length === 0) return null;\n\n // Build the root expression getter\n const rootExpr = rootName === 'Math'\n ? (() => Math)\n : (() => scope.getters[rootName]?.());\n\n return () => {\n let val: any = rootExpr();\n for (const step of steps) {\n if (val == null) {\n if (step.optional) return undefined;\n // Non-optional access on null/undefined — use ?. semantics\n // (existing behavior used ?. for dot access)\n return undefined;\n }\n if (step.type === 'prop') {\n val = val[step.name];\n } else {\n const method = val[step.name];\n if (typeof method !== 'function') return undefined;\n const args = step.argFns!.map(fn => fn());\n val = method.apply(val, args);\n }\n }\n return val;\n };\n}\n\n// ── CSP-safe expression parser ──\n\n/**\n * Parse a simple expression into a closure that evaluates against the scope.\n * Handles common patterns without requiring `new Function()` or `eval`.\n * Returns null if the expression is too complex for the CSP-safe parser.\n */\nfunction parseExpression(expr: string, scope: Scope): (() => unknown) | null {\n // Check expression factory cache first\n const cachedFactory = expressionCache.get(expr);\n if (cachedFactory) return cachedFactory(scope);\n\n const result = parseExpressionUncached(expr, scope);\n\n // Cache factory functions for common simple patterns that can be re-bound to different scopes\n if (result !== null) {\n // Cache factories for simple patterns (identifier, dot access, etc.)\n // Complex patterns with sub-expressions are scope-dependent and harder to cache as factories,\n // but we can still cache the structural match result for them.\n // Keyword literals MUST be checked before RE_IDENTIFIER — \"true\", \"false\",\n // \"null\", \"undefined\" all match /^[a-zA-Z_$]\\w*$/ and would be incorrectly\n // cached as scope variable lookups (returning undefined).\n if (expr === 'true' || expr === 'false' || expr === 'null' || expr === 'undefined') {\n const val = expr === 'true' ? true : expr === 'false' ? false : expr === 'null' ? null : undefined;\n cacheExpression(expr, () => () => val);\n } else if (RE_IDENTIFIER.test(expr)) {\n cacheExpression(expr, (s) => () => s.getters[expr]?.());\n } else if (RE_STRING_SINGLE.test(expr) || RE_STRING_DOUBLE.test(expr)) {\n const val = expr.slice(1, -1);\n cacheExpression(expr, () => () => val);\n } else if (RE_NUMBER.test(expr)) {\n const val = Number(expr);\n cacheExpression(expr, () => () => val);\n } else {\n const dotMatch = expr.match(RE_DOT_ACCESS);\n if (dotMatch) {\n const p1 = dotMatch[1]!, p2 = dotMatch[2]!;\n cacheExpression(expr, (s) => () => {\n const obj = s.getters[p1]?.();\n return (obj as any)?.[p2];\n });\n }\n }\n }\n\n return result;\n}\n\n/**\n * Core expression parser — called on cache miss.\n * Uses pre-compiled module-level regexes for all pattern matching.\n */\nfunction parseExpressionUncached(expr: string, scope: Scope): (() => unknown) | null {\n expr = expr.trim();\n\n // Parenthesized group: \"(a + b)\", \"((count))\"\n const unwrapped = unwrapOuterParens(expr);\n if (unwrapped !== expr) {\n return parseExpression(unwrapped, scope);\n }\n\n // Literals first (before identifier check, since \\w matches digits)\n\n // String literals\n if (RE_STRING_SINGLE.test(expr) || RE_STRING_DOUBLE.test(expr)) {\n const val = expr.slice(1, -1);\n return () => val;\n }\n\n // Number literals\n if (RE_NUMBER.test(expr)) {\n const val = Number(expr);\n return () => val;\n }\n\n // Boolean / null / undefined literals\n if (expr === 'true') return () => true;\n if (expr === 'false') return () => false;\n if (expr === 'null') return () => null;\n if (expr === 'undefined') return () => undefined;\n\n // Simple identifier: \"count\", \"name\" (must start with letter/underscore/$)\n if (RE_IDENTIFIER.test(expr)) {\n return () => scope.getters[expr]?.();\n }\n\n // Chained access / method calls / optional chaining:\n // \"user.name\", \"user?.name\", \"str.trim().toUpperCase()\", \"obj?.method()\", \"items.filter(x).map(y)\"\n // Also handles simple dot access, deep dot access, and single method calls.\n {\n const chainResult = parseChainedAccess(expr, scope);\n if (chainResult) return chainResult;\n }\n\n // Grouped method call: \"(expr).method(args)\" — base is a parenthesized expression\n const groupedCallMatch = expr.match(RE_GROUP_METHOD_CALL);\n if (groupedCallMatch) {\n const baseRaw = groupedCallMatch[1]!.trim();\n const methodName = groupedCallMatch[2]!;\n const argsRaw = groupedCallMatch[3]!.trim();\n\n if (UNSAFE_METHOD_NAMES.has(methodName)) return () => undefined;\n\n const baseExpr = parseExpression(baseRaw, scope);\n if (!baseExpr) return null;\n\n const argFns: Array<() => unknown> = [];\n for (const arg of splitCallArgs(argsRaw)) {\n const parsed = parseExpression(arg, scope);\n if (!parsed) return null;\n argFns.push(parsed);\n }\n\n return () => {\n const base = baseExpr() as any;\n const method = base?.[methodName];\n if (typeof method !== 'function') return undefined;\n const args = argFns.map(fn => fn());\n return method.apply(base, args);\n };\n }\n\n // Negation: \"!active\", \"!user.loggedIn\"\n if (expr.startsWith('!')) {\n const inner = parseExpression(expr.slice(1).trim(), scope);\n if (inner) return () => !inner();\n }\n\n // Bracket access: \"items[0]\", \"obj['key']\"\n const bracketMatch = expr.match(RE_BRACKET);\n if (bracketMatch) {\n const objExpr = parseExpression(bracketMatch[1]!, scope);\n let key: string | number;\n const rawKey = bracketMatch[2]!;\n if (RE_DIGIT_ONLY.test(rawKey)) {\n key = Number(rawKey);\n } else {\n key = rawKey.slice(1, -1);\n }\n if (objExpr) {\n return () => (objExpr() as any)?.[key];\n }\n }\n\n // Array literal: \"[1, 2, 3]\", \"[item.name, item.id]\", \"['a', 'b']\"\n if (expr.startsWith('[')) {\n const balanced = readBalancedSegment(expr, 0, '[', ']');\n if (balanced && balanced.end === expr.length - 1) {\n const inner = balanced.inner.trim();\n if (inner === '') {\n // Empty array: []\n return () => [];\n }\n const elements = splitCallArgs(inner);\n const elementFns: Array<() => unknown> = [];\n let allParsed = true;\n for (const el of elements) {\n const parsed = parseExpression(el.trim(), scope);\n if (!parsed) { allParsed = false; break; }\n elementFns.push(parsed);\n }\n if (allParsed) {\n return () => elementFns.map(fn => fn());\n }\n }\n }\n\n // Ternary: \"expr ? a : b\"\n const ternaryMatch = expr.match(RE_TERNARY);\n if (ternaryMatch) {\n const cond = parseExpression(ternaryMatch[1]!.trim(), scope);\n const then = parseExpression(ternaryMatch[2]!.trim(), scope);\n const els = parseExpression(ternaryMatch[3]!.trim(), scope);\n if (cond && then && els) {\n return () => cond() ? then() : els();\n }\n }\n\n // Nullish coalescing: \"value ?? 'default'\"\n const nullishMatch = expr.match(RE_NULLISH);\n if (nullishMatch) {\n const left = parseExpression(nullishMatch[1]!.trim(), scope);\n const right = parseExpression(nullishMatch[2]!.trim(), scope);\n if (left && right) {\n return () => left() ?? right();\n }\n }\n\n // Logical OR: \"a || b\" (lower precedence than AND — checked first)\n const orMatch = expr.match(RE_OR);\n if (orMatch) {\n const left = parseExpression(orMatch[1]!.trim(), scope);\n const right = parseExpression(orMatch[2]!.trim(), scope);\n if (left && right) {\n return () => left() || right();\n }\n }\n\n // Logical AND: \"a && b\" (higher precedence than OR — checked after)\n const andMatch = expr.match(RE_AND);\n if (andMatch) {\n const left = parseExpression(andMatch[1]!.trim(), scope);\n const right = parseExpression(andMatch[2]!.trim(), scope);\n if (left && right) {\n return () => left() && right();\n }\n }\n\n // Comparison operators: ===, !==, ==, !=, >=, <=, >, <\n const compMatch = expr.match(RE_COMPARISON);\n if (compMatch) {\n const left = parseExpression(compMatch[1]!.trim(), scope);\n const right = parseExpression(compMatch[3]!.trim(), scope);\n if (left && right) {\n const op = compMatch[2]!;\n return () => {\n const l = left(), r = right();\n switch (op) {\n case '===': return l === r;\n case '!==': return l !== r;\n case '==': return l == r;\n case '!=': return l != r;\n case '>': return (l as number) > (r as number);\n case '<': return (l as number) < (r as number);\n case '>=': return (l as number) >= (r as number);\n case '<=': return (l as number) <= (r as number);\n }\n };\n }\n }\n\n // Arithmetic: +, -, *, /, %\n // Addition/subtraction first (lower precedence — checked first), then * / %\n const addMatch = expr.match(RE_ADD);\n if (addMatch) {\n const left = parseExpression(addMatch[1]!.trim(), scope);\n const right = parseExpression(addMatch[3]!.trim(), scope);\n if (left && right) {\n const op = addMatch[2]!;\n return () => {\n const l = left(), r = right();\n if (op === '+') return (l as any) + (r as any);\n return (l as number) - (r as number);\n };\n }\n }\n\n // Multiplication / division / modulo (higher precedence — checked after addition)\n const mulMatch = expr.match(RE_MUL);\n if (mulMatch) {\n const left = parseExpression(mulMatch[1]!.trim(), scope);\n const right = parseExpression(mulMatch[3]!.trim(), scope);\n if (left && right) {\n const op = mulMatch[2]!;\n return () => {\n const l = left() as number, r = right() as number;\n switch (op) {\n case '*': return l * r;\n case '/': return l / r;\n case '%': return l % r;\n }\n };\n }\n }\n\n // Template literals: `Hello ${name}`\n const tmplMatch = expr.match(RE_TEMPLATE_LIT);\n if (tmplMatch) {\n const raw = tmplMatch[1]!;\n // Pre-split template literal into static/dynamic segments\n const staticParts: string[] = [];\n const dynamicFns: (() => unknown)[] = [];\n let lastIndex = 0;\n // Create a fresh regex since RE_TEMPLATE_INTERP has the 'g' flag\n const re = new RegExp(RE_TEMPLATE_INTERP.source, 'g');\n let m: RegExpExecArray | null;\n while ((m = re.exec(raw)) !== null) {\n staticParts.push(raw.slice(lastIndex, m.index));\n const inner = parseExpression(m[1]!.trim(), scope);\n if (!inner) return null; // Can't parse inner expression\n dynamicFns.push(inner);\n lastIndex = re.lastIndex;\n }\n staticParts.push(raw.slice(lastIndex));\n\n // Optimized evaluation: concatenate instead of map+join\n return () => {\n let result = staticParts[0]!;\n for (let i = 0; i < dynamicFns.length; i++) {\n result += String(dynamicFns[i]!() ?? '');\n result += staticParts[i + 1] ?? '';\n }\n return result;\n };\n }\n\n // Can't parse — return null for fallback\n return null;\n}\n\n// ── Expression evaluator ──\n\nfunction getScopeCache<T>(cache: WeakMap<Scope, Map<string, T>>, scope: Scope): Map<string, T> {\n let scoped = cache.get(scope);\n if (!scoped) {\n scoped = new Map<string, T>();\n cache.set(scope, scoped);\n }\n return scoped;\n}\n\n/** Build an actionable hint for expressions/handlers that failed CSP-safe parsing. */\nfunction cspExpressionHint(expr: string): string {\n if (expr.includes('...')) {\n return `Unsupported expression in CSP-safe mode: spread syntax detected. Use .concat() instead, or enable unsafe-eval via setUnsafeEval(true).`;\n }\n // Note: optional chaining (?.) is now supported by the CSP-safe parser.\n if (expr.includes('=>')) {\n return `Unsupported expression in CSP-safe mode: arrow function detected. Extract logic to a data-computed attribute, or enable unsafe-eval via setUnsafeEval(true).`;\n }\n return `Unsupported expression in CSP-safe mode. Simplify the expression or enable unsafe-eval via setUnsafeEval(true).`;\n}\n\nfunction buildEvaluator(expr: string, scope: Scope): () => unknown {\n const cleaned = expr.replace(RE_STRIP_BRACES, '').trim();\n const cache = getScopeCache(scopeExpressionCache, scope);\n const cached = cache.get(cleaned);\n if (cached) return cached;\n\n // Try CSP-safe parsing first\n const cspFn = parseExpression(cleaned, scope);\n if (cspFn) {\n cache.set(cleaned, cspFn);\n return cspFn;\n }\n\n // Fallback to Function constructor (for complex expressions)\n if (!_allowUnsafeEval) {\n dbg('buildEvaluator: blocked unsafe eval fallback for expression:', cleaned);\n reportDiagnostic('expression-unsupported', cleaned, cspExpressionHint(cleaned));\n const blocked = () => undefined;\n cache.set(cleaned, blocked);\n return blocked;\n }\n\n // Apply UNSAFE_METHOD_NAMES blocklist before new Function — prevents\n // prototype-pollution and eval injection via the unsafe eval path.\n const blockedMethod = findBlockedMethod(cleaned);\n if (blockedMethod) {\n const msg = `Blocked unsafe method \"${blockedMethod}\" in expression`;\n reportDiagnostic('expression-unsupported', cleaned, msg);\n throw new Error(`[FormaJS] ${msg}: ${cleaned}`);\n }\n\n try {\n const fn = new Function('__scope', `with(__scope) { return (${cleaned}); }`);\n // Cache proxy — scope.getters is a mutable object, so the proxy\n // always reflects current state without needing to be recreated.\n const proxy = new Proxy(Object.create(null) as Record<string, unknown>, {\n has(_, key: string) { return key in scope.getters; },\n get(_, key: string) {\n // Defense-in-depth: block dangerous property access even if\n // findBlockedMethod missed a bypass (e.g. computed bracket names)\n if (UNSAFE_METHOD_NAMES.has(key)) return undefined;\n const g = scope.getters[key];\n return g ? g() : undefined;\n },\n });\n const unsafe = () => fn(proxy);\n cache.set(cleaned, unsafe);\n return unsafe;\n } catch {\n reportDiagnostic('expression-unsupported', cleaned, 'Expression too complex for CSP-safe mode. Enable unsafe-eval via FormaRuntime.unsafeEval = true, or use the standard (non-hardened) build.');\n const failed = () => undefined;\n cache.set(cleaned, failed);\n return failed;\n }\n}\n\n// ── CSP-safe handler parser ──\n\n/**\n * Parse common handler patterns without `new Function()`.\n * Returns null if the expression is too complex for the CSP-safe parser.\n */\nfunction parseHandler(expr: string, scope: Scope): ((e: Event) => void) | null {\n const normalized = expr.trim().replace(/;+$/g, '').trim();\n if (!normalized) return null;\n\n const ifHandler = parseIfHandler(normalized, scope);\n if (ifHandler) return ifHandler;\n\n const stmts = splitTopLevelStatements(normalized);\n if (stmts.length > 1) {\n const handlers = stmts.map(s => parseHandler(s, scope));\n if (handlers.every(h => h !== null)) {\n return (e: Event) => {\n batch(() => {\n for (const h of handlers) h!(e);\n });\n };\n }\n return null;\n }\n\n const single = stmts[0] ?? normalized;\n\n // count++ or count--\n const incrMatch = single.match(RE_POST_INCR);\n if (incrMatch) {\n const name = incrMatch[1]!;\n const op = incrMatch[2]!;\n return () => {\n batch(() => {\n const val = scope.getters[name]?.() as number ?? 0;\n scope.setters[name]?.(op === '++' ? val + 1 : val - 1);\n });\n };\n }\n\n // ++count or --count\n const preIncrMatch = single.match(RE_PRE_INCR);\n if (preIncrMatch) {\n const op = preIncrMatch[1]!;\n const name = preIncrMatch[2]!;\n return () => {\n batch(() => {\n const val = scope.getters[name]?.() as number ?? 0;\n scope.setters[name]?.(op === '++' ? val + 1 : val - 1);\n });\n };\n }\n\n // prop = !prop (toggle)\n const toggleMatch = single.match(RE_TOGGLE);\n if (toggleMatch && toggleMatch[1] === toggleMatch[2]) {\n const name = toggleMatch[1]!;\n return () => {\n batch(() => {\n scope.setters[name]?.(!scope.getters[name]?.());\n });\n };\n }\n\n // prop = expr (simple assignment)\n const assignMatch = single.match(RE_ASSIGN);\n if (assignMatch) {\n const name = assignMatch[1]!;\n const valExpr = parseExpression(assignMatch[2]!.trim(), scope);\n if (valExpr) {\n if (_debug) dbg(`parseHandler: assignment \"${name} = ...\" — setter exists:`, !!scope.setters[name], ', getter exists:', !!scope.getters[name]);\n return () => {\n batch(() => {\n const val = valExpr();\n if (_debug) dbg(`SETTER: ${name} = ${val} (was: ${scope.getters[name]?.()})`);\n scope.setters[name]?.(val);\n });\n };\n }\n }\n\n // prop += value, prop -= value, prop *= value, prop /= value\n const compoundMatch = single.match(RE_COMPOUND);\n if (compoundMatch) {\n const name = compoundMatch[1]!;\n const op = compoundMatch[2]!;\n const valExpr = parseExpression(compoundMatch[3]!.trim(), scope);\n if (valExpr) {\n return () => {\n batch(() => {\n const current = scope.getters[name]?.() as number ?? 0;\n const val = valExpr() as number;\n switch (op) {\n case '+=': scope.setters[name]?.(current + val); break;\n case '-=': scope.setters[name]?.(current - val); break;\n case '*=': scope.setters[name]?.(current * val); break;\n case '/=': scope.setters[name]?.(current / val); break;\n }\n });\n };\n }\n }\n\n // $refetch('id') — imperative data-fetch trigger (CSP-safe)\n const refetchMatch = single.match(RE_REFETCH_CALL);\n if (refetchMatch) {\n const fetchId = refetchMatch[1]!;\n return () => $refetch(fetchId);\n }\n\n return null;\n}\n\nfunction buildHandler(expr: string, scope: Scope): HandlerBuildResult {\n // Strip balanced outer braces (e.g., `{count++}` → `count++`) but NOT\n // unbalanced ones like `if (x) { a = b }` where the `}` is a code-block close.\n let cleaned = expr.trim();\n if (cleaned.startsWith('{')) {\n const seg = readBalancedSegment(cleaned, 0, '{', '}');\n if (seg && seg.end === cleaned.length - 1) {\n cleaned = seg.inner.trim();\n }\n }\n const cache = getScopeCache(scopeHandlerCache, scope);\n const cached = cache.get(cleaned);\n if (cached) return cached;\n\n // Try CSP-safe parsing first\n const cspFn = parseHandler(cleaned, scope);\n if (cspFn) {\n const result: HandlerBuildResult = { handler: cspFn, supported: true };\n cache.set(cleaned, result);\n return result;\n }\n\n // Fallback to Function constructor (for complex expressions)\n // Use a Proxy with getters and setters so the handler can both read and\n // mutate state (e.g. \"count++\", \"active = !active\").\n if (!_allowUnsafeEval) {\n dbg('buildHandler: blocked unsafe eval fallback for expression:', cleaned);\n reportDiagnostic('handler-unsupported', cleaned, cspExpressionHint(cleaned));\n const result: HandlerBuildResult = {\n handler: () => {},\n supported: false,\n };\n cache.set(cleaned, result);\n return result;\n }\n\n // Apply UNSAFE_METHOD_NAMES blocklist before new Function — prevents\n // prototype-pollution and eval injection via the unsafe eval path.\n const blockedMethod = findBlockedMethod(cleaned);\n if (blockedMethod) {\n const msg = `Blocked unsafe method \"${blockedMethod}\" in handler`;\n reportDiagnostic('handler-unsupported', cleaned, msg);\n throw new Error(`[FormaJS] ${msg}: ${cleaned}`);\n }\n\n try {\n // Accept both `$event` and bare `event` — Claude sometimes generates either.\n const fn = new Function('__scope', '$event', 'event', `with(__scope) { ${cleaned} }`);\n // Cache proxy — scope.getters/setters are mutable objects, so the proxy\n // always reflects current state without needing to be recreated.\n const proxy = new Proxy(Object.create(null) as Record<string, unknown>, {\n has(_, key: string) {\n // Do NOT intercept '$event' or 'event' — let them fall through to\n // function parameters so $event.key, event.stopPropagation(), etc. work.\n if (key === '$event' || key === 'event') return false;\n return key in scope.getters || key in scope.setters;\n },\n get(_, key: string) {\n // Defense-in-depth: block dangerous property access\n if (UNSAFE_METHOD_NAMES.has(key)) return undefined;\n const g = scope.getters[key];\n return g ? g() : undefined;\n },\n set(_, key: string, value: unknown) {\n const s = scope.setters[key];\n if (s) s(value);\n return true;\n },\n });\n const unsafeHandler = (e: Event) => {\n batch(() => fn(proxy, e, e));\n };\n const result: HandlerBuildResult = {\n handler: unsafeHandler,\n supported: true,\n };\n cache.set(cleaned, result);\n return result;\n } catch {\n reportDiagnostic('handler-unsupported', cleaned, 'Expression too complex for CSP-safe mode. Enable unsafe-eval via FormaRuntime.unsafeEval = true, or use the standard (non-hardened) build.');\n const result: HandlerBuildResult = {\n handler: () => {},\n supported: false,\n };\n cache.set(cleaned, result);\n return result;\n }\n}\n\n// ── State initialization ──\n\nconst FORBIDDEN_STATE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction parseState(raw: string): Record<string, unknown> {\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(raw);\n } catch {\n if (_debug) {\n dbg('parseState: Invalid JSON in data-forma-state — use valid JSON with quoted keys. Got:', raw.slice(0, 200));\n }\n return {};\n }\n // Strip prototype-pollution keys\n for (const key of FORBIDDEN_STATE_KEYS) {\n if (key in parsed) delete parsed[key];\n }\n return parsed;\n}\n\n// ── DOM scanner ──\n\nfunction initScope(stateEl: Element): Scope {\n const raw = stateEl.getAttribute('data-forma-state') ?? '{}';\n const state = parseState(raw);\n const keys = Object.keys(state);\n if (_debug) {\n dbg('initScope: parsed', keys.length, 'keys:', keys.join(', '));\n if (keys.length === 0) {\n dbg('initScope: WARNING — empty state! Raw attribute:', raw.slice(0, 200));\n }\n }\n const getters: Record<string, Getter> = {};\n const setters: Record<string, Setter> = {};\n\n for (const [key, initial] of Object.entries(state)) {\n const [get, set] = createSignal(initial);\n getters[key] = get;\n setters[key] = set as Setter;\n }\n\n // Inject $refetch as a callable getter so handlers can use $refetch('id')\n getters['$refetch'] = () => $refetch;\n\n return { getters, setters };\n}\n\n// ── Safe $el proxy ──\n// Allowlist of properties exposed on the $el magic. Everything else\n// (ownerDocument, parentNode, innerHTML, …) returns undefined so that\n// attacker-authored expressions cannot escape to window/document.\n\nconst SAFE_EL_PROPS = new Set([\n // Identity & attributes\n 'id', 'className', 'tagName', 'nodeName',\n 'getAttribute', 'setAttribute', 'removeAttribute', 'hasAttribute', 'toggleAttribute',\n 'dataset', 'classList',\n // Content\n 'textContent', 'innerText',\n // Form elements\n 'value', 'checked', 'disabled', 'selected', 'type', 'name', 'placeholder',\n 'readOnly', 'required', 'min', 'max', 'step', 'pattern',\n // Dimensions & position\n 'getBoundingClientRect', 'offsetWidth', 'offsetHeight',\n 'offsetTop', 'offsetLeft', 'clientWidth', 'clientHeight',\n 'scrollWidth', 'scrollHeight', 'scrollTop', 'scrollLeft',\n // Style\n 'style', 'hidden',\n // Focus & interaction\n 'focus', 'blur', 'click', 'scrollIntoView', 'scrollTo',\n // Traversal (safe — returns elements, not window/document)\n 'closest', 'matches', 'querySelector', 'querySelectorAll',\n 'children', 'childElementCount', 'firstElementChild', 'lastElementChild',\n 'nextElementSibling', 'previousElementSibling',\n]);\n\nfunction createSafeElProxy(el: Element): Element {\n return new Proxy(el, {\n get(target, prop) {\n if (typeof prop === 'symbol') return Reflect.get(target, prop);\n if (!SAFE_EL_PROPS.has(prop)) return undefined;\n const val = Reflect.get(target, prop);\n return typeof val === 'function' ? val.bind(target) : val;\n },\n set(target, prop, value) {\n if (typeof prop === 'symbol') return false;\n if (!SAFE_EL_PROPS.has(prop)) return false;\n return Reflect.set(target, prop, value);\n },\n });\n}\n\nfunction bindElement(el: Element, scope: Scope, disposers: (() => void)[]): void {\n // Inject per-element magics: $el and $dispatch\n // Each element gets its own child scope so $el resolves to the correct element.\n const elMagics: Record<string, unknown> = {\n $el: createSafeElProxy(el),\n $dispatch: (name: string, detail?: unknown) => {\n el.dispatchEvent(new CustomEvent(name, {\n bubbles: true,\n composed: true, // crosses Shadow DOM boundaries (important for <forma-stage>)\n detail,\n }));\n },\n };\n scope = createChildScope(scope, elMagics);\n\n // When the server provides a directive map, we know exactly which directives\n // this element has. Skip getAttribute calls for directives it doesn't have.\n // `known` is null when no map is available (fallback: check everything).\n const known = getDirectives(el);\n\n // data-computed=\"name = expr\" or \"a = expr1; b = expr2\"\n const computedAttr = (!known || known.has('data-computed')) ? el.getAttribute('data-computed') : null;\n if (computedAttr) {\n // Split multi-statement computed: \"a = expr1; b = expr2; c = expr3\"\n // Uses lookahead to split at \"; identifier =\" boundaries without\n // breaking arrow functions (=>) or comparisons (===, ==).\n const parts = computedAttr.split(/;\\s*(?=\\w+\\s*=[^=])/);\n for (const part of parts) {\n const trimmed = part.trim();\n if (!trimmed) continue;\n const match = trimmed.match(RE_COMPUTED);\n if (match) {\n const name = match[1]!;\n const expr = match[2]!;\n // Remove the computed name from getters before building evaluator\n // to prevent self-referential cycle (computed reading itself)\n const prevGetter = scope.getters[name];\n delete scope.getters[name];\n const evaluate = buildEvaluator(`{${expr}}`, scope);\n const getter = createComputed(evaluate);\n scope.getters[name] = getter;\n // Keep the original setter so manual overrides still work\n if (!prevGetter) {\n // If there was no initial state entry, remove the setter too\n delete scope.setters[name];\n }\n }\n }\n }\n\n // data-text=\"{expr}\"\n const textExpr = (!known || known.has('data-text')) ? el.getAttribute('data-text') : null;\n if (textExpr) {\n const evaluate = buildEvaluator(textExpr, scope);\n const dispose = internalEffect(() => {\n setElementTextFast(el, toTextValue(evaluate()));\n });\n disposers.push(dispose);\n }\n\n // data-show=\"{expr}\"\n const showExpr = (!known || known.has('data-show')) ? el.getAttribute('data-show') : null;\n if (showExpr) {\n const evaluate = buildEvaluator(showExpr, scope);\n const transition = parseTransitionSpec(el);\n if (_debug) {\n const tag = el.tagName.toLowerCase();\n const cls = el.className ? `.${String(el.className).split(' ')[0]}` : '';\n dbg(`bindElement: data-show=\"${showExpr}\" on <${tag}${cls}>`);\n }\n let initialized = false;\n const dispose = internalEffect(() => {\n const visible = !!evaluate();\n if (_debug) dbg(`data-show effect: \"${showExpr}\" → ${visible}`);\n applyShowVisibility(el as HTMLElement, visible, transition, !initialized);\n initialized = true;\n });\n disposers.push(dispose);\n if (transition) {\n disposers.push(() => clearTransitionState(el as HTMLElement));\n }\n }\n\n // data-if=\"{expr}\" — conditional DOM insertion/removal with optional transitions\n const ifExpr = (!known || known.has('data-if')) ? el.getAttribute('data-if') : null;\n if (ifExpr) {\n const evaluate = buildEvaluator(ifExpr, scope);\n const transition = parseTransitionSpec(el);\n const placeholder = document.createComment('forma-if');\n const parent = el.parentNode;\n let inserted = true;\n let initialized = false;\n\n const dispose = internalEffect(() => {\n const show = !!evaluate();\n\n if (show && !inserted) {\n // Cancel any in-flight leave\n clearTransitionState(el as HTMLElement);\n el.removeAttribute('data-forma-leaving');\n if (initialized && transition) {\n transitionInsert(el as HTMLElement, parent!, placeholder, transition);\n } else {\n parent?.insertBefore(el, placeholder);\n }\n inserted = true;\n } else if (!show && inserted) {\n if (initialized && transition) {\n transitionRemove(el as HTMLElement, transition, () => {\n if (el.parentNode) {\n parent?.insertBefore(placeholder, el);\n el.remove();\n }\n });\n } else {\n parent?.insertBefore(placeholder, el);\n el.remove();\n }\n inserted = false;\n }\n initialized = true;\n });\n\n disposers.push(dispose);\n if (transition) {\n disposers.push(() => clearTransitionState(el as HTMLElement));\n }\n }\n\n // data-model=\"{prop}\"\n const modelExpr = (!known || known.has('data-model')) ? el.getAttribute('data-model') : null;\n if (modelExpr) {\n const prop = modelExpr.replace(RE_STRIP_BRACES, '').trim();\n const getter = scope.getters[prop];\n const setter = scope.setters[prop];\n if (getter && setter) {\n const input = el as HTMLInputElement;\n const dispose = internalEffect(() => {\n const val = getter();\n if (input.type === 'checkbox') {\n input.checked = !!val;\n } else {\n input.value = String(val ?? '');\n }\n });\n disposers.push(dispose);\n const event = input.type === 'checkbox' ? 'change' : 'input';\n const onModelInput = () => {\n if (input.type === 'checkbox') {\n setter(input.checked);\n } else if (input.type === 'number' || input.type === 'range') {\n setter(Number(input.value));\n } else {\n setter(input.value);\n }\n };\n input.addEventListener(event, onModelInput);\n disposers.push(() => {\n input.removeEventListener(event, onModelInput);\n });\n }\n }\n\n // Single-pass over attributes for data-on:*, data-class:*, data-bind:*\n // When directive map is available, skip the loop entirely if none of these are present.\n const hasColonDirectives = !known || hasAnyPrefix(known, 'data-on:', 'data-class:', 'data-bind:');\n const attrs = el.attributes;\n if (hasColonDirectives) for (let i = 0; i < attrs.length; i++) {\n const attr = attrs[i]!;\n const name = attr.name;\n\n if (name.startsWith('data-on:')) {\n const event = name.slice(8); // 'data-on:'.length === 8\n const built = buildHandler(attr.value, scope);\n const handler = built.handler;\n if (_debug) {\n const tag = el.tagName.toLowerCase();\n const id = el.id ? `#${el.id}` : '';\n const cls = el.className ? `.${String(el.className).split(' ')[0]}` : '';\n dbg(`bindElement: data-on:${event}=\"${attr.value}\" on <${tag}${id}${cls}>`);\n }\n if (!built.supported) {\n el.setAttribute('data-forma-handler-error', 'unsupported');\n } else if (el.hasAttribute('data-forma-handler-error')) {\n el.removeAttribute('data-forma-handler-error');\n }\n if (_debug) {\n const attrVal = attr.value;\n const tracedHandler = (e: Event) => {\n dbg(`HANDLER FIRED: data-on:${event}=\"${attrVal}\"`, 'isTrusted:', e.isTrusted);\n handler(e);\n };\n el.addEventListener(event, tracedHandler);\n disposers.push(() => { el.removeEventListener(event, tracedHandler); });\n } else {\n el.addEventListener(event, handler);\n disposers.push(() => { el.removeEventListener(event, handler); });\n }\n } else if (name.startsWith('data-class:')) {\n const cls = name.slice(11); // 'data-class:'.length === 11\n const evaluate = buildEvaluator(attr.value, scope);\n const dispose = internalEffect(() => {\n el.classList.toggle(cls, !!evaluate());\n });\n disposers.push(dispose);\n } else if (name.startsWith('data-bind:')) {\n const attrName = name.slice(10); // 'data-bind:'.length === 10\n const evaluate = buildEvaluator(attr.value, scope);\n const dispose = internalEffect(() => {\n const val = evaluate();\n if (val == null || val === false) {\n el.removeAttribute(attrName);\n } else {\n el.setAttribute(attrName, String(val));\n }\n });\n disposers.push(dispose);\n }\n }\n\n // data-persist=\"{prop}\"\n const persistExpr = (!known || known.has('data-persist')) ? el.getAttribute('data-persist') : null;\n if (persistExpr) {\n const prop = persistExpr.replace(RE_STRIP_BRACES, '').trim();\n const getter = scope.getters[prop];\n const setter = scope.setters[prop];\n if (getter && setter) {\n const key = 'forma:' + prop;\n try {\n const saved = localStorage.getItem(key);\n if (saved !== null) setter(JSON.parse(saved));\n } catch { /* ignore parse errors */ }\n const dispose = internalEffect(() => {\n try { localStorage.setItem(key, JSON.stringify(getter())); } catch { /* quota */ }\n });\n disposers.push(dispose);\n }\n }\n\n // data-list=\"{expr}\" — keyed reconciliation with LIS\n const listExpr = (!known || known.has('data-list')) ? el.getAttribute('data-list') : null;\n if (listExpr) {\n const evaluate = buildEvaluator(listExpr, scope);\n const templateEl = el.children[0] as Element | undefined;\n if (templateEl) {\n const template = templateEl.cloneNode(true) as Element;\n // Remove original template from DOM\n el.removeChild(templateEl);\n\n // Detect key attribute: data-key=\"{item.id}\" -> extracts \"id\"\n const keyAttr = template.getAttribute('data-key');\n const keyProp = keyAttr\n ? keyAttr.replace(RE_STRIP_ITEM_BRACES, '').trim()\n : null;\n\n // Parse transition spec from the list container element\n const listTransition = parseTransitionSpec(el);\n\n let oldItems: unknown[] = [];\n let oldNodes: Node[] = [];\n\n // For index-based keying (no data-key), we wrap items in objects\n // that carry their index so the keyFn can extract it without a\n // second argument. For property-based keying, items pass through raw.\n interface IndexWrapped { __idx: number; __item: unknown }\n\n /** Dispose all bindings stored on a clone element */\n function disposeCloneBindings(node: Node): void {\n const el = node as any;\n if (Array.isArray(el.__formaDisposers)) {\n for (const d of el.__formaDisposers) {\n try { d(); } catch { /* ensure all disposers run */ }\n }\n delete el.__formaDisposers;\n }\n }\n\n /** Clone template, bind directives via child scope */\n function createBoundClone(item: unknown, index: number): Element {\n const clone = cloneWithTemplateData(template, item);\n const childScope = createChildScope(scope, { item, index });\n const itemDisposers: (() => void)[] = [];\n bindElement(clone, childScope, itemDisposers);\n for (const desc of Array.from(clone.querySelectorAll('*'))) {\n bindElement(desc, childScope, itemDisposers);\n }\n (clone as any).__formaDisposers = itemDisposers;\n return clone;\n }\n\n /** Dispose old bindings and rebind with fresh data */\n function updateBoundClone(node: Node, item: unknown, index: number): void {\n disposeCloneBindings(node);\n updateTemplateData(node as Element, item);\n const childScope = createChildScope(scope, { item, index });\n const itemDisposers: (() => void)[] = [];\n bindElement(node as Element, childScope, itemDisposers);\n for (const desc of Array.from((node as Element).querySelectorAll('*'))) {\n bindElement(desc, childScope, itemDisposers);\n }\n (node as any).__formaDisposers = itemDisposers;\n }\n\n // Build transition hooks for reconcileList (only when transition attrs present)\n const listHooks: ListTransitionHooks | undefined = listTransition ? {\n onInsert: (node: Node) => {\n const htmlEl = node as HTMLElement;\n if (!htmlEl.setAttribute) return; // text node guard\n const state = getTransitionState(htmlEl);\n state.token += 1;\n const token = state.token;\n if (state.cancel) state.cancel();\n state.cancel = runTransitionPhase(\n htmlEl,\n {\n base: listTransition.enter,\n from: listTransition.enterFrom,\n to: listTransition.enterTo,\n durationMs: listTransition.enterDurationMs,\n },\n () => {\n const current = getTransitionState(htmlEl);\n if (current.token === token) current.cancel = null;\n },\n );\n },\n onBeforeRemove: (node: Node, done: () => void) => {\n const htmlEl = node as HTMLElement;\n if (!htmlEl.setAttribute) { done(); return; } // text node guard\n disposeCloneBindings(node);\n transitionRemove(htmlEl, listTransition, () => {\n done();\n });\n },\n } : undefined;\n\n const dispose = internalEffect(() => {\n const rawItems = evaluate();\n if (!Array.isArray(rawItems)) {\n // Remove all — dispose bindings first\n for (const n of oldNodes) {\n disposeCloneBindings(n);\n el.removeChild(n);\n }\n oldItems = [];\n oldNodes = [];\n return;\n }\n\n // Cancel any in-flight leave animations before reconciliation\n if (listTransition) {\n const leavingNodes = el.querySelectorAll('[data-forma-leaving]');\n for (const ln of Array.from(leavingNodes)) {\n clearTransitionState(ln as HTMLElement);\n ln.removeAttribute('data-forma-leaving');\n if (ln.parentNode) ln.parentNode.removeChild(ln);\n }\n }\n\n // Snapshot old nodes before reconciliation to detect removals\n const prevNodes = new Set(oldNodes);\n\n if (keyProp) {\n // ── Property-based keying ──\n const result = reconcileList(\n el,\n oldItems,\n rawItems,\n oldNodes,\n (item: unknown) => String((item as Record<string, unknown>)?.[keyProp] ?? ''),\n (item: unknown) => {\n const idx = rawItems.indexOf(item);\n return createBoundClone(item, idx);\n },\n (node: Node, item: unknown) => {\n const idx = rawItems.indexOf(item);\n updateBoundClone(node, item, idx);\n },\n undefined, // beforeNode\n listHooks,\n );\n // Dispose bindings on nodes that were removed by reconcileList\n const nextNodes = new Set(result.nodes);\n for (const n of prevNodes) {\n if (!nextNodes.has(n)) {\n // Skip nodes mid-leave — onBeforeRemove already disposed them\n if ((n as Element).hasAttribute?.('data-forma-leaving')) continue;\n disposeCloneBindings(n);\n }\n }\n oldItems = result.items;\n oldNodes = result.nodes;\n } else {\n // ── Index-based keying ──\n // Wrap items so each carries its index as the key.\n const wrapped: IndexWrapped[] = rawItems.map((item, i) => ({ __idx: i, __item: item }));\n const oldWrapped = oldItems as IndexWrapped[];\n\n const result = reconcileList<IndexWrapped>(\n el,\n oldWrapped,\n wrapped,\n oldNodes,\n (w: IndexWrapped) => w.__idx,\n (w: IndexWrapped) => createBoundClone(w.__item, w.__idx),\n (node: Node, w: IndexWrapped) => updateBoundClone(node, w.__item, w.__idx),\n undefined, // beforeNode\n listHooks,\n );\n // Dispose bindings on nodes that were removed by reconcileList\n const nextNodes = new Set(result.nodes);\n for (const n of prevNodes) {\n if (!nextNodes.has(n)) {\n // Skip nodes mid-leave — onBeforeRemove already disposed them\n if ((n as Element).hasAttribute?.('data-forma-leaving')) continue;\n disposeCloneBindings(n);\n }\n }\n oldItems = result.items;\n oldNodes = result.nodes;\n }\n });\n disposers.push(dispose);\n }\n }\n\n // data-fetch=\"[METHOD] url → prop [|loading:prop] [|error:prop] [|poll:ms]\"\n const fetchExpr = (!known || known.has('data-fetch')) ? el.getAttribute('data-fetch') : null;\n if (fetchExpr) {\n const arrowMatch = fetchExpr.match(RE_FETCH);\n if (arrowMatch) {\n const urlPart = arrowMatch[1]!.trim();\n const target = arrowMatch[2]!.trim();\n const modifiers = arrowMatch[3]?.trim() ?? '';\n\n let method = 'GET';\n let url = urlPart;\n const methodMatch = urlPart.match(RE_FETCH_METHOD);\n if (methodMatch) {\n method = methodMatch[1]!.toUpperCase();\n url = methodMatch[2]!.trim();\n }\n\n let loadingTarget: string | undefined;\n let errorTarget: string | undefined;\n let interval: number | undefined;\n for (const mod of modifiers.split('|').filter(Boolean)) {\n const [k, v] = mod.split(':').map(s => s.trim());\n if (k === 'loading') loadingTarget = v;\n else if (k === 'error') errorTarget = v;\n else if (k === 'poll') interval = parseInt(v ?? '0', 10);\n }\n\n // Create signals for target, loading, and error\n const [getTarget, setTarget] = createSignal<unknown>(null);\n scope.getters[target] = getTarget;\n scope.setters[target] = setTarget as Setter;\n if (loadingTarget) {\n const [gl, sl] = createSignal(false);\n scope.getters[loadingTarget] = gl;\n scope.setters[loadingTarget] = sl as Setter;\n }\n if (errorTarget) {\n const [ge, se] = createSignal<unknown>(null);\n scope.getters[errorTarget] = ge;\n scope.setters[errorTarget] = se as Setter;\n }\n\n const doFetch = () => {\n if (loadingTarget) scope.setters[loadingTarget]!(true);\n fetch(url, { method })\n .then(r => r.json())\n .then(data => {\n setTarget(data);\n if (loadingTarget) scope.setters[loadingTarget]!(false);\n })\n .catch(err => {\n if (errorTarget) scope.setters[errorTarget]!(err.message);\n if (loadingTarget) scope.setters[loadingTarget]!(false);\n });\n };\n\n // Register in $refetch registry if data-fetch-id is present\n const fetchId = el.getAttribute('data-fetch-id');\n if (fetchId) {\n _refetchRegistry.set(fetchId, doFetch);\n disposers.push(() => _refetchRegistry.delete(fetchId));\n }\n\n doFetch();\n if (interval && interval > 0) {\n const id = setInterval(doFetch, interval);\n disposers.push(() => clearInterval(id));\n }\n }\n }\n}\n\n// ── Scope mounting / unmounting (single data-forma-state element) ──\n\n/**\n * Mount a single `data-forma-state` element — creates signals, binds\n * all descendants, stores disposers on the element for cleanup.\n * Idempotent: skips elements that are already mounted.\n */\n/** CSS selector matching elements with at least one Forma directive.\n * Avoids scanning every descendant — only visits directive-bearing elements. */\nconst DIRECTIVE_SELECTOR = [\n '[data-text]', '[data-show]', '[data-if]', '[data-model]',\n '[data-computed]', '[data-persist]', '[data-list]', '[data-fetch]',\n '[data-bind\\\\:*]', '[data-class\\\\:*]', '[data-on\\\\:*]',\n // Catch-all for colon-prefixed data attrs that the escaped selectors miss in some engines\n '[data-transition]',\n].join(',');\n\n/** Fast check: does this element have any Forma directive attribute? */\nfunction hasDirective(el: Element): boolean {\n const attrs = el.attributes;\n for (let i = 0; i < attrs.length; i++) {\n const name = attrs[i]!.name;\n if (name.startsWith('data-text') || name.startsWith('data-show') ||\n name.startsWith('data-if') || name.startsWith('data-model') ||\n name.startsWith('data-computed') || name.startsWith('data-persist') ||\n name.startsWith('data-list') || name.startsWith('data-fetch') ||\n name.startsWith('data-on:') || name.startsWith('data-class:') ||\n name.startsWith('data-bind:') || name.startsWith('data-transition')) {\n return true;\n }\n }\n return false;\n}\n\n// ── Pre-compiled Directive Map ──\n//\n// When the server sends a directive_map sidecar (data-forma-id → directive names),\n// the runtime uses it in two ways:\n//\n// 1. mountScope(): targeted CSS selector queries only directive-bearing elements\n// instead of querySelectorAll('*') + attribute scan on every descendant.\n//\n// 2. bindElement(): skips getAttribute calls for directives the element doesn't\n// have, avoiding unnecessary work for elements with only 1-2 directives.\n\n/** Full map: data-forma-id → Set of directive attribute names. */\nlet _directiveMap: Map<string, Set<string>> | null = null;\n\n/**\n * Load a pre-compiled directive map from the server.\n * Keys are data-forma-id values, values are arrays of directive attribute names.\n */\nfunction setDirectiveMap(map: Record<string, string[]> | null): void {\n if (!map || Object.keys(map).length === 0) {\n _directiveMap = null;\n return;\n }\n _directiveMap = new Map();\n for (const id in map) {\n _directiveMap.set(id, new Set(map[id]!));\n }\n}\n\n/**\n * Build a CSS selector that targets only elements with known directives.\n * Returns null when the map has too many entries (selector would be huge)\n * or when no map is available.\n */\nfunction buildDirectiveSelector(): string | null {\n if (!_directiveMap || _directiveMap.size === 0) return null;\n // Cap at 200 IDs to avoid pathologically long selectors.\n // Above that, querySelectorAll('*') + Set check is likely faster.\n if (_directiveMap.size > 200) return null;\n const parts: string[] = [];\n for (const id of _directiveMap.keys()) {\n parts.push(`[data-forma-id=\"${id}\"]`);\n }\n return parts.join(',');\n}\n\n/** Get the directive set for an element, or null if unknown. */\nfunction getDirectives(el: Element): Set<string> | null {\n if (!_directiveMap) return null;\n const id = el.getAttribute('data-forma-id');\n if (!id) return null;\n return _directiveMap.get(id) ?? null;\n}\n\n/** Check if any entry in a Set starts with one of the given prefixes. */\nfunction hasAnyPrefix(set: Set<string>, ...prefixes: string[]): boolean {\n for (const entry of set) {\n for (const prefix of prefixes) {\n if (entry.startsWith(prefix)) return true;\n }\n }\n return false;\n}\n\nfunction mountScope(root: Element): void {\n // Idempotency guard — never double-bind\n if ((root as any).__formaDisposers) {\n if (_debug) dbg('mountScope: SKIPPED (already mounted)');\n return;\n }\n\n const scope = initScope(root);\n const disposers: (() => void)[] = [];\n\n // Bind the root itself\n bindElement(root, scope, disposers);\n\n // Bind only directive-bearing descendants (skip inert elements).\n // When the server provides a directive map, we build a targeted CSS selector\n // that queries only elements with known directives — no querySelectorAll('*').\n let boundCount = 0;\n const selector = buildDirectiveSelector();\n if (selector) {\n // Fast path: query only elements the server told us have directives\n const targets = root.querySelectorAll(selector);\n for (let i = 0; i < targets.length; i++) {\n bindElement(targets[i]!, scope, disposers);\n boundCount++;\n }\n } else {\n // Fallback: scan all descendants and check attributes\n const descendants = root.querySelectorAll('*');\n for (let i = 0; i < descendants.length; i++) {\n const el = descendants[i]!;\n if (hasDirective(el)) {\n bindElement(el, scope, disposers);\n boundCount++;\n }\n }\n }\n\n // Store disposers on the root element for cleanup\n (root as any).__formaDisposers = disposers;\n // Expose scope for devtools (State Inspector panel)\n (root as any).__formaScope = scope;\n (root as any).__formaInitialState = root.getAttribute('data-forma-state') ?? '{}';\n if (_debug) dbg('mountScope: DONE —', boundCount, 'elements bound,', disposers.length, 'disposers', selector ? '(targeted)' : '(full scan)');\n}\n\n/**\n * Unmount a single `data-forma-state` element — disposes all effects,\n * intervals, and event listeners. Safe to call on already-unmounted elements.\n */\nfunction unmountScope(root: Element): void {\n const disposers = (root as any).__formaDisposers as (() => void)[] | undefined;\n if (disposers) {\n for (const d of disposers) {\n try { d(); } catch { /* ensure all disposers run */ }\n }\n delete (root as any).__formaDisposers;\n delete (root as any).__formaScope;\n delete (root as any).__formaInitialState;\n }\n}\n\n// ── MutationObserver — auto-discovery of new data-forma-state elements ──\n//\n// Cost: O(addedNodes) per mutation batch. Never re-scans the whole document.\n// The observer only fires for childList mutations (nodes added/removed) and\n// attribute mutations on the `data-forma-state` attribute specifically.\n\nlet _observer: MutationObserver | null = null;\nconst ELEMENT_NODE = 1;\nconst MUTATION_CHUNK_SIZE = 40;\nlet _pendingMutations: MutationRecord[] = [];\nlet _drainingMutations = false;\n\nfunction processMutation(mutation: MutationRecord): void {\n // ── Removed nodes: clean up disposers to prevent memory leaks ──\n for (let i = 0; i < mutation.removedNodes.length; i++) {\n const node = mutation.removedNodes[i]!;\n if (node.nodeType !== ELEMENT_NODE) continue;\n const el = node as Element;\n if (el.hasAttribute('data-forma-state')) {\n if (_debug) dbg('MutationObserver: REMOVED scope');\n unmountScope(el);\n }\n const removed = el.querySelectorAll('[data-forma-state]');\n for (let j = 0; j < removed.length; j++) {\n unmountScope(removed[j]!);\n }\n }\n\n // ── Added nodes: auto-mount new scopes ──\n for (let i = 0; i < mutation.addedNodes.length; i++) {\n const node = mutation.addedNodes[i]!;\n if (node.nodeType !== ELEMENT_NODE) continue;\n const el = node as Element;\n if (el.closest('[data-forma-leaving]')) continue;\n if (el.hasAttribute('data-forma-state')) {\n if (_debug) dbg('MutationObserver: ADDED scope via mutation');\n mountScope(el);\n }\n const added = el.querySelectorAll('[data-forma-state]');\n if (_debug && added.length > 0) {\n dbg('MutationObserver: found', added.length, 'nested scope(s) in added subtree');\n }\n for (let j = 0; j < added.length; j++) {\n const desc = added[j]!;\n if (desc.closest('[data-forma-leaving]')) continue;\n mountScope(desc);\n }\n }\n\n // ── Attribute change: data-forma-state added/removed/changed ──\n if (mutation.type === 'attributes' && mutation.attributeName === 'data-forma-state') {\n const target = mutation.target as Element;\n // Always unmount first (cleans up old bindings)\n unmountScope(target);\n // Re-mount if the attribute still exists (value may have changed)\n if (target.hasAttribute('data-forma-state')) {\n mountScope(target);\n }\n }\n}\n\nasync function drainMutationQueue(): Promise<void> {\n try {\n while (_pendingMutations.length > 0) {\n const batch = _pendingMutations.splice(0, MUTATION_CHUNK_SIZE);\n for (let i = 0; i < batch.length; i++) {\n processMutation(batch[i]!);\n }\n if (_pendingMutations.length > 0) {\n await yieldToMain();\n }\n }\n } finally {\n _drainingMutations = false;\n // Handle races where new mutations were queued after the while-check.\n if (_pendingMutations.length > 0 && !_drainingMutations) {\n _drainingMutations = true;\n void drainMutationQueue();\n }\n }\n}\n\nfunction handleMutations(mutations: MutationRecord[]): void {\n if (_debug) dbg('MutationObserver: queued', mutations.length, 'mutation(s)');\n _pendingMutations.push(...mutations);\n if (_drainingMutations) return;\n _drainingMutations = true;\n void drainMutationQueue();\n}\n\nfunction startObserver(): void {\n if (_observer) return;\n _observer = new MutationObserver(handleMutations);\n const target = document.body || document.documentElement;\n if (target) {\n _observer.observe(target, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['data-forma-state'],\n });\n }\n}\n\nfunction stopObserver(): void {\n if (_observer) {\n _observer.disconnect();\n _observer = null;\n }\n}\n\n// ── Main init ──\n\nfunction initRuntime(): void {\n if (_autoContainment) {\n applyContainmentHints(document, { skipIfAlreadySet: true });\n }\n const stateRoots = document.querySelectorAll('[data-forma-state]');\n if (_debug) dbg('initRuntime: found', stateRoots.length, 'scope(s)');\n for (const root of Array.from(stateRoots)) {\n mountScope(root);\n }\n // Start auto-discovery after initial scan\n startObserver();\n if (_debug) dbg('initRuntime: MutationObserver started');\n}\n\n/** Dispose all FormaJS scopes — clears effects, intervals, event listeners, and stops the observer. */\nfunction destroyRuntime(): void {\n stopObserver();\n const stateRoots = document.querySelectorAll('[data-forma-state]');\n for (const root of Array.from(stateRoots)) {\n unmountScope(root);\n }\n}\n\n/**\n * Mount a specific element or subtree — scans for `data-forma-state`\n * elements and initializes their reactive bindings.\n *\n * Use this for manual control when injecting HTML dynamically.\n * With the MutationObserver active, this is usually not needed.\n *\n * @param el - The root element to scan (checks itself and all descendants).\n */\nfunction mount(el: Element): void {\n if (el.hasAttribute('data-forma-state')) {\n mountScope(el);\n }\n const descendants = el.querySelectorAll('[data-forma-state]');\n for (const desc of Array.from(descendants)) {\n mountScope(desc);\n }\n}\n\n/**\n * Unmount a specific element or subtree — disposes all reactive bindings\n * for `data-forma-state` elements within.\n *\n * @param el - The root element to clean up (checks itself and all descendants).\n */\nfunction unmount(el: Element): void {\n if (el.hasAttribute('data-forma-state')) {\n unmountScope(el);\n }\n const descendants = el.querySelectorAll('[data-forma-state]');\n for (const desc of Array.from(descendants)) {\n unmountScope(desc);\n }\n}\n\n// Auto-init in browser contexts on DOMContentLoaded (or immediately if already loaded).\nif (typeof document !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', initRuntime);\n } else {\n initRuntime();\n }\n}\n\n/** Enable/disable debug logging. Also toggleable via window.__FORMA_DEBUG = true */\nfunction setDebug(on: boolean): void { _debug = on; }\n/** Set unsafe-eval mode. `locked-off` is hardened and non-toggleable via setUnsafeEval. */\nfunction setUnsafeEvalMode(mode: UnsafeEvalMode): void {\n if (_unsafeEvalMode === mode) return;\n _unsafeEvalMode = mode;\n if (mode === 'locked-off') _allowUnsafeEval = false;\n if (mode === 'locked-on') _allowUnsafeEval = true;\n if (mode === 'mutable') _allowUnsafeEval = true;\n // Rebuild caches whenever policy changes.\n scopeExpressionCache = new WeakMap<Scope, Map<string, () => unknown>>();\n scopeHandlerCache = new WeakMap<Scope, Map<string, HandlerBuildResult>>();\n}\n/** Enable/disable unsafe `new Function` fallback for complex expressions. */\nfunction setUnsafeEval(on: boolean): void {\n if (_unsafeEvalMode !== 'mutable') {\n dbg(\n `setUnsafeEval ignored (mode=${_unsafeEvalMode}); unsafe fallback is locked`,\n );\n return;\n }\n if (_allowUnsafeEval === on) return;\n _allowUnsafeEval = on;\n // Rebuild handlers/evaluators after mode change so cached blocked results\n // don't persist when toggling trusted mode at runtime.\n scopeExpressionCache = new WeakMap<Scope, Map<string, () => unknown>>();\n scopeHandlerCache = new WeakMap<Scope, Map<string, HandlerBuildResult>>();\n}\n/** Get current unsafe-eval policy mode. */\nfunction getUnsafeEvalMode(): UnsafeEvalMode { return _unsafeEvalMode; }\n/** Enable/disable runtime diagnostics for unsupported expressions/handlers. */\nfunction setDiagnostics(on: boolean): void { _diagnosticsEnabled = on; }\n\n/** Runtime diagnostics captured while parsing/binding templates. */\nfunction getDiagnostics(): RuntimeDiagnostic[] {\n return Array.from(diagnostics.values()).map(d => ({ ...d }));\n}\n\n/** Clear runtime diagnostics collected so far. */\nfunction clearDiagnostics(): void {\n diagnostics.clear();\n}\n\n// ── DevTools API — State Inspector ──\n\ninterface ScopeDescriptor {\n element: Element;\n id: string;\n values: Record<string, { value: unknown; type: string }>;\n initialJSON: string;\n}\n\n/**\n * DevTools: enumerate all active scopes and their current signal values.\n * Only called when the State Inspector panel is open — zero overhead otherwise.\n */\nfunction getScopes(): ScopeDescriptor[] {\n const roots = document.querySelectorAll('[data-forma-state]');\n const result: ScopeDescriptor[] = [];\n\n for (const root of Array.from(roots)) {\n if (root.closest('[data-forma-leaving]')) continue;\n const scope = (root as any).__formaScope as Scope | undefined;\n const initialJSON = (root as any).__formaInitialState as string | undefined;\n if (!scope) continue;\n\n const values: Record<string, { value: unknown; type: string }> = {};\n for (const key of Object.keys(scope.getters)) {\n const val = scope.getters[key]!();\n values[key] = { value: val, type: typeof val };\n }\n\n result.push({\n element: root,\n id: root.getAttribute('data-forma-id') || root.id || root.tagName.toLowerCase(),\n values,\n initialJSON: initialJSON ?? '{}',\n });\n }\n return result;\n}\n\n/**\n * DevTools: set a state value on a specific scope element.\n * Triggers normal reactive effects (data-show, data-text, etc.).\n */\nfunction setScopeValue(element: Element, key: string, value: unknown): void {\n const scope = (element as any).__formaScope as Scope | undefined;\n if (!scope?.setters[key]) return;\n batch(() => { scope.setters[key]!(value); });\n}\n\n/**\n * DevTools: reset all values on a scope to their initial JSON state.\n */\nfunction resetScope(element: Element): void {\n const scope = (element as any).__formaScope as Scope | undefined;\n const initialJSON = (element as any).__formaInitialState as string | undefined;\n if (!scope || !initialJSON) return;\n\n const initial = parseState(initialJSON);\n batch(() => {\n for (const [key, val] of Object.entries(initial)) {\n scope.setters[key]?.(val);\n }\n });\n}\n\n// ── Reconciler ──\n\nlet _reconciler: ((container: Element, html: string) => void) | null = null;\n\nfunction getReconciler() {\n if (!_reconciler) {\n _reconciler = createReconciler({\n mountScope,\n unmountScope,\n disconnectObserver() {\n if (_observer) {\n _observer.disconnect();\n }\n },\n reconnectObserver() {\n if (_observer) {\n const target = document.body || document.documentElement;\n if (target) {\n _observer.observe(target, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['data-forma-state'],\n });\n }\n }\n },\n batch,\n });\n }\n return _reconciler;\n}\n\n/** Reconcile a container's DOM against a new HTML string. */\nfunction reconcile(container: Element, html: string): void {\n getReconciler()(container, html);\n}\n\nexport {\n initRuntime,\n destroyRuntime,\n mount,\n unmount,\n reconcile,\n setDebug,\n setUnsafeEvalMode,\n getUnsafeEvalMode,\n setUnsafeEval,\n yieldToMain,\n applyContainmentHints,\n setDirectiveMap,\n setDiagnostics,\n getDiagnostics,\n clearDiagnostics,\n getScopes,\n setScopeValue,\n resetScope,\n};\n","export const ReactiveFlags = {\n None: 0,\n Mutable: 1,\n Watching: 2,\n RecursedCheck: 4,\n Recursed: 8,\n Dirty: 16,\n Pending: 32,\n};\nexport function createReactiveSystem({ update, notify, unwatched, }) {\n return {\n link,\n unlink,\n propagate,\n checkDirty,\n shallowPropagate,\n };\n function link(dep, sub, version) {\n const prevDep = sub.depsTail;\n if (prevDep !== undefined && prevDep.dep === dep) {\n return;\n }\n const nextDep = prevDep !== undefined ? prevDep.nextDep : sub.deps;\n if (nextDep !== undefined && nextDep.dep === dep) {\n nextDep.version = version;\n sub.depsTail = nextDep;\n return;\n }\n const prevSub = dep.subsTail;\n if (prevSub !== undefined && prevSub.version === version && prevSub.sub === sub) {\n return;\n }\n const newLink = sub.depsTail\n = dep.subsTail\n = {\n version,\n dep,\n sub,\n prevDep,\n nextDep,\n prevSub,\n nextSub: undefined,\n };\n if (nextDep !== undefined) {\n nextDep.prevDep = newLink;\n }\n if (prevDep !== undefined) {\n prevDep.nextDep = newLink;\n }\n else {\n sub.deps = newLink;\n }\n if (prevSub !== undefined) {\n prevSub.nextSub = newLink;\n }\n else {\n dep.subs = newLink;\n }\n }\n function unlink(link, sub = link.sub) {\n const dep = link.dep;\n const prevDep = link.prevDep;\n const nextDep = link.nextDep;\n const nextSub = link.nextSub;\n const prevSub = link.prevSub;\n if (nextDep !== undefined) {\n nextDep.prevDep = prevDep;\n }\n else {\n sub.depsTail = prevDep;\n }\n if (prevDep !== undefined) {\n prevDep.nextDep = nextDep;\n }\n else {\n sub.deps = nextDep;\n }\n if (nextSub !== undefined) {\n nextSub.prevSub = prevSub;\n }\n else {\n dep.subsTail = prevSub;\n }\n if (prevSub !== undefined) {\n prevSub.nextSub = nextSub;\n }\n else if ((dep.subs = nextSub) === undefined) {\n unwatched(dep);\n }\n return nextDep;\n }\n function propagate(link) {\n let next = link.nextSub;\n let stack;\n top: do {\n const sub = link.sub;\n let flags = sub.flags;\n if (!(flags & (4 | 8 | 16 | 32))) {\n sub.flags = flags | 32;\n }\n else if (!(flags & (4 | 8))) {\n flags = 0;\n }\n else if (!(flags & 4)) {\n sub.flags = (flags & ~8) | 32;\n }\n else if (!(flags & (16 | 32)) && isValidLink(link, sub)) {\n sub.flags = flags | (8 | 32);\n flags &= 1;\n }\n else {\n flags = 0;\n }\n if (flags & 2) {\n notify(sub);\n }\n if (flags & 1) {\n const subSubs = sub.subs;\n if (subSubs !== undefined) {\n const nextSub = (link = subSubs).nextSub;\n if (nextSub !== undefined) {\n stack = { value: next, prev: stack };\n next = nextSub;\n }\n continue;\n }\n }\n if ((link = next) !== undefined) {\n next = link.nextSub;\n continue;\n }\n while (stack !== undefined) {\n link = stack.value;\n stack = stack.prev;\n if (link !== undefined) {\n next = link.nextSub;\n continue top;\n }\n }\n break;\n } while (true);\n }\n function checkDirty(link, sub) {\n let stack;\n let checkDepth = 0;\n let dirty = false;\n top: do {\n const dep = link.dep;\n const flags = dep.flags;\n if (sub.flags & 16) {\n dirty = true;\n }\n else if ((flags & (1 | 16)) === (1 | 16)) {\n if (update(dep)) {\n const subs = dep.subs;\n if (subs.nextSub !== undefined) {\n shallowPropagate(subs);\n }\n dirty = true;\n }\n }\n else if ((flags & (1 | 32)) === (1 | 32)) {\n if (link.nextSub !== undefined || link.prevSub !== undefined) {\n stack = { value: link, prev: stack };\n }\n link = dep.deps;\n sub = dep;\n ++checkDepth;\n continue;\n }\n if (!dirty) {\n const nextDep = link.nextDep;\n if (nextDep !== undefined) {\n link = nextDep;\n continue;\n }\n }\n while (checkDepth--) {\n const firstSub = sub.subs;\n const hasMultipleSubs = firstSub.nextSub !== undefined;\n if (hasMultipleSubs) {\n link = stack.value;\n stack = stack.prev;\n }\n else {\n link = firstSub;\n }\n if (dirty) {\n if (update(sub)) {\n if (hasMultipleSubs) {\n shallowPropagate(firstSub);\n }\n sub = link.sub;\n continue;\n }\n dirty = false;\n }\n else {\n sub.flags &= ~32;\n }\n sub = link.sub;\n const nextDep = link.nextDep;\n if (nextDep !== undefined) {\n link = nextDep;\n continue top;\n }\n }\n return dirty;\n } while (true);\n }\n function shallowPropagate(link) {\n do {\n const sub = link.sub;\n const flags = sub.flags;\n if ((flags & (32 | 16)) === 32) {\n sub.flags = flags | 16;\n if ((flags & (2 | 4)) === 2) {\n notify(sub);\n }\n }\n } while ((link = link.nextSub) !== undefined);\n }\n function isValidLink(checkLink, sub) {\n let link = sub.depsTail;\n while (link !== undefined) {\n if (link === checkLink) {\n return true;\n }\n link = link.prevDep;\n }\n return false;\n }\n}\n","import { createReactiveSystem } from './system.mjs';\nlet cycle = 0;\nlet batchDepth = 0;\nlet notifyIndex = 0;\nlet queuedLength = 0;\nlet activeSub;\nconst queued = [];\nconst { link, unlink, propagate, checkDirty, shallowPropagate, } = createReactiveSystem({\n update(node) {\n if (node.depsTail !== undefined) {\n return updateComputed(node);\n }\n else {\n return updateSignal(node);\n }\n },\n notify(effect) {\n let insertIndex = queuedLength;\n let firstInsertedIndex = insertIndex;\n do {\n queued[insertIndex++] = effect;\n effect.flags &= ~2;\n effect = effect.subs?.sub;\n if (effect === undefined || !(effect.flags & 2)) {\n break;\n }\n } while (true);\n queuedLength = insertIndex;\n while (firstInsertedIndex < --insertIndex) {\n const left = queued[firstInsertedIndex];\n queued[firstInsertedIndex++] = queued[insertIndex];\n queued[insertIndex] = left;\n }\n },\n unwatched(node) {\n if (!(node.flags & 1)) {\n effectScopeOper.call(node);\n }\n else if (node.depsTail !== undefined) {\n node.depsTail = undefined;\n node.flags = 1 | 16;\n purgeDeps(node);\n }\n },\n});\nexport function getActiveSub() {\n return activeSub;\n}\nexport function setActiveSub(sub) {\n const prevSub = activeSub;\n activeSub = sub;\n return prevSub;\n}\nexport function getBatchDepth() {\n return batchDepth;\n}\nexport function startBatch() {\n ++batchDepth;\n}\nexport function endBatch() {\n if (!--batchDepth) {\n flush();\n }\n}\nexport function isSignal(fn) {\n return fn.name === 'bound ' + signalOper.name;\n}\nexport function isComputed(fn) {\n return fn.name === 'bound ' + computedOper.name;\n}\nexport function isEffect(fn) {\n return fn.name === 'bound ' + effectOper.name;\n}\nexport function isEffectScope(fn) {\n return fn.name === 'bound ' + effectScopeOper.name;\n}\nexport function signal(initialValue) {\n return signalOper.bind({\n currentValue: initialValue,\n pendingValue: initialValue,\n subs: undefined,\n subsTail: undefined,\n flags: 1,\n });\n}\nexport function computed(getter) {\n return computedOper.bind({\n value: undefined,\n subs: undefined,\n subsTail: undefined,\n deps: undefined,\n depsTail: undefined,\n flags: 0,\n getter: getter,\n });\n}\nexport function effect(fn) {\n const e = {\n fn,\n subs: undefined,\n subsTail: undefined,\n deps: undefined,\n depsTail: undefined,\n flags: 2 | 4,\n };\n const prevSub = setActiveSub(e);\n if (prevSub !== undefined) {\n link(e, prevSub, 0);\n }\n try {\n e.fn();\n }\n finally {\n activeSub = prevSub;\n e.flags &= ~4;\n }\n return effectOper.bind(e);\n}\nexport function effectScope(fn) {\n const e = {\n deps: undefined,\n depsTail: undefined,\n subs: undefined,\n subsTail: undefined,\n flags: 0,\n };\n const prevSub = setActiveSub(e);\n if (prevSub !== undefined) {\n link(e, prevSub, 0);\n }\n try {\n fn();\n }\n finally {\n activeSub = prevSub;\n }\n return effectScopeOper.bind(e);\n}\nexport function trigger(fn) {\n const sub = {\n deps: undefined,\n depsTail: undefined,\n flags: 2,\n };\n const prevSub = setActiveSub(sub);\n try {\n fn();\n }\n finally {\n activeSub = prevSub;\n let link = sub.deps;\n while (link !== undefined) {\n const dep = link.dep;\n link = unlink(link, sub);\n const subs = dep.subs;\n if (subs !== undefined) {\n sub.flags = 0;\n propagate(subs);\n shallowPropagate(subs);\n }\n }\n if (!batchDepth) {\n flush();\n }\n }\n}\nfunction updateComputed(c) {\n ++cycle;\n c.depsTail = undefined;\n c.flags = 1 | 4;\n const prevSub = setActiveSub(c);\n try {\n const oldValue = c.value;\n return oldValue !== (c.value = c.getter(oldValue));\n }\n finally {\n activeSub = prevSub;\n c.flags &= ~4;\n purgeDeps(c);\n }\n}\nfunction updateSignal(s) {\n s.flags = 1;\n return s.currentValue !== (s.currentValue = s.pendingValue);\n}\nfunction run(e) {\n const flags = e.flags;\n if (flags & 16\n || (flags & 32\n && checkDirty(e.deps, e))) {\n ++cycle;\n e.depsTail = undefined;\n e.flags = 2 | 4;\n const prevSub = setActiveSub(e);\n try {\n e.fn();\n }\n finally {\n activeSub = prevSub;\n e.flags &= ~4;\n purgeDeps(e);\n }\n }\n else {\n e.flags = 2;\n }\n}\nfunction flush() {\n try {\n while (notifyIndex < queuedLength) {\n const effect = queued[notifyIndex];\n queued[notifyIndex++] = undefined;\n run(effect);\n }\n }\n finally {\n while (notifyIndex < queuedLength) {\n const effect = queued[notifyIndex];\n queued[notifyIndex++] = undefined;\n effect.flags |= 2 | 8;\n }\n notifyIndex = 0;\n queuedLength = 0;\n }\n}\nfunction computedOper() {\n const flags = this.flags;\n if (flags & 16\n || (flags & 32\n && (checkDirty(this.deps, this)\n || (this.flags = flags & ~32, false)))) {\n if (updateComputed(this)) {\n const subs = this.subs;\n if (subs !== undefined) {\n shallowPropagate(subs);\n }\n }\n }\n else if (!flags) {\n this.flags = 1 | 4;\n const prevSub = setActiveSub(this);\n try {\n this.value = this.getter();\n }\n finally {\n activeSub = prevSub;\n this.flags &= ~4;\n }\n }\n const sub = activeSub;\n if (sub !== undefined) {\n link(this, sub, cycle);\n }\n return this.value;\n}\nfunction signalOper(...value) {\n if (value.length) {\n if (this.pendingValue !== (this.pendingValue = value[0])) {\n this.flags = 1 | 16;\n const subs = this.subs;\n if (subs !== undefined) {\n propagate(subs);\n if (!batchDepth) {\n flush();\n }\n }\n }\n }\n else {\n if (this.flags & 16) {\n if (updateSignal(this)) {\n const subs = this.subs;\n if (subs !== undefined) {\n shallowPropagate(subs);\n }\n }\n }\n let sub = activeSub;\n while (sub !== undefined) {\n if (sub.flags & (1 | 2)) {\n link(this, sub, cycle);\n break;\n }\n sub = sub.subs?.sub;\n }\n return this.currentValue;\n }\n}\nfunction effectOper() {\n effectScopeOper.call(this);\n}\nfunction effectScopeOper() {\n this.depsTail = undefined;\n this.flags = 0;\n purgeDeps(this);\n const sub = this.subs;\n if (sub !== undefined) {\n unlink(sub);\n }\n}\nfunction purgeDeps(sub) {\n const depsTail = sub.depsTail;\n let dep = depsTail !== undefined ? depsTail.nextDep : sub.deps;\n while (dep !== undefined) {\n dep = unlink(dep, sub);\n }\n}\n","/**\n * Forma Reactive - Signal\n *\n * Fine-grained reactive primitive backed by alien-signals.\n * API: createSignal returns [getter, setter] tuple following SolidJS conventions.\n *\n * TC39 Signals equivalent: Signal.State\n */\n\nimport { signal as createRawSignal, setActiveSub } from 'alien-signals';\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport type SignalGetter<T> = () => T;\nexport type SignalSetter<T> = (v: T | ((prev: T) => T)) => void;\n\nexport interface SignalOptions<T> {\n /** Debug name — attached to getter in dev mode for devtools inspection. */\n name?: string;\n /**\n * Custom equality check. When provided, the setter will read the current\n * value and only update the signal if `equals(prev, next)` returns `false`.\n *\n * Default: none (alien-signals uses strict inequality `!==` internally).\n *\n * ```ts\n * const [pos, setPos] = createSignal(\n * { x: 0, y: 0 },\n * { equals: (a, b) => a.x === b.x && a.y === b.y },\n * );\n *\n * setPos({ x: 0, y: 0 }); // skipped — equals returns true\n * setPos({ x: 1, y: 0 }); // applied — equals returns false\n * ```\n */\n equals?: (prev: T, next: T) => boolean;\n}\n\n/**\n * Wrap a value so the setter treats it as a literal value, not a functional updater.\n *\n * When `T` is itself a function type, passing a function to the setter is\n * ambiguous -- it looks like a functional update (`prev => next`). Use\n * `value()` to disambiguate:\n *\n * ```ts\n * const [getFn, setFn] = createSignal<() => void>(() => console.log('a'));\n *\n * // BUG: interpreted as a functional update -- calls the arrow with prev\n * // setFn(() => console.log('b'));\n *\n * // Correct: wraps in a thunk so the setter stores it as-is\n * setFn(value(() => console.log('b')));\n * ```\n */\nexport function value<T>(v: T): () => T {\n return () => v;\n}\n\ntype RawSignal<T> = {\n (): T;\n (value: T): void;\n};\n\nfunction applySignalSet<T>(\n s: RawSignal<T>,\n v: T | ((prev: T) => T),\n equals?: (prev: T, next: T) => boolean,\n): void {\n if (typeof v !== 'function') {\n if (equals) {\n // Read current value without tracking\n const prevSub = setActiveSub(undefined);\n const prev = s();\n setActiveSub(prevSub);\n if (equals(prev, v)) return; // skip — values are equal\n }\n s(v);\n return;\n }\n\n // Functional update: read prev without tracking\n const prevSub = setActiveSub(undefined);\n const prev = s();\n setActiveSub(prevSub);\n const next = (v as (prev: T) => T)(prev);\n if (equals && equals(prev, next)) return; // skip — values are equal\n s(next);\n}\n\n/**\n * Create a reactive signal.\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * console.log(count()); // 0\n * setCount(1);\n * setCount(prev => prev + 1);\n * ```\n *\n * With custom equality:\n *\n * ```ts\n * const [pos, setPos] = createSignal(\n * { x: 0, y: 0 },\n * { equals: (a, b) => a.x === b.x && a.y === b.y },\n * );\n * ```\n */\nexport function createSignal<T>(initialValue: T, options?: SignalOptions<T>): [get: SignalGetter<T>, set: SignalSetter<T>] {\n const s = createRawSignal<T>(initialValue) as RawSignal<T>;\n const getter = s as unknown as SignalGetter<T>;\n const eq = options?.equals;\n const setter: SignalSetter<T> = (v: T | ((prev: T) => T)) => applySignalSet(s, v, eq);\n\n return [getter, setter];\n}\n","/**\n * Forma Reactive - Root\n *\n * Explicit reactive ownership scope. All effects created inside a root\n * are automatically disposed when the root is torn down.\n *\n * Uses alien-signals' `effectScope` under the hood for native graph-level\n * effect tracking, with a userland disposer list for non-effect cleanup\n * (e.g., event listeners, DOM references, timers).\n */\n\nimport { effectScope as rawEffectScope } from 'alien-signals';\n\n// ---------------------------------------------------------------------------\n// Root scope tracking\n// ---------------------------------------------------------------------------\n\nlet currentRoot: RootScope | null = null;\nconst rootStack: (RootScope | null)[] = [];\n\ninterface RootScope {\n /** Userland disposers (event listeners, DOM refs, timers, etc.) */\n disposers: (() => void)[];\n /** alien-signals effect scope dispose — tears down all reactive effects */\n scopeDispose: (() => void) | null;\n}\n\n/**\n * Create a reactive root scope.\n *\n * All effects created (via `createEffect`) inside the callback are tracked\n * at both the reactive graph level (via alien-signals effectScope) and the\n * userland level (via registerDisposer). The returned `dispose` function\n * tears down everything.\n *\n * ```ts\n * const dispose = createRoot(() => {\n * createEffect(() => console.log(count()));\n * createEffect(() => console.log(name()));\n * });\n * // later: dispose() stops both effects\n * ```\n */\nexport function createRoot<T>(fn: (dispose: () => void) => T): T {\n const scope: RootScope = { disposers: [], scopeDispose: null };\n\n rootStack.push(currentRoot);\n currentRoot = scope;\n\n const dispose = () => {\n // Dispose alien-signals effect scope first (reactive graph cleanup)\n if (scope.scopeDispose) {\n try { scope.scopeDispose(); } catch { /* ensure userland disposers still run */ }\n scope.scopeDispose = null;\n }\n // Then run userland disposers\n for (const d of scope.disposers) {\n try { d(); } catch { /* ensure all disposers run */ }\n }\n scope.disposers.length = 0;\n };\n\n let result: T;\n try {\n // Wrap in alien-signals effectScope for native effect tracking\n scope.scopeDispose = rawEffectScope(() => {\n result = fn(dispose);\n });\n } finally {\n currentRoot = rootStack.pop() ?? null;\n }\n\n return result!;\n}\n\n/**\n * @internal — called by createEffect to register disposers in the current root.\n */\nexport function registerDisposer(dispose: () => void): void {\n if (currentRoot) {\n currentRoot.disposers.push(dispose);\n }\n}\n\n/**\n * @internal — check if we're inside a root scope.\n */\nexport function hasActiveRoot(): boolean {\n return currentRoot !== null;\n}\n","/**\n * Forma Reactive - Effect\n *\n * Side-effectful reactive computation that auto-tracks signal dependencies.\n * Backed by alien-signals for automatic dependency tracking.\n *\n * TC39 Signals equivalent: Signal.subtle.Watcher (effect is a userland concept)\n */\n\nimport { effect as rawEffect } from 'alien-signals';\nimport { hasActiveRoot, registerDisposer } from './root.js';\nimport { setCleanupCollector } from './cleanup.js';\nimport { reportError } from './dev.js';\n\n// ---------------------------------------------------------------------------\n// Cleanup array pool — avoids allocating a new array every effect re-run\n// ---------------------------------------------------------------------------\n\nconst POOL_SIZE = 32;\nconst MAX_REENTRANT_RUNS = 100;\nconst pool: (() => void)[][] = [];\nfor (let i = 0; i < POOL_SIZE; i++) pool.push([]);\nlet poolIdx = POOL_SIZE;\n\nfunction acquireArray(): (() => void)[] {\n if (poolIdx > 0) {\n const arr = pool[--poolIdx]!;\n arr.length = 0;\n return arr;\n }\n return [];\n}\n\nfunction releaseArray(arr: (() => void)[]): void {\n arr.length = 0;\n if (poolIdx < POOL_SIZE) {\n pool[poolIdx++] = arr;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Unified cleanup runner — single function for both re-run and dispose paths\n// ---------------------------------------------------------------------------\n\nfunction runCleanup(fn: (() => void) | undefined): void {\n if (fn === undefined) return;\n try {\n fn();\n } catch (e) {\n reportError(e, 'effect cleanup');\n }\n}\n\nfunction runCleanups(bag: (() => void)[] | undefined): void {\n if (bag === undefined) return;\n for (let i = 0; i < bag.length; i++) {\n try { bag[i]!(); } catch (e) { reportError(e, 'effect cleanup'); }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactive effect that auto-tracks signal dependencies.\n *\n * The provided function runs immediately and re-runs whenever any signal it\n * reads changes. If the function returns a cleanup function, that cleanup is\n * called before each re-run and on disposal.\n *\n * Additionally, `onCleanup()` can be called inside the effect to register\n * cleanup functions composably.\n *\n * Returns a dispose function that stops the effect.\n */\n/**\n * @internal — Lightweight effect for Forma's internal DOM bindings.\n *\n * Bypasses createEffect's cleanup infrastructure (pool, collector, error\n * reporting, engine compression) since internal effects never use\n * onCleanup() or return cleanup functions. This saves ~4 function calls\n * per effect creation and per re-run.\n *\n * ONLY use for effects that:\n * 1. Never call onCleanup()\n * 2. Never return a cleanup function\n * 3. Contain simple \"read signal → write DOM\" logic\n */\nexport function internalEffect(fn: () => void): () => void {\n const dispose = rawEffect(fn);\n if (hasActiveRoot()) {\n registerDisposer(dispose);\n }\n return dispose;\n}\n\nexport function createEffect(fn: () => void | (() => void)): () => void {\n const shouldRegister = hasActiveRoot();\n\n // Most effects have zero or one cleanup. Track the single-cleanup case\n // without array allocation; only promote to pooled array when needed.\n let cleanup: (() => void) | undefined;\n let cleanupBag: (() => void)[] | undefined;\n let nextCleanup: (() => void) | undefined;\n let nextCleanupBag: (() => void)[] | undefined;\n\n const addCleanup = (cb: () => void) => {\n if (nextCleanupBag !== undefined) {\n nextCleanupBag.push(cb);\n return;\n }\n if (nextCleanup !== undefined) {\n const bag = acquireArray();\n bag.push(nextCleanup, cb);\n nextCleanup = undefined;\n nextCleanupBag = bag;\n return;\n }\n nextCleanup = cb;\n };\n\n // \"Engine Compression\" exploit: most effects never use cleanup (onCleanup()\n // or return value). After the first clean run, we know this effect is\n // \"cleanup-free\" and can skip the entire cleanup infrastructure on re-runs.\n // This saves 4 function calls per re-run: acquireArray, setCleanupCollector,\n // releaseArray, and bag inspection. Like the engine compression ratio exploit —\n // the \"rules\" say we should always prepare for cleanup, but we measure at\n // \"room temperature\" (first run) and exploit the gap.\n let skipCleanupInfra = false;\n let firstRun = true;\n let running = false;\n let rerunRequested = false;\n\n const runOnce = () => {\n // Run and clear previous cleanups (only if any exist).\n if (cleanup !== undefined) {\n runCleanup(cleanup);\n cleanup = undefined;\n }\n if (cleanupBag !== undefined) {\n runCleanups(cleanupBag);\n releaseArray(cleanupBag);\n cleanupBag = undefined;\n }\n\n // Ultra-fast path: this effect has proven it doesn't use cleanup.\n // Skip acquireArray + setCleanupCollector + bag checks + releaseArray.\n if (skipCleanupInfra) {\n try { fn(); } catch (e) { reportError(e, 'effect'); }\n return;\n }\n\n nextCleanup = undefined;\n nextCleanupBag = undefined;\n\n // Full path: install collector for onCleanup() calls.\n const prevCollector = setCleanupCollector(addCleanup);\n\n try {\n const result = fn();\n\n if (typeof result === 'function') {\n addCleanup(result as () => void);\n }\n\n // Hot path: no cleanups registered or returned — enable ultra-fast path.\n if (nextCleanup === undefined && nextCleanupBag === undefined) {\n // First clean run → enable ultra-fast path for all subsequent runs\n if (firstRun) skipCleanupInfra = true;\n return;\n }\n\n if (nextCleanupBag !== undefined) {\n cleanupBag = nextCleanupBag;\n } else {\n cleanup = nextCleanup;\n }\n } catch (e) {\n reportError(e, 'effect');\n\n if (nextCleanupBag !== undefined) {\n cleanupBag = nextCleanupBag;\n } else {\n cleanup = nextCleanup;\n }\n } finally {\n setCleanupCollector(prevCollector);\n firstRun = false;\n }\n };\n\n const safeFn = () => {\n if (running) {\n rerunRequested = true;\n return;\n }\n\n running = true;\n try {\n let reentrantRuns = 0;\n do {\n rerunRequested = false;\n runOnce();\n if (rerunRequested) {\n reentrantRuns++;\n if (reentrantRuns >= MAX_REENTRANT_RUNS) {\n reportError(\n new Error(`createEffect exceeded ${MAX_REENTRANT_RUNS} re-entrant runs`),\n 'effect',\n );\n rerunRequested = false;\n }\n }\n } while (rerunRequested);\n } finally {\n running = false;\n }\n };\n\n const dispose = rawEffect(safeFn);\n\n // Wrap dispose to also run final cleanups\n let disposed = false;\n const wrappedDispose = () => {\n if (disposed) return;\n disposed = true;\n dispose();\n if (cleanup !== undefined) {\n runCleanup(cleanup);\n cleanup = undefined;\n }\n if (cleanupBag !== undefined) {\n runCleanups(cleanupBag);\n releaseArray(cleanupBag);\n cleanupBag = undefined;\n }\n };\n\n // Register in current root scope (if any)\n if (shouldRegister) {\n registerDisposer(wrappedDispose);\n }\n\n return wrappedDispose;\n}\n","/**\n * Forma Reactive - Computed\n *\n * Lazy, cached derived value that participates in the reactive graph.\n * Backed by alien-signals for automatic dependency tracking\n * and cache invalidation.\n *\n * TC39 Signals equivalent: Signal.Computed\n */\n\nimport { computed as rawComputed } from 'alien-signals';\n\n/**\n * Create a lazy, cached computed value.\n *\n * Note: Unlike SolidJS's createComputed (which is an eager synchronous\n * side effect), this is a lazy cached derivation — equivalent to\n * SolidJS's createMemo. Both createComputed and createMemo in FormaJS\n * are identical.\n *\n * The getter receives the previous value as an argument, enabling\n * efficient diffing patterns without a separate signal:\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * const doubled = createComputed(() => count() * 2);\n * console.log(doubled()); // 0\n * setCount(5);\n * console.log(doubled()); // 10\n * ```\n *\n * With previous value (for diffing):\n *\n * ```ts\n * const changes = createComputed((prev) => {\n * const next = items();\n * if (prev) console.log(`changed from ${prev.length} to ${next.length} items`);\n * return next;\n * });\n * ```\n */\nexport function createComputed<T>(fn: (previousValue?: T) => T): () => T {\n return rawComputed(fn);\n}\n","/**\n * Forma Reactive - Batch\n *\n * Groups multiple signal updates and defers effect execution until the\n * outermost batch completes. Prevents intermediate re-renders.\n * Backed by alien-signals.\n *\n * TC39 Signals: no built-in batch — this is a userland optimization.\n */\n\nimport { startBatch, endBatch } from 'alien-signals';\n\n/**\n * Group multiple signal updates so that effects only run once after all\n * updates have been applied.\n *\n * ```ts\n * batch(() => {\n * setA(1);\n * setB(2);\n * // effects that depend on A and B won't run yet\n * });\n * // effects run here, once\n * ```\n *\n * Batches are nestable — only the outermost batch triggers the flush.\n */\nexport function batch(fn: () => void): void {\n startBatch();\n try {\n fn();\n } finally {\n endBatch();\n }\n}\n","/**\n * Forma DOM - List\n *\n * Keyed list reconciliation with Longest Increasing Subsequence (LIS).\n * The LIS tells us the maximum set of DOM nodes that can stay in place;\n * only the remaining nodes need to be moved. This minimises DOM operations\n * to exactly `n - LIS_length` moves — provably optimal.\n *\n * Algorithm used by ivi, Inferno, and (with variations) Solid, Vue 3, Svelte.\n *\n * Uses comment-node markers instead of a wrapper <div>, so the list can be\n * placed inside <table>, <ul>, <select>, etc. without breaking semantics.\n *\n * Total module budget: <2KB minified.\n */\n\nimport { createSignal, internalEffect, untrack, __DEV__ } from '../reactive';\nimport { hydrating } from './hydrate.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ReconcileResult<T> {\n nodes: Node[];\n items: T[];\n}\n\nexport interface ListTransitionHooks {\n onInsert?: (node: Node) => void;\n onBeforeRemove?: (node: Node, done: () => void) => void;\n}\n\ninterface CachedItem<T> {\n element: HTMLElement;\n item: T;\n getIndex: () => number;\n setIndex: (v: number) => void;\n}\n\nexport interface CreateListOptions {\n /**\n * How to handle same-key items whose object identity changed.\n * - 'none' (default): keep the existing row node for maximum throughput.\n * - 'rerender': re-render changed rows and patch static row DOM in place.\n */\n updateOnItemChange?: 'none' | 'rerender';\n}\n\n// ---------------------------------------------------------------------------\n// LIS — O(n log n) via patience sorting + binary search\n// ---------------------------------------------------------------------------\n\n/**\n * Find the longest increasing subsequence.\n * Returns indices into the input array.\n * O(n log n) time, O(n) space.\n */\nexport function longestIncreasingSubsequence(arr: number[]): number[] {\n const n = arr.length;\n if (n === 0) return [];\n\n // Pre-allocate typed arrays — avoids V8 array growth overhead on push\n const tails = new Int32Array(n);\n const tailIndices = new Int32Array(n);\n const predecessor = new Int32Array(n).fill(-1);\n let tailsLen = 0;\n\n for (let i = 0; i < n; i++) {\n const val = arr[i]!;\n\n // Binary search: leftmost tail >= val\n let lo = 0, hi = tailsLen;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (tails[mid]! < val) lo = mid + 1;\n else hi = mid;\n }\n\n tails[lo] = val;\n tailIndices[lo] = i;\n if (lo > 0) predecessor[i] = tailIndices[lo - 1]!;\n if (lo >= tailsLen) tailsLen++;\n }\n\n // Reconstruct — return plain array since callers expect number[]\n const result = new Array<number>(tailsLen);\n let idx = tailIndices[tailsLen - 1]!;\n for (let i = tailsLen - 1; i >= 0; i--) {\n result[i] = idx;\n idx = predecessor[idx]!;\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// reconcileList — low-level keyed reconciler\n// ---------------------------------------------------------------------------\n\n/** Below this threshold, use flat array scan instead of Map for better cache locality. */\nconst SMALL_LIST_THRESHOLD = 32;\nconst ABORT_SYM = Symbol.for('forma-abort');\nconst CACHE_SYM = Symbol.for('forma-attr-cache');\nconst DYNAMIC_CHILD_SYM = Symbol.for('forma-dynamic-child');\n\nfunction canPatchStaticElement(target: Node, source: Node): target is HTMLElement {\n return target instanceof HTMLElement\n && source instanceof HTMLElement\n && target.tagName === source.tagName\n && !(target as any)[ABORT_SYM]\n && !(target as any)[CACHE_SYM]\n && !(target as any)[DYNAMIC_CHILD_SYM]\n && !(source as any)[ABORT_SYM]\n && !(source as any)[CACHE_SYM]\n && !(source as any)[DYNAMIC_CHILD_SYM];\n}\n\nfunction patchStaticElement(target: HTMLElement, source: HTMLElement): void {\n // Sync attributes (events/reactive bindings are excluded by canPatchStaticElement).\n const sourceAttrNames = new Set<string>();\n for (const attr of Array.from(source.attributes)) {\n sourceAttrNames.add(attr.name);\n if (target.getAttribute(attr.name) !== attr.value) {\n target.setAttribute(attr.name, attr.value);\n }\n }\n for (const attr of Array.from(target.attributes)) {\n if (!sourceAttrNames.has(attr.name)) {\n target.removeAttribute(attr.name);\n }\n }\n\n // Move freshly rendered children into the existing keyed node.\n target.replaceChildren(...Array.from(source.childNodes));\n}\n\n/**\n * Small-list reconciler: uses flat arrays + indexOf instead of Map/Set.\n * For < 32 items, linear scan is faster than hash computation overhead.\n */\nfunction reconcileSmall<T>(\n parent: Node,\n oldItems: T[],\n newItems: T[],\n oldNodes: Node[],\n keyFn: (item: T) => string | number,\n createFn: (item: T) => Node,\n updateFn: (node: Node, item: T) => void,\n beforeNode?: Node | null,\n hooks?: ListTransitionHooks,\n): ReconcileResult<T> {\n const oldLen = oldItems.length;\n const newLen = newItems.length;\n\n // Build flat arrays for old keys/nodes — better cache locality than Map\n const oldKeys: (string | number)[] = new Array(oldLen);\n for (let i = 0; i < oldLen; i++) {\n oldKeys[i] = keyFn(oldItems[i]!);\n }\n\n // Classify each new item: find matching old index via linear scan\n const oldIndices = new Array<number>(newLen);\n const oldUsed = new Uint8Array(oldLen); // 0 = unused, 1 = used\n\n for (let i = 0; i < newLen; i++) {\n const key = keyFn(newItems[i]!);\n let found = -1;\n for (let j = 0; j < oldLen; j++) {\n if (!oldUsed[j] && oldKeys[j] === key) {\n found = j;\n oldUsed[j] = 1;\n break;\n }\n }\n oldIndices[i] = found;\n }\n\n // Remove old items not reused\n for (let i = 0; i < oldLen; i++) {\n if (!oldUsed[i]) {\n if (hooks?.onBeforeRemove) {\n const node = oldNodes[i]!;\n hooks.onBeforeRemove(node, () => {\n if (node.parentNode) node.parentNode.removeChild(node);\n });\n } else {\n parent.removeChild(oldNodes[i]!);\n }\n }\n }\n\n // Fast path: same keys, same order -> just update, 0 DOM moves\n if (oldLen === newLen) {\n let allSameOrder = true;\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== i) {\n allSameOrder = false;\n break;\n }\n }\n if (allSameOrder) {\n const nodes = new Array<Node>(newLen);\n for (let i = 0; i < newLen; i++) {\n const node = oldNodes[i]!;\n updateFn(node, newItems[i]!);\n nodes[i] = node;\n }\n return { nodes, items: newItems };\n }\n }\n\n // LIS for minimum moves (still needed even for small lists)\n const reusedIndices: number[] = [];\n const reusedPositions: number[] = [];\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== -1) {\n reusedIndices.push(oldIndices[i]!);\n reusedPositions.push(i);\n }\n }\n\n const lisOfReused = longestIncreasingSubsequence(reusedIndices);\n // Use Uint8Array as a bitmap instead of Set for small lists\n const lisFlags = new Uint8Array(newLen);\n for (const li of lisOfReused) {\n lisFlags[reusedPositions[li]!] = 1;\n }\n\n // Build result: walk right-to-left for stable insertBefore targets\n const newNodes = new Array<Node>(newLen);\n let nextSibling: Node | null = beforeNode ?? null;\n\n for (let i = newLen - 1; i >= 0; i--) {\n let node: Node;\n let isNew = false;\n\n if (oldIndices[i] === -1) {\n node = createFn(newItems[i]!);\n isNew = true;\n } else {\n node = oldNodes[oldIndices[i]!]!;\n updateFn(node, newItems[i]!);\n\n if (lisFlags[i]) {\n newNodes[i] = node;\n nextSibling = node;\n continue;\n }\n }\n\n if (nextSibling) {\n parent.insertBefore(node, nextSibling);\n } else {\n parent.appendChild(node);\n }\n\n if (isNew) hooks?.onInsert?.(node);\n\n newNodes[i] = node;\n nextSibling = node;\n }\n\n return { nodes: newNodes, items: newItems };\n}\n\n/**\n * Reconcile a DOM parent's children to match a new array of items.\n * Uses keyed reconciliation with LIS for minimum DOM operations.\n *\n * For small lists (< 32 items), uses a flat array scan path that avoids\n * Map/Set hash overhead and provides better cache locality.\n *\n * @param parent - The container DOM element\n * @param oldItems - Previous array (from last reconciliation)\n * @param newItems - New array to render\n * @param oldNodes - Previous DOM nodes array\n * @param keyFn - Extracts a unique key from each item\n * @param createFn - Creates a new DOM node for an item\n * @param updateFn - Updates an existing DOM node with new item data\n * @param beforeNode - Optional boundary marker. When provided, new nodes are\n * inserted before this node instead of appended to parent.\n * This allows the reconciler to operate within a range\n * delimited by comment markers.\n * @returns Object with new nodes array and items array for next call\n */\nexport function reconcileList<T>(\n parent: Node,\n oldItems: T[],\n newItems: T[],\n oldNodes: Node[],\n keyFn: (item: T) => string | number,\n createFn: (item: T) => Node,\n updateFn: (node: Node, item: T) => void,\n beforeNode?: Node | null,\n hooks?: ListTransitionHooks,\n): ReconcileResult<T> {\n const oldLen = oldItems.length;\n const newLen = newItems.length;\n\n // --- Trivial: new is empty -> remove all ---\n if (newLen === 0) {\n for (let i = 0; i < oldLen; i++) {\n if (hooks?.onBeforeRemove) {\n const node = oldNodes[i]!;\n hooks.onBeforeRemove(node, () => {\n if (node.parentNode) node.parentNode.removeChild(node);\n });\n } else {\n parent.removeChild(oldNodes[i]!);\n }\n }\n return { nodes: [], items: [] };\n }\n\n // --- Trivial: old is empty -> create all ---\n if (oldLen === 0) {\n const nodes = new Array<Node>(newLen);\n for (let i = 0; i < newLen; i++) {\n const node = createFn(newItems[i]!);\n if (beforeNode) {\n parent.insertBefore(node, beforeNode);\n } else {\n parent.appendChild(node);\n }\n hooks?.onInsert?.(node);\n nodes[i] = node;\n }\n return { nodes, items: newItems };\n }\n\n // --- Small list path: flat array scan, no Map/Set overhead ---\n if (oldLen < SMALL_LIST_THRESHOLD) {\n return reconcileSmall(parent, oldItems, newItems, oldNodes, keyFn, createFn, updateFn, beforeNode, hooks);\n }\n\n // --- Large list path: Map-based approach ---\n const oldKeyMap = new Map<string | number, number>();\n for (let i = 0; i < oldLen; i++) {\n oldKeyMap.set(keyFn(oldItems[i]!), i);\n }\n\n // --- Classify each new item: reuse or create ---\n // Use Uint8Array bitmap instead of Set for O(1) lookup without hash overhead\n const oldIndices = new Array<number>(newLen); // -1 means new item\n const oldUsed = new Uint8Array(oldLen);\n\n for (let i = 0; i < newLen; i++) {\n const key = keyFn(newItems[i]!);\n const oldIdx = oldKeyMap.get(key);\n if (oldIdx !== undefined) {\n oldIndices[i] = oldIdx;\n oldUsed[oldIdx] = 1;\n } else {\n oldIndices[i] = -1;\n }\n }\n\n // --- Remove old items not in new array ---\n for (let i = 0; i < oldLen; i++) {\n if (!oldUsed[i]) {\n if (hooks?.onBeforeRemove) {\n const node = oldNodes[i]!;\n hooks.onBeforeRemove(node, () => {\n if (node.parentNode) node.parentNode.removeChild(node);\n });\n } else {\n parent.removeChild(oldNodes[i]!);\n }\n }\n }\n\n // --- Fast path: same keys, same order -> just update, 0 DOM moves ---\n if (oldLen === newLen) {\n let allSameOrder = true;\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== i) {\n allSameOrder = false;\n break;\n }\n }\n if (allSameOrder) {\n const nodes = new Array<Node>(newLen);\n for (let i = 0; i < newLen; i++) {\n const node = oldNodes[i]!;\n updateFn(node, newItems[i]!);\n nodes[i] = node;\n }\n return { nodes, items: newItems };\n }\n }\n\n // --- Find LIS of old indices (reused items only) ---\n const reusedIndices: number[] = [];\n const reusedPositions: number[] = []; // position in new array\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== -1) {\n reusedIndices.push(oldIndices[i]!);\n reusedPositions.push(i);\n }\n }\n\n const lisOfReused = longestIncreasingSubsequence(reusedIndices);\n // Use Uint8Array bitmap instead of Set for O(1) lookup without hash overhead\n const lisFlags = new Uint8Array(newLen);\n for (const li of lisOfReused) {\n lisFlags[reusedPositions[li]!] = 1;\n }\n\n // --- Build result: walk right-to-left for stable insertBefore targets ---\n const newNodes = new Array<Node>(newLen);\n let nextSibling: Node | null = beforeNode ?? null;\n\n for (let i = newLen - 1; i >= 0; i--) {\n let node: Node;\n let isNew = false;\n\n if (oldIndices[i] === -1) {\n // NEW: create and insert\n node = createFn(newItems[i]!);\n isNew = true;\n } else {\n // REUSE: update content\n node = oldNodes[oldIndices[i]!]!;\n updateFn(node, newItems[i]!);\n\n if (lisFlags[i]) {\n // LIS item: already in correct relative position, don't move\n newNodes[i] = node;\n nextSibling = node;\n continue;\n }\n }\n\n // Insert/move into position\n if (nextSibling) {\n parent.insertBefore(node, nextSibling);\n } else {\n parent.appendChild(node);\n }\n\n if (isNew) hooks?.onInsert?.(node);\n\n newNodes[i] = node;\n nextSibling = node;\n }\n\n return { nodes: newNodes, items: newItems };\n}\n\n// ---------------------------------------------------------------------------\n// createList — high-level reactive API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactively-bound list of DOM elements with keyed reconciliation.\n *\n * Returns a `DocumentFragment` containing two comment markers\n * (`<!--forma-list-start-->` and `<!--forma-list-end-->`) that delimit the\n * list's range in the DOM. All managed elements live between these markers.\n *\n * This avoids a wrapper `<div>` which would break `<table>`, `<ul>`,\n * `<select>` semantics and pollute the DOM.\n *\n * When the `items` signal changes, only the minimal set of DOM mutations is\n * performed using the LIS algorithm:\n * - New keys: create elements via `renderFn`\n * - Removed keys: remove elements from DOM\n * - Moved keys: reorder elements using minimum moves (n - LIS)\n * - Same keys: keep row nodes and update index signals\n * (or re-render row content when `updateOnItemChange: 'rerender'`)\n *\n * @param items Signal getter returning the current array of items.\n * @param keyFn Extracts a unique key from each item.\n * @param renderFn Renders a single item. Receives the item and a reactive index getter.\n * @returns A DocumentFragment to insert into the DOM. The fragment includes\n * start/end comment markers and any initial list items.\n *\n * ```ts\n * const frag = createList(\n * todos,\n * (t) => t.id,\n * (todo, index) => h('li', null, () => `${index() + 1}. ${todo.text}`),\n * );\n * container.appendChild(frag);\n * ```\n */\nexport function createList<T>(\n items: () => T[],\n keyFn: (item: T) => string | number,\n renderFn: (item: T, index: () => number) => HTMLElement,\n options?: CreateListOptions,\n): DocumentFragment {\n if (hydrating) {\n return { type: 'list', items, keyFn, renderFn, options } as unknown as DocumentFragment;\n }\n\n const startMarker = document.createComment('forma-list-start');\n const endMarker = document.createComment('forma-list-end');\n\n const fragment = document.createDocumentFragment();\n fragment.appendChild(startMarker);\n fragment.appendChild(endMarker);\n\n // Cache: key -> { element, item, setIndex }\n let cache = new Map<string | number, CachedItem<T>>();\n let currentNodes: Node[] = [];\n let currentItems: T[] = [];\n const updateOnItemChange = options?.updateOnItemChange ?? 'none';\n\n internalEffect(() => {\n const newItems = items();\n\n // The parent is discovered lazily: once the fragment has been inserted\n // into the live DOM the markers have a parentNode.\n const parent = startMarker.parentNode;\n if (!parent) {\n // Markers are not yet in the DOM — nothing to reconcile.\n // This can happen if the effect fires synchronously before mount.\n return;\n }\n\n // Edge case: non-array\n if (!Array.isArray(newItems)) {\n if (__DEV__) {\n console.warn('[forma] createList: value is not an array, treating as empty');\n }\n // Remove all nodes between the markers\n for (const node of currentNodes) {\n if (node.parentNode === parent) parent.removeChild(node);\n }\n cache = new Map();\n currentNodes = [];\n currentItems = [];\n return;\n }\n\n // Filter nullish items — avoid array allocation when no nulls found (common case)\n let cleanItems: T[] = newItems;\n for (let i = 0; i < newItems.length; i++) {\n if (newItems[i] == null) {\n cleanItems = newItems.filter(item => item != null);\n break;\n }\n }\n\n // Dev-mode duplicate key detection\n if (__DEV__) {\n const seen = new Set<string | number>();\n for (const item of cleanItems) {\n const key = keyFn(item);\n if (seen.has(key)) {\n console.warn('[forma] createList: duplicate key detected:', key);\n }\n seen.add(key);\n }\n }\n\n const updateRow = updateOnItemChange === 'rerender'\n ? (node: Node, item: T): void => {\n const key = keyFn(item);\n const cached = cache.get(key);\n if (!cached) return;\n if (cached.item === item) return;\n cached.item = item;\n\n if (!(node instanceof HTMLElement)) return;\n if ((node as any)[ABORT_SYM] || (node as any)[CACHE_SYM] || (node as any)[DYNAMIC_CHILD_SYM]) {\n return;\n }\n\n const next = untrack(() => renderFn(item, cached.getIndex));\n if (canPatchStaticElement(node, next)) {\n patchStaticElement(node, next);\n cached.element = node;\n }\n }\n : (_node: Node, item: T): void => {\n const key = keyFn(item);\n const cached = cache.get(key);\n if (cached) cached.item = item;\n };\n\n const result = reconcileList<T>(\n parent,\n currentItems,\n cleanItems,\n currentNodes,\n keyFn,\n // createFn: create element + cache entry\n (item) => {\n const key = keyFn(item);\n const [getIndex, setIndex] = createSignal(0);\n // Prevent child effects created during render from being nested under\n // the reconciler effect, which can stall their updates on reorders.\n const element = untrack(() => renderFn(item, getIndex));\n cache.set(key, { element, item, getIndex, setIndex });\n return element;\n },\n updateRow,\n // beforeNode: insert items before the end marker\n endMarker,\n );\n\n // Rebuild cache + update index signals in a single pass.\n // Avoids .map() array allocation + Set construction from the previous approach.\n const newCache = new Map<string | number, CachedItem<T>>();\n for (let i = 0; i < cleanItems.length; i++) {\n const key = keyFn(cleanItems[i]!);\n const cached = cache.get(key);\n if (cached) {\n cached.setIndex(i);\n newCache.set(key, cached);\n }\n }\n cache = newCache;\n\n currentNodes = result.nodes;\n currentItems = result.items;\n });\n\n return fragment;\n}\n","/**\n * Forma Reconciler — DOM diffing and patching engine.\n *\n * Replaces morphdom with a purpose-built reconciler that understands\n * Forma's directive system (data-forma-state, data-list, data-if, etc.).\n *\n * Usage:\n * const rec = createReconciler({ mountScope, unmountScope, ... });\n * rec(container, htmlString);\n *\n * Scope modes for data-forma-state elements matched by data-forma-id:\n * PRESERVE — same data-module + same state shape → patch attrs, keep bindings\n * RESET — same data-module + different state shape → unmount, patch, remount\n * REPLACE — different data-module → remove old, insert new, mount fresh\n */\n\n// ── Types ─────────────────────────────────────────────────────────────\n\nexport interface ReconcilerConfig {\n mountScope: (el: Element) => void;\n unmountScope: (el: Element) => void;\n disconnectObserver: () => void;\n reconnectObserver: () => void;\n batch: (fn: () => void) => void;\n}\n\ntype ScopeMode = 'PRESERVE' | 'RESET' | 'REPLACE';\n\n// ── Attribute helpers ─────────────────────────────────────────────────\n\n/** Check if an element has data-bind:X targeting a specific attribute */\nfunction getBindTargets(el: Element): Set<string> {\n const targets = new Set<string>();\n const attrs = el.attributes;\n for (let i = 0; i < attrs.length; i++) {\n const name = attrs[i]!.name;\n if (name.startsWith('data-bind:')) {\n targets.add(name.slice(10));\n }\n }\n return targets;\n}\n\n/** Check if an element owns its subtree (data-list or data-if) */\nfunction ownsSubtree(el: Element): boolean {\n return el.hasAttribute('data-list') || el.hasAttribute('data-if');\n}\n\n// ── State shape comparison ────────────────────────────────────────────\n\nfunction getStateKeys(json: string): string[] {\n try {\n const obj = JSON.parse(json);\n return Object.keys(obj).sort();\n } catch {\n return [];\n }\n}\n\nfunction sameShape(keysA: string[], keysB: string[]): boolean {\n if (keysA.length !== keysB.length) return false;\n for (let i = 0; i < keysA.length; i++) {\n if (keysA[i] !== keysB[i]) return false;\n }\n return true;\n}\n\n// ── Scope mode determination ──────────────────────────────────────────\n\nfunction determineScopeMode(liveEl: Element, newEl: Element): ScopeMode {\n const liveModule = liveEl.getAttribute('data-module');\n const newModule = newEl.getAttribute('data-module');\n\n if (liveModule !== newModule) return 'REPLACE';\n\n // Compare state shape: use __formaInitialState (set at mount time) for the\n // live element, and the raw attribute for the new element.\n const liveInitialState = (liveEl as any).__formaInitialState as string | undefined;\n const liveStateJSON = liveInitialState ?? liveEl.getAttribute('data-forma-state') ?? '{}';\n const newStateJSON = newEl.getAttribute('data-forma-state') ?? '{}';\n\n const liveKeys = getStateKeys(liveStateJSON);\n const newKeys = getStateKeys(newStateJSON);\n\n if (sameShape(liveKeys, newKeys)) return 'PRESERVE';\n return 'RESET';\n}\n\n// ── HTML parsing ──────────────────────────────────────────────────────\n\n/** Reused template element — avoids creating a new one per reconcile call. */\nlet _parseTemplate: HTMLTemplateElement | null = null;\n\nfunction parseHTML(html: string): DocumentFragment {\n if (!_parseTemplate) _parseTemplate = document.createElement('template');\n _parseTemplate.innerHTML = html;\n // content is consumed (moved) by the caller, so template is empty after\n return _parseTemplate.content;\n}\n\n// ── Attribute patching ────────────────────────────────────────────────\n\nfunction patchAttributes(liveEl: Element, newEl: Element): void {\n const bindTargets = getBindTargets(liveEl);\n const hasDataShow = liveEl.hasAttribute('data-show');\n const hasDataModel = liveEl.hasAttribute('data-model');\n\n // Check for class directives without Array.from allocation\n let liveHasClassDirectives = false;\n const liveAttrs = liveEl.attributes;\n for (let i = 0; i < liveAttrs.length; i++) {\n if (liveAttrs[i]!.name.startsWith('data-class:')) {\n liveHasClassDirectives = true;\n break;\n }\n }\n\n // Set/update attributes from newEl\n const newAttrs = newEl.attributes;\n for (let i = 0; i < newAttrs.length; i++) {\n const attr = newAttrs[i]!;\n // Skip directive-owned attributes\n if (attr.name === 'style' && hasDataShow) continue;\n if (attr.name === 'class' && liveHasClassDirectives) continue;\n if ((attr.name === 'value' || attr.name === 'checked') && hasDataModel) continue;\n if (bindTargets.has(attr.name)) continue;\n\n const liveVal = liveEl.getAttribute(attr.name);\n if (liveVal !== attr.value) {\n liveEl.setAttribute(attr.name, attr.value);\n }\n }\n\n // Remove attributes that are no longer present in newEl\n // Iterate backwards since removeAttribute shifts indices\n for (let i = liveAttrs.length - 1; i >= 0; i--) {\n const attr = liveAttrs[i]!;\n if (!newEl.hasAttribute(attr.name)) {\n if (attr.name === 'style' && hasDataShow) continue;\n if (attr.name === 'class' && liveHasClassDirectives) continue;\n if ((attr.name === 'value' || attr.name === 'checked') && hasDataModel) continue;\n if (bindTargets.has(attr.name)) continue;\n\n liveEl.removeAttribute(attr.name);\n }\n }\n}\n\n// ── Text node patching ────────────────────────────────────────────────\n\nfunction patchTextNodes(liveEl: Element, newEl: Element): void {\n // data-text directive owns this element's text content — don't overwrite\n if (liveEl.hasAttribute('data-text')) return;\n\n const liveTexts: Text[] = [];\n const newTexts: { node: Text; index: number }[] = [];\n\n for (const child of Array.from(liveEl.childNodes)) {\n if (child.nodeType === Node.TEXT_NODE) liveTexts.push(child as Text);\n }\n for (let i = 0; i < newEl.childNodes.length; i++) {\n const child = newEl.childNodes[i];\n if (child.nodeType === Node.TEXT_NODE) newTexts.push({ node: child as Text, index: i });\n }\n\n // Fast path: same count, just patch content\n if (liveTexts.length === newTexts.length) {\n for (let i = 0; i < liveTexts.length; i++) {\n if (liveTexts[i].textContent !== newTexts[i].node.textContent) {\n liveTexts[i].textContent = newTexts[i].node.textContent;\n }\n }\n return;\n }\n\n // Count mismatch: reuse live text nodes in order, insert/remove as needed\n const usedLive = new Set<Text>();\n let liveIdx = 0;\n\n for (const { node: newText, index: newChildIdx } of newTexts) {\n if (liveIdx < liveTexts.length) {\n // Reuse existing text node\n const liveText = liveTexts[liveIdx]!;\n liveIdx++;\n usedLive.add(liveText);\n if (liveText.textContent !== newText.textContent) {\n liveText.textContent = newText.textContent;\n }\n } else {\n // Insert new text node at correct position\n const ref = findTextInsertionRef(liveEl, newEl, newChildIdx);\n liveEl.insertBefore(document.createTextNode(newText.textContent ?? ''), ref);\n }\n }\n\n // Remove unused live text nodes\n for (const lt of liveTexts) {\n if (!usedLive.has(lt) && lt.parentNode === liveEl) {\n liveEl.removeChild(lt);\n }\n }\n}\n\n/** Find the insertion reference node for a text node being inserted into liveEl. */\nfunction findTextInsertionRef(liveEl: Element, newEl: Element, newIdx: number): Node | null {\n for (let j = newIdx + 1; j < newEl.childNodes.length; j++) {\n const sibling = newEl.childNodes[j];\n if (sibling.nodeType === Node.ELEMENT_NODE) {\n const key = (sibling as Element).getAttribute('data-forma-id');\n if (key) {\n const match = liveEl.querySelector(`[data-forma-id=\"${CSS.escape(key)}\"]`);\n if (match && match.parentElement === liveEl) return match;\n }\n }\n }\n return null;\n}\n\n// ── Recursive element diffing ─────────────────────────────────────────\n\nfunction diffChildren(\n liveParent: Element,\n newParent: Element,\n config: ReconcilerConfig,\n): void {\n // Skip directive-owned subtrees\n if (ownsSubtree(liveParent)) return;\n\n // Patch text nodes at this level\n patchTextNodes(liveParent, newParent);\n\n // Collect child elements (ignore text nodes for structural diff)\n const liveChildren = Array.from(liveParent.children);\n const newChildren = Array.from(newParent.children);\n\n // Build keyed maps for data-forma-id elements\n const liveKeyed = new Map<string, Element>();\n const liveUnkeyed: Element[] = [];\n for (const child of liveChildren) {\n if (child.hasAttribute('data-forma-leaving')) continue;\n const key = child.getAttribute('data-forma-id');\n if (key) {\n liveKeyed.set(key, child);\n } else {\n liveUnkeyed.push(child);\n }\n }\n\n let unkeyedIdx = 0;\n\n // Walk new children in order\n const usedLiveElements = new Set<Element>();\n\n for (const newChild of newChildren) {\n const key = newChild.getAttribute('data-forma-id');\n let liveMatch: Element | undefined;\n\n if (key) {\n liveMatch = liveKeyed.get(key);\n } else {\n // Match unkeyed elements by position and tag\n while (unkeyedIdx < liveUnkeyed.length) {\n const candidate = liveUnkeyed[unkeyedIdx];\n unkeyedIdx++;\n if (candidate.tagName === newChild.tagName && !usedLiveElements.has(candidate)) {\n liveMatch = candidate;\n break;\n }\n }\n }\n\n if (liveMatch) {\n usedLiveElements.add(liveMatch);\n\n // Check if this is a data-forma-state scope element\n if (liveMatch.hasAttribute('data-forma-state') && newChild.hasAttribute('data-forma-state')) {\n const mode = determineScopeMode(liveMatch, newChild);\n\n switch (mode) {\n case 'PRESERVE':\n // Patch attributes only, keep reactive bindings alive\n patchAttributes(liveMatch, newChild);\n // Recurse into non-directive-owned children\n diffChildren(liveMatch, newChild, config);\n break;\n\n case 'RESET':\n // Unmount old scope, patch DOM, mount fresh\n config.unmountScope(liveMatch);\n patchAttributes(liveMatch, newChild);\n // Replace inner content\n replaceInnerContent(liveMatch, newChild);\n config.mountScope(liveMatch);\n break;\n\n case 'REPLACE': {\n // Full element swap\n config.unmountScope(liveMatch);\n const replacement = newChild.cloneNode(true) as Element;\n liveParent.replaceChild(replacement, liveMatch);\n config.mountScope(replacement);\n usedLiveElements.delete(liveMatch);\n liveMatch = replacement;\n usedLiveElements.add(replacement);\n break;\n }\n }\n } else {\n // Non-scope element: patch attrs and recurse\n patchAttributes(liveMatch, newChild);\n diffChildren(liveMatch, newChild, config);\n }\n\n // Ensure element is in the correct position\n // Find where it should be relative to previousSibling\n ensurePosition(liveParent, liveMatch, newChild, newChildren);\n } else {\n // New element — insert it\n const clone = newChild.cloneNode(true) as Element;\n // Find insertion point\n const insertionRef = findInsertionPoint(liveParent, newChild, newChildren);\n liveParent.insertBefore(clone, insertionRef);\n usedLiveElements.add(clone);\n\n // Mount any scopes in the new element\n if (clone.hasAttribute('data-forma-state')) {\n config.mountScope(clone);\n }\n const nestedScopes = clone.querySelectorAll('[data-forma-state]');\n for (const nested of Array.from(nestedScopes)) {\n config.mountScope(nested);\n }\n }\n }\n\n // Remove live children that are no longer in new children\n for (const child of liveChildren) {\n if (!usedLiveElements.has(child)) {\n // Guard: element may already be detached (e.g. after REPLACE)\n if (child.parentElement !== liveParent) continue;\n // Guard: element is mid-leave transition — its transition will remove it\n if (child.hasAttribute('data-forma-leaving')) continue;\n // Unmount any scopes\n if (child.hasAttribute('data-forma-state')) {\n config.unmountScope(child);\n }\n const nestedScopes = child.querySelectorAll('[data-forma-state]');\n for (const nested of Array.from(nestedScopes)) {\n config.unmountScope(nested);\n }\n liveParent.removeChild(child);\n }\n }\n}\n\n/** Replace inner content of live element with content from new element */\nfunction replaceInnerContent(liveEl: Element, newEl: Element): void {\n // Remove all children\n while (liveEl.firstChild) {\n liveEl.removeChild(liveEl.firstChild);\n }\n // Clone and append all children from new element\n for (const child of Array.from(newEl.childNodes)) {\n liveEl.appendChild(child.cloneNode(true));\n }\n}\n\n/** Ensure a live element is at the correct position */\nfunction ensurePosition(\n parent: Element,\n liveEl: Element,\n _newEl: Element,\n newChildren: Element[],\n): void {\n const newIdx = newChildren.indexOf(_newEl);\n const liveChildElements = Array.from(parent.children);\n const currentIdx = liveChildElements.indexOf(liveEl);\n\n if (currentIdx !== newIdx) {\n // Find the element that should come after this one\n const nextNewChild = newChildren[newIdx + 1];\n if (nextNewChild) {\n const nextKey = nextNewChild.getAttribute('data-forma-id');\n if (nextKey) {\n // Find this element in live DOM\n const nextLive = parent.querySelector(`[data-forma-id=\"${CSS.escape(nextKey)}\"]`);\n if (nextLive && nextLive.parentElement === parent) {\n parent.insertBefore(liveEl, nextLive);\n return;\n }\n }\n }\n // Append to end\n parent.appendChild(liveEl);\n }\n}\n\n/** Find the correct insertion point for a new element */\nfunction findInsertionPoint(\n parent: Element,\n newChild: Element,\n newChildren: Element[],\n): Node | null {\n const newIdx = newChildren.indexOf(newChild);\n\n // Look for the next sibling in the new children that exists in the live DOM\n for (let i = newIdx + 1; i < newChildren.length; i++) {\n const key = newChildren[i].getAttribute('data-forma-id');\n if (key) {\n const existing = parent.querySelector(`[data-forma-id=\"${CSS.escape(key)}\"]`);\n if (existing && existing.parentElement === parent) {\n return existing;\n }\n }\n }\n\n return null; // Append to end\n}\n\n// ── Factory ───────────────────────────────────────────────────────────\n\nexport function createReconciler(config: ReconcilerConfig) {\n /** Last HTML string that was successfully reconciled into this container.\n * Used to skip reconciliation when the HTML hasn't changed. */\n let _lastHtml = '';\n\n return function reconcile(container: Element, html: string): void {\n const trimmed = html.trim();\n if (!trimmed) return;\n\n // Fast path: skip reconciliation entirely when HTML is identical\n if (trimmed === _lastHtml && container.hasChildNodes()) return;\n _lastHtml = trimmed;\n\n // Disconnect observer to prevent double-mount during patching\n config.disconnectObserver();\n\n try {\n // ── Fast path: empty container ──\n if (!container.hasChildNodes() || container.children.length === 0) {\n container.innerHTML = trimmed;\n\n // Mount all data-forma-state scopes\n config.batch(() => {\n const scopes = container.querySelectorAll('[data-forma-state]');\n for (const scope of Array.from(scopes)) {\n config.mountScope(scope);\n }\n });\n\n return;\n }\n\n // ── Parse new HTML into a DocumentFragment ──\n const fragment = parseHTML(trimmed);\n const templateContainer = document.createElement('div');\n templateContainer.appendChild(fragment);\n\n // ── Full-replacement fast path ──\n // When there is zero data-forma-id overlap between live and new children,\n // skip the diff entirely — dispose all live scopes, innerHTML, mount fresh.\n // This handles module-switch scenarios cleanly and avoids issues with\n // corrupted HTML confusing the diff.\n const liveKeys = new Set<string>();\n for (const child of Array.from(container.children)) {\n if (child.hasAttribute('data-forma-leaving')) continue;\n const key = child.getAttribute('data-forma-id');\n if (key) liveKeys.add(key);\n }\n let hasOverlap = false;\n if (liveKeys.size > 0) {\n for (const child of Array.from(templateContainer.children)) {\n const key = child.getAttribute('data-forma-id');\n if (key && liveKeys.has(key)) { hasOverlap = true; break; }\n }\n }\n\n if (liveKeys.size > 0 && !hasOverlap) {\n // Full replacement: unmount all live scopes, replace content, mount new\n config.batch(() => {\n const liveScopes = container.querySelectorAll('[data-forma-state]');\n for (const scope of Array.from(liveScopes)) {\n config.unmountScope(scope);\n }\n container.innerHTML = trimmed;\n const newScopes = container.querySelectorAll('[data-forma-state]');\n for (const scope of Array.from(newScopes)) {\n config.mountScope(scope);\n }\n });\n return;\n }\n\n // ── Diff and patch ──\n config.batch(() => {\n diffChildren(container, templateContainer, config);\n });\n } finally {\n // Always reconnect observer, even if an error occurred\n config.reconnectObserver();\n }\n };\n}\n"],"mappings":"8cAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,2BAAAE,GAAA,qBAAAC,GAAA,mBAAAC,GAAA,mBAAAC,GAAA,cAAAC,GAAA,sBAAAC,GAAA,gBAAAC,GAAA,UAAAC,GAAA,cAAAC,GAAA,eAAAC,GAAA,aAAAC,GAAA,mBAAAC,GAAA,oBAAAC,GAAA,kBAAAC,GAAA,kBAAAC,GAAA,sBAAAC,GAAA,YAAAC,GAAA,gBAAAC,KCSO,SAASC,GAAqB,CAAE,OAAAC,EAAQ,OAAAC,EAAQ,UAAAC,CAAW,EAAG,CACjE,MAAO,CACH,KAAAC,EACA,OAAAC,EACA,UAAAC,EACA,WAAAC,EACA,iBAAAC,CACJ,EACA,SAASJ,EAAKK,EAAKC,EAAKC,EAAS,CAC7B,IAAMC,EAAUF,EAAI,SACpB,GAAIE,IAAY,QAAaA,EAAQ,MAAQH,EACzC,OAEJ,IAAMI,EAAUD,IAAY,OAAYA,EAAQ,QAAUF,EAAI,KAC9D,GAAIG,IAAY,QAAaA,EAAQ,MAAQJ,EAAK,CAC9CI,EAAQ,QAAUF,EAClBD,EAAI,SAAWG,EACf,MACJ,CACA,IAAMC,EAAUL,EAAI,SACpB,GAAIK,IAAY,QAAaA,EAAQ,UAAYH,GAAWG,EAAQ,MAAQJ,EACxE,OAEJ,IAAMK,EAAUL,EAAI,SACdD,EAAI,SACA,CACE,QAAAE,EACA,IAAAF,EACA,IAAAC,EACA,QAAAE,EACA,QAAAC,EACA,QAAAC,EACA,QAAS,MACb,EACJD,IAAY,SACZA,EAAQ,QAAUE,GAElBH,IAAY,OACZA,EAAQ,QAAUG,EAGlBL,EAAI,KAAOK,EAEXD,IAAY,OACZA,EAAQ,QAAUC,EAGlBN,EAAI,KAAOM,CAEnB,CACA,SAASV,EAAOD,EAAMM,EAAMN,EAAK,IAAK,CAClC,IAAMK,EAAML,EAAK,IACXQ,EAAUR,EAAK,QACfS,EAAUT,EAAK,QACfY,EAAUZ,EAAK,QACfU,EAAUV,EAAK,QACrB,OAAIS,IAAY,OACZA,EAAQ,QAAUD,EAGlBF,EAAI,SAAWE,EAEfA,IAAY,OACZA,EAAQ,QAAUC,EAGlBH,EAAI,KAAOG,EAEXG,IAAY,OACZA,EAAQ,QAAUF,EAGlBL,EAAI,SAAWK,EAEfA,IAAY,OACZA,EAAQ,QAAUE,GAEZP,EAAI,KAAOO,KAAa,QAC9Bb,EAAUM,CAAG,EAEVI,CACX,CACA,SAASP,EAAUF,EAAM,CACrB,IAAIa,EAAOb,EAAK,QACZc,EACJC,EAAK,EAAG,CACJ,IAAMT,EAAMN,EAAK,IACbgB,EAAQV,EAAI,MAoBhB,GAnBMU,EAAS,GAGJA,EAAS,GAGTA,EAAQ,EAGV,EAAEA,EAAS,KAAaC,EAAYjB,EAAMM,CAAG,GAClDA,EAAI,MAAQU,EAAS,GACrBA,GAAS,GAGTA,EAAQ,EAPRV,EAAI,MAASU,EAAQ,GAAM,GAH3BA,EAAQ,EAHRV,EAAI,MAAQU,EAAQ,GAepBA,EAAQ,GACRlB,EAAOQ,CAAG,EAEVU,EAAQ,EAAG,CACX,IAAME,EAAUZ,EAAI,KACpB,GAAIY,IAAY,OAAW,CACvB,IAAMN,GAAWZ,EAAOkB,GAAS,QAC7BN,IAAY,SACZE,EAAQ,CAAE,MAAOD,EAAM,KAAMC,CAAM,EACnCD,EAAOD,GAEX,QACJ,CACJ,CACA,IAAKZ,EAAOa,KAAU,OAAW,CAC7BA,EAAOb,EAAK,QACZ,QACJ,CACA,KAAOc,IAAU,QAGb,GAFAd,EAAOc,EAAM,MACbA,EAAQA,EAAM,KACVd,IAAS,OAAW,CACpBa,EAAOb,EAAK,QACZ,SAASe,CACb,CAEJ,KACJ,OAAS,GACb,CACA,SAASZ,EAAWH,EAAMM,EAAK,CAC3B,IAAIQ,EACAK,EAAa,EACbC,EAAQ,GACZL,EAAK,EAAG,CACJ,IAAMV,EAAML,EAAK,IACXgB,EAAQX,EAAI,MAClB,GAAIC,EAAI,MAAQ,GACZc,EAAQ,YAEFJ,EAAS,MAAc,IAC7B,GAAInB,EAAOQ,CAAG,EAAG,CACb,IAAMgB,EAAOhB,EAAI,KACbgB,EAAK,UAAY,QACjBjB,EAAiBiB,CAAI,EAEzBD,EAAQ,EACZ,WAEMJ,EAAS,MAAc,GAAS,EAClChB,EAAK,UAAY,QAAaA,EAAK,UAAY,UAC/Cc,EAAQ,CAAE,MAAOd,EAAM,KAAMc,CAAM,GAEvCd,EAAOK,EAAI,KACXC,EAAMD,EACN,EAAEc,EACF,QACJ,CACA,GAAI,CAACC,EAAO,CACR,IAAMX,EAAUT,EAAK,QACrB,GAAIS,IAAY,OAAW,CACvBT,EAAOS,EACP,QACJ,CACJ,CACA,KAAOU,KAAc,CACjB,IAAMG,EAAWhB,EAAI,KACfiB,EAAkBD,EAAS,UAAY,OAQ7C,GAPIC,GACAvB,EAAOc,EAAM,MACbA,EAAQA,EAAM,MAGdd,EAAOsB,EAEPF,EAAO,CACP,GAAIvB,EAAOS,CAAG,EAAG,CACTiB,GACAnB,EAAiBkB,CAAQ,EAE7BhB,EAAMN,EAAK,IACX,QACJ,CACAoB,EAAQ,EACZ,MAEId,EAAI,OAAS,IAEjBA,EAAMN,EAAK,IACX,IAAMS,EAAUT,EAAK,QACrB,GAAIS,IAAY,OAAW,CACvBT,EAAOS,EACP,SAASM,CACb,CACJ,CACA,OAAOK,CACX,OAAS,GACb,CACA,SAAShB,EAAiBJ,EAAM,CAC5B,EAAG,CACC,IAAMM,EAAMN,EAAK,IACXgB,EAAQV,EAAI,OACbU,EAAS,MAAc,KACxBV,EAAI,MAAQU,EAAQ,IACfA,EAAS,KAAY,GACtBlB,EAAOQ,CAAG,EAGtB,QAAUN,EAAOA,EAAK,WAAa,OACvC,CACA,SAASiB,EAAYO,EAAWlB,EAAK,CACjC,IAAIN,EAAOM,EAAI,SACf,KAAON,IAAS,QAAW,CACvB,GAAIA,IAASwB,EACT,MAAO,GAEXxB,EAAOA,EAAK,OAChB,CACA,MAAO,EACX,CACJ,CCvOA,IAAIyB,GAAQ,EACRC,GAAa,EACbC,EAAc,EACdC,GAAe,EACfC,EACEC,EAAS,CAAC,EACV,CAAE,KAAAC,GAAM,OAAAC,GAAQ,UAAAC,GAAW,WAAAC,GAAY,iBAAAC,EAAkB,EAAIC,GAAqB,CACpF,OAAOC,EAAM,CACT,OAAIA,EAAK,WAAa,OACXC,GAAeD,CAAI,EAGnBE,GAAaF,CAAI,CAEhC,EACA,OAAOG,EAAQ,CACX,IAAIC,EAAcb,GACdc,EAAqBD,EACzB,EAII,IAHAX,EAAOW,GAAa,EAAID,EACxBA,EAAO,OAAS,GAChBA,EAASA,EAAO,MAAM,IAClBA,IAAW,QAAa,EAAEA,EAAO,MAAQ,GACzC,YAEC,IAET,IADAZ,GAAea,EACRC,EAAqB,EAAED,GAAa,CACvC,IAAME,EAAOb,EAAOY,CAAkB,EACtCZ,EAAOY,GAAoB,EAAIZ,EAAOW,CAAW,EACjDX,EAAOW,CAAW,EAAIE,CAC1B,CACJ,EACA,UAAUN,EAAM,CACNA,EAAK,MAAQ,EAGVA,EAAK,WAAa,SACvBA,EAAK,SAAW,OAChBA,EAAK,MAAQ,GACbO,GAAUP,CAAI,GALdQ,GAAgB,KAAKR,CAAI,CAOjC,CACJ,CAAC,EAIM,SAASS,EAAaC,EAAK,CAC9B,IAAMC,EAAUC,EAChB,OAAAA,EAAYF,EACLC,CACX,CAIO,SAASE,IAAa,CACzB,EAAEC,EACN,CACO,SAASC,IAAW,CAClB,EAAED,IACHE,GAAM,CAEd,CAaO,SAASC,GAAOC,EAAc,CACjC,OAAOC,GAAW,KAAK,CACnB,aAAcD,EACd,aAAcA,EACd,KAAM,OACN,SAAU,OACV,MAAO,CACX,CAAC,CACL,CACO,SAASE,GAASC,EAAQ,CAC7B,OAAOC,GAAa,KAAK,CACrB,MAAO,OACP,KAAM,OACN,SAAU,OACV,KAAM,OACN,SAAU,OACV,MAAO,EACP,OAAQD,CACZ,CAAC,CACL,CACO,SAASE,GAAOC,EAAI,CACvB,IAAMC,EAAI,CACN,GAAAD,EACA,KAAM,OACN,SAAU,OACV,KAAM,OACN,SAAU,OACV,MAAO,CACX,EACME,EAAUC,EAAaF,CAAC,EAC1BC,IAAY,QACZE,GAAKH,EAAGC,EAAS,CAAC,EAEtB,GAAI,CACAD,EAAE,GAAG,CACT,QACA,CACII,EAAYH,EACZD,EAAE,OAAS,EACf,CACA,OAAOK,GAAW,KAAKL,CAAC,CAC5B,CAiDA,SAASM,GAAeC,EAAG,CACvB,EAAEC,GACFD,EAAE,SAAW,OACbA,EAAE,MAAQ,EACV,IAAME,EAAUC,EAAaH,CAAC,EAC9B,GAAI,CACA,IAAMI,EAAWJ,EAAE,MACnB,OAAOI,KAAcJ,EAAE,MAAQA,EAAE,OAAOI,CAAQ,EACpD,QACA,CACIC,EAAYH,EACZF,EAAE,OAAS,GACXM,GAAUN,CAAC,CACf,CACJ,CACA,SAASO,GAAaC,EAAG,CACrB,OAAAA,EAAE,MAAQ,EACHA,EAAE,gBAAkBA,EAAE,aAAeA,EAAE,aAClD,CACA,SAASC,GAAI,EAAG,CACZ,IAAMC,EAAQ,EAAE,MAChB,GAAIA,EAAQ,IACJA,EAAQ,IACLC,GAAW,EAAE,KAAM,CAAC,EAAI,CAC/B,EAAEV,GACF,EAAE,SAAW,OACb,EAAE,MAAQ,EACV,IAAMC,EAAUC,EAAa,CAAC,EAC9B,GAAI,CACA,EAAE,GAAG,CACT,QACA,CACIE,EAAYH,EACZ,EAAE,OAAS,GACXI,GAAU,CAAC,CACf,CACJ,MAEI,EAAE,MAAQ,CAElB,CACA,SAASM,IAAQ,CACb,GAAI,CACA,KAAOC,EAAcC,IAAc,CAC/B,IAAMC,EAASC,EAAOH,CAAW,EACjCG,EAAOH,GAAa,EAAI,OACxBJ,GAAIM,CAAM,CACd,CACJ,QACA,CACI,KAAOF,EAAcC,IAAc,CAC/B,IAAMC,EAASC,EAAOH,CAAW,EACjCG,EAAOH,GAAa,EAAI,OACxBE,EAAO,OAAS,EACpB,CACAF,EAAc,EACdC,GAAe,CACnB,CACJ,CACA,SAASG,IAAe,CACpB,IAAMP,EAAQ,KAAK,MACnB,GAAIA,EAAQ,IACJA,EAAQ,KACJC,GAAW,KAAK,KAAM,IAAI,IACtB,KAAK,MAAQD,EAAQ,IAAK,MACtC,GAAIX,GAAe,IAAI,EAAG,CACtB,IAAMmB,EAAO,KAAK,KACdA,IAAS,QACTC,GAAiBD,CAAI,CAE7B,UAEK,CAACR,EAAO,CACb,KAAK,MAAQ,EACb,IAAMR,EAAUC,EAAa,IAAI,EACjC,GAAI,CACA,KAAK,MAAQ,KAAK,OAAO,CAC7B,QACA,CACIE,EAAYH,EACZ,KAAK,OAAS,EAClB,CACJ,CACA,IAAMkB,EAAMf,EACZ,OAAIe,IAAQ,QACRC,GAAK,KAAMD,EAAKnB,EAAK,EAElB,KAAK,KAChB,CACA,SAASqB,MAAcC,EAAO,CAC1B,GAAIA,EAAM,QACN,GAAI,KAAK,gBAAkB,KAAK,aAAeA,EAAM,CAAC,GAAI,CACtD,KAAK,MAAQ,GACb,IAAML,EAAO,KAAK,KACdA,IAAS,SACTM,GAAUN,CAAI,EACTO,IACDb,GAAM,EAGlB,MAEC,CACD,GAAI,KAAK,MAAQ,IACTL,GAAa,IAAI,EAAG,CACpB,IAAMW,EAAO,KAAK,KACdA,IAAS,QACTC,GAAiBD,CAAI,CAE7B,CAEJ,IAAIE,EAAMf,EACV,KAAOe,IAAQ,QAAW,CACtB,GAAIA,EAAI,MAAS,EAAQ,CACrBC,GAAK,KAAMD,EAAKnB,EAAK,EACrB,KACJ,CACAmB,EAAMA,EAAI,MAAM,GACpB,CACA,OAAO,KAAK,YAChB,CACJ,CACA,SAASM,IAAa,CAClBC,GAAgB,KAAK,IAAI,CAC7B,CACA,SAASA,IAAkB,CACvB,KAAK,SAAW,OAChB,KAAK,MAAQ,EACbrB,GAAU,IAAI,EACd,IAAMc,EAAM,KAAK,KACbA,IAAQ,QACRQ,GAAOR,CAAG,CAElB,CACA,SAASd,GAAUc,EAAK,CACpB,IAAMS,EAAWT,EAAI,SACjBU,EAAMD,IAAa,OAAYA,EAAS,QAAUT,EAAI,KAC1D,KAAOU,IAAQ,QACXA,EAAMF,GAAOE,EAAKV,CAAG,CAE7B,CChPA,SAASW,GACPC,EACAC,EACAC,EACM,CACN,GAAI,OAAOD,GAAM,WAAY,CAC3B,GAAIC,EAAQ,CAEV,IAAMC,EAAUC,EAAa,MAAS,EAChCC,EAAOL,EAAE,EAEf,GADAI,EAAaD,CAAO,EAChBD,EAAOG,EAAMJ,CAAC,EAAG,MACvB,CACAD,EAAEC,CAAC,EACH,MACF,CAGA,IAAME,EAAUC,EAAa,MAAS,EAChCC,EAAOL,EAAE,EACfI,EAAaD,CAAO,EACpB,IAAMG,EAAQL,EAAqBI,CAAI,EACnCH,GAAUA,EAAOG,EAAMC,CAAI,GAC/BN,EAAEM,CAAI,CACR,CAqBO,SAASC,GAAgBC,EAAiBC,EAA0E,CACzH,IAAMT,EAAIU,GAAmBF,CAAY,EACnCG,EAASX,EACTY,EAAKH,GAAS,OAGpB,MAAO,CAACE,EAFyBV,GAA4BF,GAAeC,EAAGC,EAAGW,CAAE,CAE9D,CACxB,CCrGA,IAAIC,GAAgC,KA6D7B,SAASC,GAAiBC,EAA2B,CACtDC,IACFA,GAAY,UAAU,KAAKD,CAAO,CAEtC,CAKO,SAASE,IAAyB,CACvC,OAAOD,KAAgB,IACzB,CCvEA,IAAME,GAAY,GAElB,IAAMC,GAAyB,CAAC,EAChC,QAASC,EAAI,EAAGA,EAAIC,GAAWD,IAAKD,GAAK,KAAK,CAAC,CAAC,EAoEzC,SAASG,EAAeC,EAA4B,CACzD,IAAMC,EAAUC,GAAUF,CAAE,EAC5B,OAAIG,GAAc,GAChBC,GAAiBH,CAAO,EAEnBA,CACT,CCtDO,SAASI,GAAkBC,EAAuC,CACvE,OAAOC,GAAYD,CAAE,CACvB,CChBO,SAASE,EAAMC,EAAsB,CAC1CC,GAAW,EACX,GAAI,CACFD,EAAG,CACL,QAAE,CACAE,GAAS,CACX,CACF,CCwBO,SAASC,GAA6BC,EAAyB,CACpE,IAAMC,EAAID,EAAI,OACd,GAAIC,IAAM,EAAG,MAAO,CAAC,EAGrB,IAAMC,EAAQ,IAAI,WAAWD,CAAC,EACxBE,EAAc,IAAI,WAAWF,CAAC,EAC9BG,EAAc,IAAI,WAAWH,CAAC,EAAE,KAAK,EAAE,EACzCI,EAAW,EAEf,QAASC,EAAI,EAAGA,EAAIL,EAAGK,IAAK,CAC1B,IAAMC,EAAMP,EAAIM,CAAC,EAGbE,EAAK,EAAGC,EAAKJ,EACjB,KAAOG,EAAKC,GAAI,CACd,IAAMC,EAAOF,EAAKC,GAAO,EACrBP,EAAMQ,CAAG,EAAKH,EAAKC,EAAKE,EAAM,EAC7BD,EAAKC,CACZ,CAEAR,EAAMM,CAAE,EAAID,EACZJ,EAAYK,CAAE,EAAIF,EACdE,EAAK,IAAGJ,EAAYE,CAAC,EAAIH,EAAYK,EAAK,CAAC,GAC3CA,GAAMH,GAAUA,GACtB,CAGA,IAAMM,EAAS,IAAI,MAAcN,CAAQ,EACrCO,EAAMT,EAAYE,EAAW,CAAC,EAClC,QAASC,EAAID,EAAW,EAAGC,GAAK,EAAGA,IACjCK,EAAOL,CAAC,EAAIM,EACZA,EAAMR,EAAYQ,CAAG,EAGvB,OAAOD,CACT,CAOA,IAAME,GAAuB,GAwC7B,SAASC,GACPC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACoB,CACpB,IAAMC,EAASR,EAAS,OAClBS,EAASR,EAAS,OAGlBS,EAA+B,IAAI,MAAMF,CAAM,EACrD,QAASG,EAAI,EAAGA,EAAIH,EAAQG,IAC1BD,EAAQC,CAAC,EAAIR,EAAMH,EAASW,CAAC,CAAE,EAIjC,IAAMC,EAAa,IAAI,MAAcH,CAAM,EACrCI,EAAU,IAAI,WAAWL,CAAM,EAErC,QAASG,EAAI,EAAGA,EAAIF,EAAQE,IAAK,CAC/B,IAAMG,EAAMX,EAAMF,EAASU,CAAC,CAAE,EAC1BI,EAAQ,GACZ,QAASC,EAAI,EAAGA,EAAIR,EAAQQ,IAC1B,GAAI,CAACH,EAAQG,CAAC,GAAKN,EAAQM,CAAC,IAAMF,EAAK,CACrCC,EAAQC,EACRH,EAAQG,CAAC,EAAI,EACb,KACF,CAEFJ,EAAWD,CAAC,EAAII,CAClB,CAGA,QAASJ,EAAI,EAAGA,EAAIH,EAAQG,IAC1B,GAAI,CAACE,EAAQF,CAAC,EACZ,GAAIJ,GAAO,eAAgB,CACzB,IAAMU,EAAOf,EAASS,CAAC,EACvBJ,EAAM,eAAeU,EAAM,IAAM,CAC3BA,EAAK,YAAYA,EAAK,WAAW,YAAYA,CAAI,CACvD,CAAC,CACH,MACElB,EAAO,YAAYG,EAASS,CAAC,CAAE,EAMrC,GAAIH,IAAWC,EAAQ,CACrB,IAAIS,EAAe,GACnB,QAASP,EAAI,EAAGA,EAAIF,EAAQE,IAC1B,GAAIC,EAAWD,CAAC,IAAMA,EAAG,CACvBO,EAAe,GACf,KACF,CAEF,GAAIA,EAAc,CAChB,IAAMC,EAAQ,IAAI,MAAYV,CAAM,EACpC,QAASE,EAAI,EAAGA,EAAIF,EAAQE,IAAK,CAC/B,IAAMM,EAAOf,EAASS,CAAC,EACvBN,EAASY,EAAMhB,EAASU,CAAC,CAAE,EAC3BQ,EAAMR,CAAC,EAAIM,CACb,CACA,MAAO,CAAE,MAAAE,EAAO,MAAOlB,CAAS,CAClC,CACF,CAGA,IAAMmB,EAA0B,CAAC,EAC3BC,EAA4B,CAAC,EACnC,QAASV,EAAI,EAAGA,EAAIF,EAAQE,IACtBC,EAAWD,CAAC,IAAM,KACpBS,EAAc,KAAKR,EAAWD,CAAC,CAAE,EACjCU,EAAgB,KAAKV,CAAC,GAI1B,IAAMW,EAAcC,GAA6BH,CAAa,EAExDI,EAAW,IAAI,WAAWf,CAAM,EACtC,QAAWgB,KAAMH,EACfE,EAASH,EAAgBI,CAAE,CAAE,EAAI,EAInC,IAAMC,EAAW,IAAI,MAAYjB,CAAM,EACnCkB,EAA2BrB,GAAc,KAE7C,QAASK,EAAIF,EAAS,EAAGE,GAAK,EAAGA,IAAK,CACpC,IAAIM,EACAW,EAAQ,GAEZ,GAAIhB,EAAWD,CAAC,IAAM,GACpBM,EAAOb,EAASH,EAASU,CAAC,CAAE,EAC5BiB,EAAQ,WAERX,EAAOf,EAASU,EAAWD,CAAC,CAAE,EAC9BN,EAASY,EAAMhB,EAASU,CAAC,CAAE,EAEvBa,EAASb,CAAC,EAAG,CACfe,EAASf,CAAC,EAAIM,EACdU,EAAcV,EACd,QACF,CAGEU,EACF5B,EAAO,aAAakB,EAAMU,CAAW,EAErC5B,EAAO,YAAYkB,CAAI,EAGrBW,GAAOrB,GAAO,WAAWU,CAAI,EAEjCS,EAASf,CAAC,EAAIM,EACdU,EAAcV,CAChB,CAEA,MAAO,CAAE,MAAOS,EAAU,MAAOzB,CAAS,CAC5C,CAsBO,SAAS4B,GACd9B,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACoB,CACpB,IAAMC,EAASR,EAAS,OAClBS,EAASR,EAAS,OAGxB,GAAIQ,IAAW,EAAG,CAChB,QAASE,EAAI,EAAGA,EAAIH,EAAQG,IAC1B,GAAIJ,GAAO,eAAgB,CACzB,IAAMU,EAAOf,EAASS,CAAC,EACvBJ,EAAM,eAAeU,EAAM,IAAM,CAC3BA,EAAK,YAAYA,EAAK,WAAW,YAAYA,CAAI,CACvD,CAAC,CACH,MACElB,EAAO,YAAYG,EAASS,CAAC,CAAE,EAGnC,MAAO,CAAE,MAAO,CAAC,EAAG,MAAO,CAAC,CAAE,CAChC,CAGA,GAAIH,IAAW,EAAG,CAChB,IAAMW,EAAQ,IAAI,MAAYV,CAAM,EACpC,QAASE,EAAI,EAAGA,EAAIF,EAAQE,IAAK,CAC/B,IAAMM,EAAOb,EAASH,EAASU,CAAC,CAAE,EAC9BL,EACFP,EAAO,aAAakB,EAAMX,CAAU,EAEpCP,EAAO,YAAYkB,CAAI,EAEzBV,GAAO,WAAWU,CAAI,EACtBE,EAAMR,CAAC,EAAIM,CACb,CACA,MAAO,CAAE,MAAAE,EAAO,MAAOlB,CAAS,CAClC,CAGA,GAAIO,EAASsB,GACX,OAAOhC,GAAeC,EAAQC,EAAUC,EAAUC,EAAUC,EAAOC,EAAUC,EAAUC,EAAYC,CAAK,EAI1G,IAAMwB,EAAY,IAAI,IACtB,QAASpB,EAAI,EAAGA,EAAIH,EAAQG,IAC1BoB,EAAU,IAAI5B,EAAMH,EAASW,CAAC,CAAE,EAAGA,CAAC,EAKtC,IAAMC,EAAa,IAAI,MAAcH,CAAM,EACrCI,EAAU,IAAI,WAAWL,CAAM,EAErC,QAASG,EAAI,EAAGA,EAAIF,EAAQE,IAAK,CAC/B,IAAMG,EAAMX,EAAMF,EAASU,CAAC,CAAE,EACxBqB,EAASD,EAAU,IAAIjB,CAAG,EAC5BkB,IAAW,QACbpB,EAAWD,CAAC,EAAIqB,EAChBnB,EAAQmB,CAAM,EAAI,GAElBpB,EAAWD,CAAC,EAAI,EAEpB,CAGA,QAASA,EAAI,EAAGA,EAAIH,EAAQG,IAC1B,GAAI,CAACE,EAAQF,CAAC,EACZ,GAAIJ,GAAO,eAAgB,CACzB,IAAMU,EAAOf,EAASS,CAAC,EACvBJ,EAAM,eAAeU,EAAM,IAAM,CAC3BA,EAAK,YAAYA,EAAK,WAAW,YAAYA,CAAI,CACvD,CAAC,CACH,MACElB,EAAO,YAAYG,EAASS,CAAC,CAAE,EAMrC,GAAIH,IAAWC,EAAQ,CACrB,IAAIS,EAAe,GACnB,QAASP,EAAI,EAAGA,EAAIF,EAAQE,IAC1B,GAAIC,EAAWD,CAAC,IAAMA,EAAG,CACvBO,EAAe,GACf,KACF,CAEF,GAAIA,EAAc,CAChB,IAAMC,EAAQ,IAAI,MAAYV,CAAM,EACpC,QAASE,EAAI,EAAGA,EAAIF,EAAQE,IAAK,CAC/B,IAAMM,EAAOf,EAASS,CAAC,EACvBN,EAASY,EAAMhB,EAASU,CAAC,CAAE,EAC3BQ,EAAMR,CAAC,EAAIM,CACb,CACA,MAAO,CAAE,MAAAE,EAAO,MAAOlB,CAAS,CAClC,CACF,CAGA,IAAMmB,EAA0B,CAAC,EAC3BC,EAA4B,CAAC,EACnC,QAASV,EAAI,EAAGA,EAAIF,EAAQE,IACtBC,EAAWD,CAAC,IAAM,KACpBS,EAAc,KAAKR,EAAWD,CAAC,CAAE,EACjCU,EAAgB,KAAKV,CAAC,GAI1B,IAAMW,EAAcC,GAA6BH,CAAa,EAExDI,EAAW,IAAI,WAAWf,CAAM,EACtC,QAAWgB,KAAMH,EACfE,EAASH,EAAgBI,CAAE,CAAE,EAAI,EAInC,IAAMC,EAAW,IAAI,MAAYjB,CAAM,EACnCkB,EAA2BrB,GAAc,KAE7C,QAASK,EAAIF,EAAS,EAAGE,GAAK,EAAGA,IAAK,CACpC,IAAIM,EACAW,EAAQ,GAEZ,GAAIhB,EAAWD,CAAC,IAAM,GAEpBM,EAAOb,EAASH,EAASU,CAAC,CAAE,EAC5BiB,EAAQ,WAGRX,EAAOf,EAASU,EAAWD,CAAC,CAAE,EAC9BN,EAASY,EAAMhB,EAASU,CAAC,CAAE,EAEvBa,EAASb,CAAC,EAAG,CAEfe,EAASf,CAAC,EAAIM,EACdU,EAAcV,EACd,QACF,CAIEU,EACF5B,EAAO,aAAakB,EAAMU,CAAW,EAErC5B,EAAO,YAAYkB,CAAI,EAGrBW,GAAOrB,GAAO,WAAWU,CAAI,EAEjCS,EAASf,CAAC,EAAIM,EACdU,EAAcV,CAChB,CAEA,MAAO,CAAE,MAAOS,EAAU,MAAOzB,CAAS,CAC5C,CCjaA,SAASgC,GAAeC,EAA0B,CAChD,IAAMC,EAAU,IAAI,IACdC,EAAQF,EAAG,WACjB,QAASG,EAAI,EAAGA,EAAID,EAAM,OAAQC,IAAK,CACrC,IAAMC,EAAOF,EAAMC,CAAC,EAAG,KACnBC,EAAK,WAAW,YAAY,GAC9BH,EAAQ,IAAIG,EAAK,MAAM,EAAE,CAAC,CAE9B,CACA,OAAOH,CACT,CAGA,SAASI,GAAYL,EAAsB,CACzC,OAAOA,EAAG,aAAa,WAAW,GAAKA,EAAG,aAAa,SAAS,CAClE,CAIA,SAASM,GAAaC,EAAwB,CAC5C,GAAI,CACF,IAAMC,EAAM,KAAK,MAAMD,CAAI,EAC3B,OAAO,OAAO,KAAKC,CAAG,EAAE,KAAK,CAC/B,MAAQ,CACN,MAAO,CAAC,CACV,CACF,CAEA,SAASC,GAAUC,EAAiBC,EAA0B,CAC5D,GAAID,EAAM,SAAWC,EAAM,OAAQ,MAAO,GAC1C,QAASR,EAAI,EAAGA,EAAIO,EAAM,OAAQP,IAChC,GAAIO,EAAMP,CAAC,IAAMQ,EAAMR,CAAC,EAAG,MAAO,GAEpC,MAAO,EACT,CAIA,SAASS,GAAmBC,EAAiBC,EAA2B,CACtE,IAAMC,EAAaF,EAAO,aAAa,aAAa,EAC9CG,EAAYF,EAAM,aAAa,aAAa,EAElD,GAAIC,IAAeC,EAAW,MAAO,UAKrC,IAAMC,EADoBJ,EAAe,qBACCA,EAAO,aAAa,kBAAkB,GAAK,KAC/EK,EAAeJ,EAAM,aAAa,kBAAkB,GAAK,KAEzDK,EAAWb,GAAaW,CAAa,EACrCG,EAAUd,GAAaY,CAAY,EAEzC,OAAIT,GAAUU,EAAUC,CAAO,EAAU,WAClC,OACT,CAKA,IAAIC,GAA6C,KAEjD,SAASC,GAAUC,EAAgC,CACjD,OAAKF,KAAgBA,GAAiB,SAAS,cAAc,UAAU,GACvEA,GAAe,UAAYE,EAEpBF,GAAe,OACxB,CAIA,SAASG,GAAgBX,EAAiBC,EAAsB,CAC9D,IAAMW,EAAc1B,GAAec,CAAM,EACnCa,EAAcb,EAAO,aAAa,WAAW,EAC7Cc,EAAed,EAAO,aAAa,YAAY,EAGjDe,EAAyB,GACvBC,EAAYhB,EAAO,WACzB,QAASV,EAAI,EAAGA,EAAI0B,EAAU,OAAQ1B,IACpC,GAAI0B,EAAU1B,CAAC,EAAG,KAAK,WAAW,aAAa,EAAG,CAChDyB,EAAyB,GACzB,KACF,CAIF,IAAME,EAAWhB,EAAM,WACvB,QAASX,EAAI,EAAGA,EAAI2B,EAAS,OAAQ3B,IAAK,CACxC,IAAM4B,EAAOD,EAAS3B,CAAC,EAKvB,GAHI4B,EAAK,OAAS,SAAWL,GACzBK,EAAK,OAAS,SAAWH,IACxBG,EAAK,OAAS,SAAWA,EAAK,OAAS,YAAcJ,GACtDF,EAAY,IAAIM,EAAK,IAAI,EAAG,SAEhBlB,EAAO,aAAakB,EAAK,IAAI,IAC7BA,EAAK,OACnBlB,EAAO,aAAakB,EAAK,KAAMA,EAAK,KAAK,CAE7C,CAIA,QAAS5B,EAAI0B,EAAU,OAAS,EAAG1B,GAAK,EAAGA,IAAK,CAC9C,IAAM4B,EAAOF,EAAU1B,CAAC,EACxB,GAAI,CAACW,EAAM,aAAaiB,EAAK,IAAI,EAAG,CAIlC,GAHIA,EAAK,OAAS,SAAWL,GACzBK,EAAK,OAAS,SAAWH,IACxBG,EAAK,OAAS,SAAWA,EAAK,OAAS,YAAcJ,GACtDF,EAAY,IAAIM,EAAK,IAAI,EAAG,SAEhClB,EAAO,gBAAgBkB,EAAK,IAAI,CAClC,CACF,CACF,CAIA,SAASC,GAAenB,EAAiBC,EAAsB,CAE7D,GAAID,EAAO,aAAa,WAAW,EAAG,OAEtC,IAAMoB,EAAoB,CAAC,EACrBC,EAA4C,CAAC,EAEnD,QAAWC,KAAS,MAAM,KAAKtB,EAAO,UAAU,EAC1CsB,EAAM,WAAa,KAAK,WAAWF,EAAU,KAAKE,CAAa,EAErE,QAAShC,EAAI,EAAGA,EAAIW,EAAM,WAAW,OAAQX,IAAK,CAChD,IAAMgC,EAAQrB,EAAM,WAAWX,CAAC,EAC5BgC,EAAM,WAAa,KAAK,WAAWD,EAAS,KAAK,CAAE,KAAMC,EAAe,MAAOhC,CAAE,CAAC,CACxF,CAGA,GAAI8B,EAAU,SAAWC,EAAS,OAAQ,CACxC,QAAS/B,EAAI,EAAGA,EAAI8B,EAAU,OAAQ9B,IAChC8B,EAAU9B,CAAC,EAAE,cAAgB+B,EAAS/B,CAAC,EAAE,KAAK,cAChD8B,EAAU9B,CAAC,EAAE,YAAc+B,EAAS/B,CAAC,EAAE,KAAK,aAGhD,MACF,CAGA,IAAMiC,EAAW,IAAI,IACjBC,EAAU,EAEd,OAAW,CAAE,KAAMC,EAAS,MAAOC,CAAY,IAAKL,EAClD,GAAIG,EAAUJ,EAAU,OAAQ,CAE9B,IAAMO,EAAWP,EAAUI,CAAO,EAClCA,IACAD,EAAS,IAAII,CAAQ,EACjBA,EAAS,cAAgBF,EAAQ,cACnCE,EAAS,YAAcF,EAAQ,YAEnC,KAAO,CAEL,IAAMG,EAAMC,GAAqB7B,EAAQC,EAAOyB,CAAW,EAC3D1B,EAAO,aAAa,SAAS,eAAeyB,EAAQ,aAAe,EAAE,EAAGG,CAAG,CAC7E,CAIF,QAAWE,KAAMV,EACX,CAACG,EAAS,IAAIO,CAAE,GAAKA,EAAG,aAAe9B,GACzCA,EAAO,YAAY8B,CAAE,CAG3B,CAGA,SAASD,GAAqB7B,EAAiBC,EAAgB8B,EAA6B,CAC1F,QAASC,EAAID,EAAS,EAAGC,EAAI/B,EAAM,WAAW,OAAQ+B,IAAK,CACzD,IAAMC,EAAUhC,EAAM,WAAW+B,CAAC,EAClC,GAAIC,EAAQ,WAAa,KAAK,aAAc,CAC1C,IAAMC,EAAOD,EAAoB,aAAa,eAAe,EAC7D,GAAIC,EAAK,CACP,IAAMC,EAAQnC,EAAO,cAAc,mBAAmB,IAAI,OAAOkC,CAAG,CAAC,IAAI,EACzE,GAAIC,GAASA,EAAM,gBAAkBnC,EAAQ,OAAOmC,CACtD,CACF,CACF,CACA,OAAO,IACT,CAIA,SAASC,GACPC,EACAC,EACAC,EACM,CAEN,GAAI/C,GAAY6C,CAAU,EAAG,OAG7BlB,GAAekB,EAAYC,CAAS,EAGpC,IAAME,EAAe,MAAM,KAAKH,EAAW,QAAQ,EAC7CI,EAAc,MAAM,KAAKH,EAAU,QAAQ,EAG3CI,EAAY,IAAI,IAChBC,EAAyB,CAAC,EAChC,QAAWrB,KAASkB,EAAc,CAChC,GAAIlB,EAAM,aAAa,oBAAoB,EAAG,SAC9C,IAAMY,EAAMZ,EAAM,aAAa,eAAe,EAC1CY,EACFQ,EAAU,IAAIR,EAAKZ,CAAK,EAExBqB,EAAY,KAAKrB,CAAK,CAE1B,CAEA,IAAIsB,EAAa,EAGXC,EAAmB,IAAI,IAE7B,QAAWC,KAAYL,EAAa,CAClC,IAAMP,EAAMY,EAAS,aAAa,eAAe,EAC7CC,EAEJ,GAAIb,EACFa,EAAYL,EAAU,IAAIR,CAAG,MAG7B,MAAOU,EAAaD,EAAY,QAAQ,CACtC,IAAMK,EAAYL,EAAYC,CAAU,EAExC,GADAA,IACII,EAAU,UAAYF,EAAS,SAAW,CAACD,EAAiB,IAAIG,CAAS,EAAG,CAC9ED,EAAYC,EACZ,KACF,CACF,CAGF,GAAID,EAAW,CAIb,GAHAF,EAAiB,IAAIE,CAAS,EAG1BA,EAAU,aAAa,kBAAkB,GAAKD,EAAS,aAAa,kBAAkB,EAGxF,OAFa/C,GAAmBgD,EAAWD,CAAQ,EAErC,CACZ,IAAK,WAEHnC,GAAgBoC,EAAWD,CAAQ,EAEnCV,GAAaW,EAAWD,EAAUP,CAAM,EACxC,MAEF,IAAK,QAEHA,EAAO,aAAaQ,CAAS,EAC7BpC,GAAgBoC,EAAWD,CAAQ,EAEnCG,GAAoBF,EAAWD,CAAQ,EACvCP,EAAO,WAAWQ,CAAS,EAC3B,MAEF,IAAK,UAAW,CAEdR,EAAO,aAAaQ,CAAS,EAC7B,IAAMG,EAAcJ,EAAS,UAAU,EAAI,EAC3CT,EAAW,aAAaa,EAAaH,CAAS,EAC9CR,EAAO,WAAWW,CAAW,EAC7BL,EAAiB,OAAOE,CAAS,EACjCA,EAAYG,EACZL,EAAiB,IAAIK,CAAW,EAChC,KACF,CACF,MAGAvC,GAAgBoC,EAAWD,CAAQ,EACnCV,GAAaW,EAAWD,EAAUP,CAAM,EAK1CY,GAAed,EAAYU,EAAWD,EAAUL,CAAW,CAC7D,KAAO,CAEL,IAAMW,EAAQN,EAAS,UAAU,EAAI,EAE/BO,EAAeC,GAAmBjB,EAAYS,EAAUL,CAAW,EACzEJ,EAAW,aAAae,EAAOC,CAAY,EAC3CR,EAAiB,IAAIO,CAAK,EAGtBA,EAAM,aAAa,kBAAkB,GACvCb,EAAO,WAAWa,CAAK,EAEzB,IAAMG,EAAeH,EAAM,iBAAiB,oBAAoB,EAChE,QAAWI,KAAU,MAAM,KAAKD,CAAY,EAC1ChB,EAAO,WAAWiB,CAAM,CAE5B,CACF,CAGA,QAAWlC,KAASkB,EAClB,GAAI,CAACK,EAAiB,IAAIvB,CAAK,EAAG,CAIhC,GAFIA,EAAM,gBAAkBe,GAExBf,EAAM,aAAa,oBAAoB,EAAG,SAE1CA,EAAM,aAAa,kBAAkB,GACvCiB,EAAO,aAAajB,CAAK,EAE3B,IAAMiC,EAAejC,EAAM,iBAAiB,oBAAoB,EAChE,QAAWkC,KAAU,MAAM,KAAKD,CAAY,EAC1ChB,EAAO,aAAaiB,CAAM,EAE5BnB,EAAW,YAAYf,CAAK,CAC9B,CAEJ,CAGA,SAAS2B,GAAoBjD,EAAiBC,EAAsB,CAElE,KAAOD,EAAO,YACZA,EAAO,YAAYA,EAAO,UAAU,EAGtC,QAAWsB,KAAS,MAAM,KAAKrB,EAAM,UAAU,EAC7CD,EAAO,YAAYsB,EAAM,UAAU,EAAI,CAAC,CAE5C,CAGA,SAAS6B,GACPM,EACAzD,EACA0D,EACAjB,EACM,CACN,IAAMV,EAASU,EAAY,QAAQiB,CAAM,EAIzC,GAH0B,MAAM,KAAKD,EAAO,QAAQ,EACf,QAAQzD,CAAM,IAEhC+B,EAAQ,CAEzB,IAAM4B,EAAelB,EAAYV,EAAS,CAAC,EAC3C,GAAI4B,EAAc,CAChB,IAAMC,EAAUD,EAAa,aAAa,eAAe,EACzD,GAAIC,EAAS,CAEX,IAAMC,EAAWJ,EAAO,cAAc,mBAAmB,IAAI,OAAOG,CAAO,CAAC,IAAI,EAChF,GAAIC,GAAYA,EAAS,gBAAkBJ,EAAQ,CACjDA,EAAO,aAAazD,EAAQ6D,CAAQ,EACpC,MACF,CACF,CACF,CAEAJ,EAAO,YAAYzD,CAAM,CAC3B,CACF,CAGA,SAASsD,GACPG,EACAX,EACAL,EACa,CACb,IAAMV,EAASU,EAAY,QAAQK,CAAQ,EAG3C,QAAS,EAAIf,EAAS,EAAG,EAAIU,EAAY,OAAQ,IAAK,CACpD,IAAMP,EAAMO,EAAY,CAAC,EAAE,aAAa,eAAe,EACvD,GAAIP,EAAK,CACP,IAAM4B,EAAWL,EAAO,cAAc,mBAAmB,IAAI,OAAOvB,CAAG,CAAC,IAAI,EAC5E,GAAI4B,GAAYA,EAAS,gBAAkBL,EACzC,OAAOK,CAEX,CACF,CAEA,OAAO,IACT,CAIO,SAASC,GAAiBxB,EAA0B,CAGzD,IAAIyB,EAAY,GAEhB,OAAO,SAAmBC,EAAoBvD,EAAoB,CAChE,IAAMwD,EAAUxD,EAAK,KAAK,EAC1B,GAAKwD,GAGD,EAAAA,IAAYF,GAAaC,EAAU,cAAc,GACrD,CAAAD,EAAYE,EAGZ3B,EAAO,mBAAmB,EAE1B,GAAI,CAEF,GAAI,CAAC0B,EAAU,cAAc,GAAKA,EAAU,SAAS,SAAW,EAAG,CACjEA,EAAU,UAAYC,EAGtB3B,EAAO,MAAM,IAAM,CACjB,IAAM4B,EAASF,EAAU,iBAAiB,oBAAoB,EAC9D,QAAWG,KAAS,MAAM,KAAKD,CAAM,EACnC5B,EAAO,WAAW6B,CAAK,CAE3B,CAAC,EAED,MACF,CAGA,IAAMC,EAAW5D,GAAUyD,CAAO,EAC5BI,EAAoB,SAAS,cAAc,KAAK,EACtDA,EAAkB,YAAYD,CAAQ,EAOtC,IAAM/D,EAAW,IAAI,IACrB,QAAWgB,KAAS,MAAM,KAAK2C,EAAU,QAAQ,EAAG,CAClD,GAAI3C,EAAM,aAAa,oBAAoB,EAAG,SAC9C,IAAMY,EAAMZ,EAAM,aAAa,eAAe,EAC1CY,GAAK5B,EAAS,IAAI4B,CAAG,CAC3B,CACA,IAAIqC,EAAa,GACjB,GAAIjE,EAAS,KAAO,EAClB,QAAWgB,KAAS,MAAM,KAAKgD,EAAkB,QAAQ,EAAG,CAC1D,IAAMpC,EAAMZ,EAAM,aAAa,eAAe,EAC9C,GAAIY,GAAO5B,EAAS,IAAI4B,CAAG,EAAG,CAAEqC,EAAa,GAAM,KAAO,CAC5D,CAGF,GAAIjE,EAAS,KAAO,GAAK,CAACiE,EAAY,CAEpChC,EAAO,MAAM,IAAM,CACjB,IAAMiC,EAAaP,EAAU,iBAAiB,oBAAoB,EAClE,QAAWG,KAAS,MAAM,KAAKI,CAAU,EACvCjC,EAAO,aAAa6B,CAAK,EAE3BH,EAAU,UAAYC,EACtB,IAAMO,EAAYR,EAAU,iBAAiB,oBAAoB,EACjE,QAAWG,KAAS,MAAM,KAAKK,CAAS,EACtClC,EAAO,WAAW6B,CAAK,CAE3B,CAAC,EACD,MACF,CAGA7B,EAAO,MAAM,IAAM,CACjBH,GAAa6B,EAAWK,EAAmB/B,CAAM,CACnD,CAAC,CACH,QAAE,CAEAA,EAAO,kBAAkB,CAC3B,EACF,CACF,CT3XA,IAAMmC,GAAmB,IAAI,IAE7B,SAASC,GAASC,EAAkB,CAClC,IAAMC,EAAKH,GAAiB,IAAIE,CAAE,EAC9BC,EACFA,EAAG,EACMC,GACTC,EAAI,oCAAoCH,CAAE,SAAS,CAEvD,CAEA,SAASI,GAAiBC,EAAeC,EAAwC,CAC/E,IAAMC,EAAuC,OAAO,OAAO,IAAI,EAC/D,QAAWC,KAAO,OAAO,KAAKF,CAAM,EAClCC,EAAaC,CAAG,EAAI,IAAMF,EAAOE,CAAG,EAGtC,MAAO,CACL,QAAS,IAAI,MAAMH,EAAO,QAAS,CACjC,IAAII,EAAQC,EAAc,CACxB,OAAIA,KAAQH,EAAqBA,EAAaG,CAAI,EAC3CD,EAAOC,CAAI,CACpB,EACA,IAAID,EAAQC,EAAc,CACxB,OAAOA,KAAQH,GAAgBG,KAAQD,CACzC,CACF,CAAC,EACD,QAASJ,EAAO,OAClB,CACF,CAGA,IAAIH,EAAS,GAETS,EAAkC,UAClCC,EAAmB,GACnBC,GAAsB,GAC1B,SAASV,KAAOW,EAAuB,EACjCZ,GAAW,OAAO,OAAW,KAAgB,OAAe,gBAC9D,QAAQ,IAAI,YAAa,GAAGY,CAAI,CAEpC,CAmBA,IAAMC,GAAc,IAAI,IAExB,SAASC,GAAiBC,EAAqD,CAC7E,GAAIA,GAAO,KAAM,OACjB,IAAMC,EAAaD,EAAI,KAAK,EAAE,YAAY,EAC1C,GAAIC,IAAe,KAAOA,IAAe,QAAUA,IAAe,MAAQA,IAAe,MAAO,MAAO,GACvG,GAAIA,IAAe,KAAOA,IAAe,SAAWA,IAAe,OAASA,IAAe,KAAM,MAAO,EAE1G,CAEA,SAASC,GAAoBF,EAA4D,CACvF,GAAIA,GAAO,KAAM,OACjB,IAAMC,EAAaD,EAAI,KAAK,EAAE,YAAY,EAC1C,GAAIC,IAAe,UAAW,MAAO,UACrC,GAAIA,IAAe,cAAgBA,IAAe,OAASA,IAAe,WACxE,MAAO,aAET,GAAIA,IAAe,aAAeA,IAAe,MAAQA,IAAe,UACtE,MAAO,WAGX,CAEA,SAASE,IAAmC,CAC1C,IAAMC,EAAwB,CAAC,EAE/B,GAAI,OAAO,OAAW,IAAa,CACjC,IAAMC,EAAgB,OAAe,uBACrC,GAAIA,EAAc,CAIhB,GAHI,OAAOA,EAAa,iBAAoB,YAC1CD,EAAO,gBAAkBC,EAAa,iBAEpC,OAAOA,EAAa,gBAAmB,SAAU,CACnD,IAAMC,EAASJ,GAAoBG,EAAa,cAAc,EAC1DC,IAAQF,EAAO,eAAiBE,EACtC,CACI,OAAOD,EAAa,gBAAmB,YACzCD,EAAO,eAAiBC,EAAa,gBAEnC,OAAOA,EAAa,aAAgB,YACtCD,EAAO,YAAcC,EAAa,aAEhC,OAAOA,EAAa,iBAAoB,YAC1CD,EAAO,gBAAkBC,EAAa,gBAE1C,CACF,CAEA,GAAI,OAAO,SAAa,IAAa,CACnC,IAAME,EAAS,SAAS,cACxB,GAAIA,EAAQ,CACV,IAAMC,EAAiBT,GAAiBQ,EAAO,aAAa,wBAAwB,CAAC,EACjFC,IAAmB,SACrBJ,EAAO,gBAAkBI,GAE3B,IAAMC,EAAeP,GACnBK,EAAO,aAAa,6BAA6B,CACnD,EACIE,IAAiB,SACnBL,EAAO,eAAiBK,GAE1B,IAAMC,EAAeX,GAAiBQ,EAAO,aAAa,6BAA6B,CAAC,EACpFG,IAAiB,SACnBN,EAAO,eAAiBM,GAE1B,IAAMC,EAAsBZ,GAAiBQ,EAAO,aAAa,wBAAwB,CAAC,EACtFI,IAAwB,SAC1BP,EAAO,YAAcO,GAEvB,IAAMC,EAAsBb,GAAiBQ,EAAO,aAAa,6BAA6B,CAAC,EAC3FK,IAAwB,SAC1BR,EAAO,gBAAkBQ,EAE7B,CACF,CAEA,OAAOR,CACT,CAEA,SAASS,GACPC,EACAC,EACAC,EACM,CACN,GAAI,CAACpB,GAAqB,OAE1B,IAAML,EAAM,GAAGuB,CAAI,IAAIE,CAAM,IAAID,CAAI,GAC/BE,EAAM,KAAK,IAAI,EACfC,EAAWpB,GAAY,IAAIP,CAAG,EAEhC2B,GACFA,EAAS,OAAS,EAClBA,EAAS,WAAaD,IAEtBnB,GAAY,IAAIP,EAAK,CACnB,KAAAuB,EACA,KAAAC,EACA,OAAAC,EACA,MAAO,EACP,YAAaC,EACb,WAAYA,CACd,CAAC,EACD,QAAQ,KAAK,aAAaD,CAAM,KAAKD,CAAI,EAAE,GAG7C,GAAI,CACF,GAAI,OAAO,OAAW,IAAa,CACjC,IAAMI,EAAS,CACb,KAAAL,EACA,KAAAC,EACA,OAAAC,EACA,MAAOlB,GAAY,IAAIP,CAAG,GAAG,OAAS,CACxC,EACA,OAAO,cAAc,IAAI,YAAY,qBAAsB,CAAE,OAAA4B,CAAO,CAAC,CAAC,CACxE,CACF,MAAQ,CAER,CACF,CAGA,IAAMC,GAAsBlB,GAEtB,SAEN,EAEIkB,KACF1B,EAAkB0B,GACd1B,IAAoB,eAAcC,EAAmB,IACrDD,IAAoB,cAAaC,EAAmB,IACpDD,IAAoB,YAAWC,EAAmB,KAGxD,IAAM0B,GAAgBlB,GAAkB,EAClCmB,GAAmBD,GAAc,eACnC,aACAA,GAAc,eACdC,KACF5B,EAAkB4B,GACd5B,IAAoB,eAAcC,EAAmB,IACrDD,IAAoB,cAAaC,EAAmB,KAGxDD,IAAoB,WACjB,OAAO2B,GAAc,iBAAoB,YAE5C1B,EAAmB0B,GAAc,iBAE/B,OAAOA,GAAc,aAAgB,YACvCzB,GAAsByB,GAAc,aAEtC,IAAME,GAAmBF,GAAc,kBAAoB,GAU3D,SAASG,IAA0C,CACjD,IAAMC,EAAa,YAAoB,UACvC,GAAKA,IACD,OAAOA,EAAU,OAAU,YAAc,OAAOA,EAAU,UAAa,YACzE,OAAOA,CAGX,CAGA,eAAeC,IAA6B,CAC1C,IAAMC,EAAYH,GAAa,EAC/B,GAAIG,GAAW,MAAO,CACpB,MAAMA,EAAU,MAAM,EACtB,MACF,CACA,GAAIA,GAAW,SAAU,CACvB,MAAMA,EAAU,SAAS,IAAM,CAAC,EAAG,CAAE,SAAU,YAAa,CAAC,EAC7D,MACF,CACA,MAAM,IAAI,QAAeC,GAAY,WAAWA,EAAS,CAAC,CAAC,CAC7D,CAWA,SAASC,GACPC,EAAmB,SACnBC,EAAmC,CAAC,EAC5B,CACR,IAAMC,EAAWD,EAAQ,UAAY,uBAErC,GADI,CAACC,GACD,OAAQF,EAAoB,kBAAqB,WAAY,MAAO,GAExE,IAAMG,EAAQH,EAAK,iBAAiBE,CAAQ,EACxCE,EAAU,EACd,QAASC,EAAI,EAAGA,EAAIF,EAAM,OAAQE,IAAK,CACrC,IAAMC,EAAKH,EAAME,CAAC,EAClB,GAAI,CAACC,GAAI,MAAO,SAEhB,IAAMC,EAAUD,EAAG,aAAa,oBAAoB,GAAKL,EAAQ,SAAW,qBACtEO,EAAoBF,EAAG,aAAa,+BAA+B,GACpEL,EAAQ,mBACR,OACCQ,EAAuBH,EAAG,aAAa,mCAAmC,GAC3EL,EAAQ,sBACR,aACCS,EAAeT,EAAQ,mBAAqB,GAC9CU,EAAU,GAERC,EAAiBN,EAAG,MAAM,iBAAiB,SAAS,EACpDO,EAAoBP,EAAG,MAAM,iBAAiB,oBAAoB,EAClEQ,EAAqBR,EAAG,MAAM,iBAAiB,wBAAwB,EAEzEC,IAAY,QAAU,CAACG,GAAgB,CAACE,KAC1CN,EAAG,MAAM,YAAY,UAAWC,CAAO,EACvCI,EAAU,IAERH,IAAsB,QAAU,CAACE,GAAgB,CAACG,KACpDP,EAAG,MAAM,YAAY,qBAAsBE,CAAiB,EAC5DG,EAAU,IAERF,IAAyB,QAAU,CAACC,GAAgB,CAACI,KACvDR,EAAG,MAAM,YAAY,yBAA0BG,CAAoB,EACnEE,EAAU,IAGRA,GAASP,GACf,CAEA,OAAIjD,GAAUiD,EAAU,GACtBhD,EAAI,oCAAqCgD,EAAS,YAAY,EAEzDA,CACT,CAIA,IAAMW,GAAmB,YACnBC,GAAmB,YACnBC,GAAY,kBACZC,GAAgB,kBAChBC,GAAgB,iBAEtB,IAAMC,GAAa,mCACbC,GAAa,kCACbC,GAAa,wBACbC,GAAS,sBACTC,GAAQ,wBACRC,GAAgB,6CAChBC,GAAS,2BACTC,GAAS,0BACTC,GAAkB,cAClBC,GAAqB,iBAE3B,IAAMC,GAAuB,4BACvBC,GAAkB,WAExB,IAAMC,GAAgB,QAChBC,GAAe,mBACfC,GAAc,mBACdC,GAAY,uBACZC,GAAY,qBACZC,GAAc,oCACdC,GAAe,QAGfC,GAAc,qBACdC,GAAW,8BACXC,GAAkB,wCAClBC,GAAuB,kBAGvBC,GAAe,4BACfC,GAAkB,wCAkBlBC,GAAuB,OAAO,IAAI,wBAAwB,EAM1DC,GAAuB,KACvBC,GAAkB,IAAI,IAC5B,SAASC,GAAgBC,EAAaC,EAAkC,CACtE,GAAIH,GAAgB,MAAQD,GAAsB,CAEhD,IAAMK,EAAQJ,GAAgB,KAAK,EAAE,KAAK,EAAE,MACxCI,IAAU,QAAWJ,GAAgB,OAAOI,CAAK,CACvD,CACAJ,GAAgB,IAAIE,EAAKC,CAAO,CAClC,CACA,IAAIE,GAAuB,IAAI,QAO3BC,GAAoB,IAAI,QAUtBC,GAAwB,IAAI,IAC5BC,GAA8B,KACpC,SAASC,GAAsBP,EAAaQ,EAAkC,CAC5E,GAAIH,GAAsB,MAAQC,GAA6B,CAE7D,IAAMJ,EAAQG,GAAsB,KAAK,EAAE,KAAK,EAAE,MAC9CH,IAAU,QAAWG,GAAsB,OAAOH,CAAK,CAC7D,CACAG,GAAsB,IAAIL,EAAKQ,CAAQ,CACzC,CACA,IAAMC,GAAsB,IAAI,IAAI,CAClC,cAAe,YAAa,YAC5B,mBAAoB,mBAAoB,mBAAoB,mBAC5D,OAAQ,UACV,CAAC,EAMKC,IAAqF,IAAM,CAC/F,IAAMC,EAAoE,CAAC,EAC3E,QAAWC,KAAQH,GAAqB,CACtC,IAAMI,EAAUD,EAAK,QAAQ,sBAAuB,MAAM,EAC1DD,EAAO,KAAK,CACV,KAAAC,EAEA,MAAO,IAAI,OAAO,YAAYC,CAAO,4BAA6B,GAAG,EAErE,UAAW,IAAI,OAAO,cAAcA,CAAO,MAAMA,CAAO,OAAaA,EAAU,WAAgB,CACjG,CAAC,CACH,CACA,OAAOF,CACT,GAAG,EAeH,SAASG,GAAkBC,EAA6B,CAEtD,IAAIC,EAAUD,EAAK,QAAQ,oBAAqB,EAAE,EAElDC,EAAUA,EAAQ,QAAQ,cAAe,EAAE,EAE3CA,EAAUA,EAAQ,QAAQ,YAAa,GAAG,EAE1C,OAAW,CAAE,KAAAJ,EAAM,MAAAK,EAAO,UAAAC,CAAU,IAAKR,GAEvC,GADIO,EAAM,KAAKD,CAAO,GAClBE,EAAU,KAAKF,CAAO,EAAG,OAAOJ,EAOtC,GAAII,EAAQ,SAAS,GAAG,EAAG,CACzB,IAAMG,EAAkBC,GAAuBJ,CAAO,EACtD,QAAWK,KAAWF,EAAiB,CAErC,GAAI,CAACE,EAAQ,SAAS,GAAG,EAAG,SAE5B,IAAMC,EAAYD,EAAQ,MAAM,uBAAuB,EACvD,GAAI,CAACC,EAAW,SAChB,IAAMC,EAASD,EAAU,IAAIE,GAAKA,EAAE,MAAM,EAAG,EAAE,CAAC,EAAE,KAAK,EAAE,EACzD,GAAIf,GAAoB,IAAIc,CAAM,EAAG,OAAOA,CAC9C,CACF,CAEA,OAAO,IACT,CAGA,SAASH,GAAuBL,EAAwB,CACtD,IAAMU,EAAoB,CAAC,EACvBC,EAAQ,EACRC,EAAQ,GACZ,QAAS,EAAI,EAAG,EAAIZ,EAAK,OAAQ,IAC3BA,EAAK,CAAC,IAAM,KACVW,IAAU,IAAGC,EAAQ,EAAI,GAC7BD,KACSX,EAAK,CAAC,IAAM,MACrBW,IACIA,IAAU,GAAKC,GAAS,IAC1BF,EAAQ,KAAKV,EAAK,MAAMY,EAAO,CAAC,CAAC,EACjCA,EAAQ,KAId,OAAOF,CACT,CAEA,IAAMG,GAAmB,OAAO,IAAI,0BAA0B,EAQ9D,SAASC,GAAYC,EAAwB,CAC3C,OAAIA,GAAS,KAAa,GACtB,OAAOA,GAAU,SAAiBA,EAClC,OAAOA,GAAU,SAAiBA,EAAM,SAAS,EAC9C,OAAOA,CAAK,CACrB,CAEA,SAASC,GAAmBC,EAAaC,EAAoB,CAC3D,IAAIC,EAASF,EAAWJ,EAAgB,EAMxC,GALKM,IACHA,EAAQ,CAAE,YAAa,GAAO,KAAM,GAAI,KAAM,IAAK,EAClDF,EAAWJ,EAAgB,EAAIM,GAG9BA,EAAM,aAAeA,EAAM,OAASD,EAAM,OAG9C,IAAIE,EAAOD,EAAM,KACjB,GAAI,CAACC,GAAQA,EAAK,aAAeH,GAAMA,EAAG,WAAW,SAAW,GAAKA,EAAG,aAAeG,EACrF,GAAIH,EAAG,WAAW,SAAW,GAAKA,EAAG,YAAY,WAAa,KAAK,UACjEG,EAAOH,EAAG,WACVE,EAAM,KAAOC,MACR,CACLH,EAAG,YAAcC,EACjB,IAAM/B,EAAQ8B,EAAG,WACjBE,EAAM,KAAQhC,GAASA,EAAM,WAAa,KAAK,WAAa8B,EAAG,WAAW,SAAW,EAChF9B,EACD,KACJgC,EAAM,KAAOD,EACbC,EAAM,YAAc,GACpB,MACF,CAGFC,EAAK,KAAOF,EACZC,EAAM,KAAOD,EACbC,EAAM,YAAc,EACtB,CAEA,SAASE,GAAcC,EAAuB,CAC5C,IAAMC,EAAgB,CAAC,EACvB,GAAID,EAAI,KAAK,IAAM,GAAI,OAAOC,EAE9B,IAAIZ,EAAQ,EACRa,EAAW,GACXC,EAAW,GACX3B,EAAU,GACVc,EAAQ,EAEZ,QAASc,EAAI,EAAGA,EAAIJ,EAAI,OAAQI,IAAK,CACnC,IAAMC,EAAKL,EAAII,CAAC,EAEhB,GAAI5B,EAAS,CACXA,EAAU,GACV,QACF,CAEA,GAAI6B,IAAO,KAAM,CACf7B,EAAU,GACV,QACF,CAEA,GAAI0B,EAAU,CACRG,IAAO,MAAMH,EAAW,IAC5B,QACF,CACA,GAAIC,EAAU,CACRE,IAAO,MAAKF,EAAW,IAC3B,QACF,CAEA,GAAIE,IAAO,IAAM,CACfH,EAAW,GACX,QACF,CACA,GAAIG,IAAO,IAAK,CACdF,EAAW,GACX,QACF,CAEA,GAAIE,IAAO,IAAK,CACdhB,IACA,QACF,CACA,GAAIgB,IAAO,IAAK,CACVhB,EAAQ,GAAGA,IACf,QACF,CAEIgB,IAAO,KAAOhB,IAAU,IAC1BY,EAAI,KAAKD,EAAI,MAAMV,EAAOc,CAAC,EAAE,KAAK,CAAC,EACnCd,EAAQc,EAAI,EAEhB,CAEA,OAAAH,EAAI,KAAKD,EAAI,MAAMV,CAAK,EAAE,KAAK,CAAC,EACzBW,EAAI,OAAO,OAAO,CAC3B,CAEA,SAASK,GACPC,EACAjB,EACAkB,EACAC,EACuC,CACvC,GAAIF,EAAMjB,CAAK,IAAMkB,EAAM,OAAO,KAElC,IAAInB,EAAQ,EACRa,EAAW,GACXC,EAAW,GACXO,EAAa,GACblC,EAAU,GAEd,QAAS4B,EAAId,EAAOc,EAAIG,EAAM,OAAQH,IAAK,CACzC,IAAMC,EAAKE,EAAMH,CAAC,EAElB,GAAI5B,EAAS,CACXA,EAAU,GACV,QACF,CAEA,GAAI6B,IAAO,OAASH,GAAYC,GAAYO,GAAa,CACvDlC,EAAU,GACV,QACF,CAEA,GAAI0B,EAAU,CACRG,IAAO,MAAMH,EAAW,IAC5B,QACF,CACA,GAAIC,EAAU,CACRE,IAAO,MAAKF,EAAW,IAC3B,QACF,CACA,GAAIO,EAAY,CACVL,IAAO,MAAKK,EAAa,IAC7B,QACF,CAEA,GAAIL,IAAO,IAAM,CACfH,EAAW,GACX,QACF,CACA,GAAIG,IAAO,IAAK,CACdF,EAAW,GACX,QACF,CACA,GAAIE,IAAO,IAAK,CACdK,EAAa,GACb,QACF,CAEA,GAAIL,IAAOG,EAAM,CACfnB,IACA,QACF,CACA,GAAIgB,IAAOI,IACTpB,IACIA,IAAU,GACZ,MAAO,CACL,MAAOkB,EAAM,MAAMjB,EAAQ,EAAGc,CAAC,EAC/B,IAAKA,CACP,CAGN,CAEA,OAAO,IACT,CAEA,SAASO,GAAwBX,EAAuB,CACtD,IAAMO,EAAQP,EAAI,KAAK,EACvB,GAAI,CAACO,EAAO,MAAO,CAAC,EAEpB,IAAMN,EAAgB,CAAC,EACnBW,EAAa,EACbC,EAAa,EACbC,EAAe,EACfZ,EAAW,GACXC,EAAW,GACXO,EAAa,GACblC,EAAU,GACVc,EAAQ,EAEZ,QAASc,EAAI,EAAGA,EAAIG,EAAM,OAAQH,IAAK,CACrC,IAAMC,EAAKE,EAAMH,CAAC,EAElB,GAAI5B,EAAS,CACXA,EAAU,GACV,QACF,CAEA,GAAI6B,IAAO,OAASH,GAAYC,GAAYO,GAAa,CACvDlC,EAAU,GACV,QACF,CAEA,GAAI0B,EAAU,CACRG,IAAO,MAAMH,EAAW,IAC5B,QACF,CACA,GAAIC,EAAU,CACRE,IAAO,MAAKF,EAAW,IAC3B,QACF,CACA,GAAIO,EAAY,CACVL,IAAO,MAAKK,EAAa,IAC7B,QACF,CAEA,GAAIL,IAAO,IAAM,CACfH,EAAW,GACX,QACF,CACA,GAAIG,IAAO,IAAK,CACdF,EAAW,GACX,QACF,CACA,GAAIE,IAAO,IAAK,CACdK,EAAa,GACb,QACF,CASA,GAPIL,IAAO,IAAKO,IACPP,IAAO,KAAOO,EAAa,EAAGA,IAC9BP,IAAO,IAAKQ,IACZR,IAAO,KAAOQ,EAAa,EAAGA,IAC9BR,IAAO,IAAKS,IACZT,IAAO,KAAOS,EAAe,GAAGA,IAErCT,IAAO,KAAOO,IAAe,GAAKC,IAAe,GAAKC,IAAiB,EAAG,CAC5E,IAAMC,EAAOR,EAAM,MAAMjB,EAAOc,CAAC,EAAE,KAAK,EACpCW,GAAMd,EAAI,KAAKc,CAAI,EACvBzB,EAAQc,EAAI,CACd,CACF,CAEA,IAAMY,EAAOT,EAAM,MAAMjB,CAAK,EAAE,KAAK,EACrC,OAAI0B,GAAMf,EAAI,KAAKe,CAAI,EAChBf,CACT,CAEA,SAASgB,GAAiBjB,EAAoD,CAC5E,IAAMO,EAAQP,EAAI,KAAK,EACvB,GAAI,CAACO,EAAO,OAAO,KAEnB,GAAIA,EAAM,WAAW,GAAG,EAAG,CACzB,IAAMW,EAAQZ,GAAoBC,EAAO,EAAG,IAAK,GAAG,EACpD,GAAI,CAACW,EAAO,OAAO,KACnB,IAAMC,EAAOD,EAAM,MAAM,KAAK,EAC1BE,EAAOb,EAAM,MAAMW,EAAM,IAAM,CAAC,EAAE,KAAK,EAC3C,OAAIE,EAAK,WAAW,GAAG,IAAGA,EAAOA,EAAK,MAAM,CAAC,EAAE,KAAK,GAC7C,CAAE,KAAAD,EAAM,KAAAC,CAAK,CACtB,CAEA,IAAIR,EAAa,EACbC,EAAa,EACbC,EAAe,EACfZ,EAAW,GACXC,EAAW,GACXO,EAAa,GACblC,EAAU,GAEd,QAAS4B,EAAI,EAAGA,EAAIG,EAAM,OAAQH,IAAK,CACrC,IAAMC,EAAKE,EAAMH,CAAC,EAElB,GAAI5B,EAAS,CACXA,EAAU,GACV,QACF,CAEA,GAAI6B,IAAO,OAASH,GAAYC,GAAYO,GAAa,CACvDlC,EAAU,GACV,QACF,CAEA,GAAI0B,EAAU,CACRG,IAAO,MAAMH,EAAW,IAC5B,QACF,CACA,GAAIC,EAAU,CACRE,IAAO,MAAKF,EAAW,IAC3B,QACF,CACA,GAAIO,EAAY,CACVL,IAAO,MAAKK,EAAa,IAC7B,QACF,CAEA,GAAIL,IAAO,IAAM,CACfH,EAAW,GACX,QACF,CACA,GAAIG,IAAO,IAAK,CACdF,EAAW,GACX,QACF,CACA,GAAIE,IAAO,IAAK,CACdK,EAAa,GACb,QACF,CASA,GAPIL,IAAO,IAAKO,IACPP,IAAO,KAAOO,EAAa,EAAGA,IAC9BP,IAAO,IAAKQ,IACZR,IAAO,KAAOQ,EAAa,EAAGA,IAC9BR,IAAO,IAAKS,IACZT,IAAO,KAAOS,EAAe,GAAGA,IAErCT,IAAO,KAAOO,IAAe,GAAKC,IAAe,GAAKC,IAAiB,EACzE,MAAO,CACL,KAAMP,EAAM,MAAM,EAAGH,CAAC,EAAE,KAAK,EAC7B,KAAMG,EAAM,MAAMH,EAAI,CAAC,EAAE,KAAK,CAChC,CAEJ,CAEA,MAAO,CACL,KAAMG,EACN,KAAM,EACR,CACF,CAEA,SAASc,GAAe3C,EAAc4C,EAA2C,CAC/E,IAAMf,EAAQ7B,EAAK,KAAK,EAKxB,GAJI,CAAC1B,GAAa,KAAKuD,CAAK,GAIxBlD,GAAa,KAAKkD,CAAK,EAAG,OAAO,KAErC,IAAIgB,EAAM,EACV,KAAOA,EAAMhB,EAAM,QAAU,KAAK,KAAKA,EAAMgB,CAAG,CAAE,GAAGA,IACrD,GAAIhB,EAAMgB,CAAG,IAAM,IAAK,OAAO,KAE/B,IAAMC,EAAclB,GAAoBC,EAAOgB,EAAK,IAAK,GAAG,EAC5D,GAAI,CAACC,EAAa,OAAO,KAEzB,IAAMC,EAAWC,EAAgBF,EAAY,MAAM,KAAK,EAAGF,CAAK,EAChE,GAAI,CAACG,EAAU,OAAO,KAEtB,IAAIL,EAAOb,EAAM,MAAMiB,EAAY,IAAM,CAAC,EAAE,KAAK,EAC3CG,EAAWV,GAAiBG,CAAI,EACtC,GAAI,CAACO,GAAY,CAACA,EAAS,KAAM,OAAO,KAExC,IAAMC,EAAcC,GAAaF,EAAS,KAAML,CAAK,EACrD,GAAI,CAACM,EAAa,OAAO,KAEzBR,EAAOO,EAAS,KAAK,KAAK,EAC1B,IAAIG,EAA2C,KAC/C,GAAIV,EAAK,WAAW,MAAM,EAAG,CAC3BA,EAAOA,EAAK,MAAM,CAAa,EAAE,KAAK,EACtC,IAAMW,EAAWd,GAAiBG,CAAI,EAGtC,GAFI,CAACW,GAAY,CAACA,EAAS,OAC3BD,EAAcD,GAAaE,EAAS,KAAMT,CAAK,EAC3C,CAACQ,GAAa,OAAO,KACzBV,EAAOW,EAAS,KAAK,KAAK,CAC5B,CAEA,OAAIX,EAAK,OAAS,EAAU,KAEpBY,GAAa,CACnBC,EAAM,IAAM,CACNR,EAAS,EAAGG,EAAYI,CAAC,EACxBF,IAAcE,CAAC,CACtB,CAAC,CACH,CACF,CAEA,SAASE,GAAkBlC,EAAqB,CAC9C,IAAItB,EAAOsB,EAAI,KAAK,EACpB,KAAOtB,EAAK,WAAW,GAAG,GAAG,CAC3B,IAAMyD,EAAU7B,GAAoB5B,EAAM,EAAG,IAAK,GAAG,EACrD,GAAI,CAACyD,GAAWA,EAAQ,MAAQzD,EAAK,OAAS,EAAG,MACjD,IAAM0D,EAAQD,EAAQ,MAAM,KAAK,EACjC,GAAI,CAACC,EAAO,MACZ1D,EAAO0D,CACT,CACA,OAAO1D,CACT,CAEA,SAAS2D,GAAgBC,EAAgC,CACvD,IAAMC,EAASvE,GAAsB,IAAIsE,CAAI,EAC7C,GAAIC,EAAQ,OAAOA,EAEnB,IAAMC,EAAoB,CAAC,EACrBC,EAAqB,CAAC,EACxBC,EAAY,EAEVC,EAAK,oBACPC,EACJ,MAAQA,EAAID,EAAG,KAAKL,CAAI,KAAO,MAC7BE,EAAQ,KAAKF,EAAK,MAAMI,EAAWE,EAAE,KAAK,CAAC,EAC3CH,EAAS,KAAKG,EAAE,CAAC,CAAE,EACnBF,EAAYC,EAAG,UAEjBH,EAAQ,KAAKF,EAAK,MAAMI,CAAS,CAAC,EAElC,IAAMpE,EAA2B,CAC/B,QAAAkE,EACA,SAAAC,EACA,WAAYA,EAAS,OAAS,CAChC,EACA,OAAAvE,GAAsBoE,EAAMhE,CAAM,EAC3BA,CACT,CAKA,IAAMuE,GAAgB,IAAI,QAe1B,SAASC,GAAyBC,EAA4BC,EAAuB,CACnF,GAAI,CAACD,EAAS,WAAY,OAAOA,EAAS,QAAQ,CAAC,EACnD,IAAIE,EAASF,EAAS,QAAQ,CAAC,EAC/B,QAASG,EAAI,EAAGA,EAAIH,EAAS,SAAS,OAAQG,IAAK,CACjD,IAAMC,EAAMJ,EAAS,SAASG,CAAC,EAC1BC,EAGHF,GAAU,OAAQD,IAAmCG,CAAG,GAAK,EAAE,EAF/DF,GAAU,OAAOD,GAAS,SAAW,KAAK,UAAUA,CAAI,EAAI,OAAOA,GAAQ,EAAE,EAI/EC,GAAUF,EAAS,QAAQG,EAAI,CAAC,GAAK,EACvC,CACA,OAAOD,CACT,CAMA,SAASG,GAAsBC,EAAmBL,EAAwB,CACxE,IAAMM,EAAQD,EAAS,UAAU,EAAI,EAC/BE,EAAS,SAAS,iBAAiBD,EAAO,WAAW,SAAS,EACpE,KAAOC,EAAO,SAAS,GAAG,CACxB,IAAMC,EAAOD,EAAO,YACdE,EAAOD,EAAK,aAAe,GACjC,GAAIC,EAAK,SAAS,OAAO,EAAG,CAC1B,IAAMV,EAAWW,GAAgBD,CAAI,EACrCE,GAAc,IAAIH,EAAMT,CAAQ,EAChCS,EAAK,YAAcV,GAAyBC,EAAUC,CAAI,CAC5D,CACF,CAEA,OAAAY,GAAwBN,EAAON,CAAI,EAC5BM,CACT,CAMA,SAASO,GAAmBC,EAAad,EAAqB,CAC5D,IAAMO,EAAS,SAAS,iBAAiBO,EAAI,WAAW,SAAS,EACjE,KAAOP,EAAO,SAAS,GAAG,CACxB,IAAMC,EAAOD,EAAO,YACdR,EAAWY,GAAc,IAAIH,CAAI,EACnCT,IACFS,EAAK,YAAcV,GAAyBC,EAAUC,CAAI,EAE9D,CACF,CAGA,IAAMe,GAAgB,IAAI,QASpBC,GAA0B,CAC9B,YAAa,YAAa,YAAa,UAAW,aAClD,WAAY,cAAe,aAAc,gBAAiB,eAAgB,aAC1E,kBAAmB,kBACrB,EACA,SAASC,GAAgBC,EAAuB,CAC9C,QAAWC,KAAUH,GACnB,GAAIE,IAASC,GAAUD,EAAK,WAAWC,CAAM,EAAG,MAAO,GAEzD,MAAO,EACT,CAEA,SAASC,GAAiBC,EAA8B,CACtD,OAAKA,EACEA,EACJ,KAAK,EACL,MAAM,KAAK,EACX,IAAK,GAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO,EALA,CAAC,CAMpB,CAEA,SAASC,GAAqBC,EAA8B,CAC1D,IAAM,EAAIA,EAAM,KAAK,EAAE,YAAY,EACnC,GAAI,EAAE,SAAS,IAAI,EAAG,CACpB,IAAM,EAAI,OAAO,EAAE,MAAM,EAAG,EAAE,CAAC,EAC/B,OAAO,OAAO,SAAS,CAAC,GAAK,GAAK,EAAI,EAAI,IAC5C,CACA,GAAI,EAAE,SAAS,GAAG,EAAG,CACnB,IAAM,EAAI,OAAO,EAAE,MAAM,EAAG,EAAE,CAAC,EAC/B,OAAO,OAAO,SAAS,CAAC,GAAK,GAAK,EAAI,EAAI,IAAO,IACnD,CACA,OAAO,IACT,CAEA,SAASC,GAA4BH,EAAgE,CACnG,IAAMI,EAAoB,CAAC,EACvBC,EACJ,QAAWH,KAASH,GAAiBC,CAAG,EAAG,CACzC,IAAMM,EAASL,GAAqBC,CAAK,EACrCI,GAAU,KACZD,EAAaC,EAEbF,EAAQ,KAAKF,CAAK,CAEtB,CACA,MAAO,CAAE,QAAAE,EAAS,WAAAC,CAAW,CAC/B,CAEA,SAASE,EAAaC,EAA4B,CAChD,OAAO,MAAM,KAAK,IAAI,IAAIA,EAAO,OAAO,OAAO,CAAC,CAAC,CACnD,CAEA,SAASC,GAAmBT,EAAuB,CACjD,OAAKA,EACEA,EACJ,MAAM,GAAG,EACT,IAAKU,GAAST,GAAqBS,EAAK,KAAK,CAAC,CAAC,EAC/C,OAAQC,GAAqBA,GAAM,IAAI,EAJzB,CAAC,CAKpB,CAEA,SAASC,GAAqBC,EAAqBC,EAA0B,CAC3E,GAAID,EAAU,SAAW,GAAKC,EAAO,SAAW,EAAG,MAAO,GAC1D,GAAID,EAAU,SAAW,EAAG,OAAO,KAAK,IAAI,GAAGC,EAAQ,CAAC,EACxD,GAAIA,EAAO,SAAW,EAAG,OAAO,KAAK,IAAI,GAAGD,EAAW,CAAC,EAExD,IAAME,EAAM,KAAK,IAAIF,EAAU,OAAQC,EAAO,MAAM,EAChDE,EAAM,EACV,QAAS,EAAI,EAAG,EAAID,EAAK,IAAK,CAC5B,IAAME,EAAIJ,EAAU,EAAIA,EAAU,MAAM,GAAK,EACvCK,EAAQJ,EAAO,EAAIA,EAAO,MAAM,GAAK,EACvCG,EAAIC,EAAQF,IAAKA,EAAMC,EAAIC,EACjC,CACA,OAAOF,CACT,CAEA,SAASG,GAA4B1B,EAAiB2B,EAA6B,CACjF,GAAI,OAAOA,GAAe,SAAU,OAAOA,EAC3C,IAAMC,EAAK,OAAO,iBAAiB5B,CAAE,EAC/B6B,EAAQV,GACZH,GAAmBY,EAAG,kBAAkB,EACxCZ,GAAmBY,EAAG,eAAe,CACvC,EACME,EAAOX,GACXH,GAAmBY,EAAG,iBAAiB,EACvCZ,GAAmBY,EAAG,cAAc,CACtC,EACA,OAAO,KAAK,IAAIC,EAAOC,CAAI,CAC7B,CAEA,SAASC,EAAmB/B,EAAyC,CACnE,IAAMgC,EAAYhC,EAAWiC,EAAoB,EACjD,GAAID,EAAU,OAAOA,EACrB,IAAME,EAAkC,CAAE,MAAO,EAAG,OAAQ,IAAK,EACjE,OAAClC,EAAWiC,EAAoB,EAAIC,EAC7BA,CACT,CAEA,SAASC,GAAqBnC,EAAuB,CACnD,IAAMoC,EAASpC,EAAWiC,EAAoB,EAC1CG,GAAO,QACTA,EAAM,OAAO,EAEf,OAAQpC,EAAWiC,EAAoB,CACzC,CAEA,SAASI,GAAoBrC,EAAoC,CAG/D,GAAI,EAFsBA,EAAG,aAAa,iBAAiB,GACtD,MAAM,KAAKA,EAAG,UAAU,EAAE,KAAMsC,GAAMA,EAAE,KAAK,WAAW,kBAAkB,CAAC,GACxD,OAAO,KAE/B,IAAMC,EAAO7B,GAA4BV,EAAG,aAAa,iBAAiB,CAAC,EAAE,QAEvEwC,EAAQ9B,GAA4BV,EAAG,aAAa,uBAAuB,CAAC,EAC5EyC,EAAQ/B,GAA4BV,EAAG,aAAa,uBAAuB,CAAC,EAC5E0C,EAAYpC,GAChBN,EAAG,aAAa,4BAA4B,GACzCA,EAAG,aAAa,6BAA6B,CAClD,EACM2C,EAAUrC,GACdN,EAAG,aAAa,0BAA0B,GACvCA,EAAG,aAAa,2BAA2B,CAChD,EACM4C,EAAYtC,GAChBN,EAAG,aAAa,4BAA4B,GACzCA,EAAG,aAAa,6BAA6B,CAClD,EACM6C,EAAUvC,GACdN,EAAG,aAAa,0BAA0B,GACvCA,EAAG,aAAa,2BAA2B,CAChD,EAEM8C,EAAetC,GAAqBR,EAAG,aAAa,0BAA0B,GAAK,EAAE,EACrF+C,EAAgBvC,GAAqBR,EAAG,aAAa,gCAAgC,GAAK,EAAE,GAC7FwC,EAAM,YACNM,GACA,OACCE,EAAgBxC,GAAqBR,EAAG,aAAa,gCAAgC,GAAK,EAAE,GAC7FyC,EAAM,YACNK,GACA,OAEL,MAAO,CACL,MAAOhC,EAAa,CAAC,GAAGyB,EAAM,GAAGC,EAAM,OAAO,CAAC,EAC/C,UAAW1B,EAAa4B,CAAS,EACjC,QAAS5B,EAAa6B,CAAO,EAC7B,MAAO7B,EAAa,CAAC,GAAGyB,EAAM,GAAGE,EAAM,OAAO,CAAC,EAC/C,UAAW3B,EAAa8B,CAAS,EACjC,QAAS9B,EAAa+B,CAAO,EAC7B,gBAAiBE,EACjB,gBAAiBC,CACnB,CACF,CAEA,SAASC,GAAcjD,EAAaW,EAAyB,CAC3D,QAAWuC,KAAOvC,EAChBX,EAAG,UAAU,OAAOkD,CAAG,CAE3B,CAEA,SAASC,GAAWnD,EAAaW,EAAyB,CACxD,QAAWuC,KAAOvC,EAChBX,EAAG,UAAU,IAAIkD,CAAG,CAExB,CAEA,SAASE,GACPpD,EACAqD,EACAC,EACY,CACZ,IAAMC,EAAiBzC,EAAa,CAClC,GAAGuC,EAAa,KAChB,GAAGA,EAAa,KAChB,GAAGA,EAAa,EAClB,CAAC,EAEGG,EAAO,GACPC,EAA2B,KAC3BC,EAAsB,KACtBC,EAAsB,KAEpBC,EAAS,IAAM,CACfJ,IACJA,EAAO,GACHC,GAAa,MAAM,OAAO,aAAaA,CAAS,EAChDC,GAAQ,MAAM,qBAAqBA,CAAI,EACvCC,GAAQ,MAAM,qBAAqBA,CAAI,EAC3CV,GAAcjD,EAAIuD,CAAc,EAChCD,EAAO,EACT,EAEA,OAAAH,GAAWnD,EAAIqD,EAAa,IAAI,EAChCF,GAAWnD,EAAIqD,EAAa,IAAI,EAChCJ,GAAcjD,EAAIqD,EAAa,EAAE,EAEjCK,EAAO,sBAAsB,IAAM,CACjCC,EAAO,sBAAsB,IAAM,CACjC,GAAIH,EAAM,OACVP,GAAcjD,EAAIqD,EAAa,IAAI,EACnCF,GAAWnD,EAAIqD,EAAa,EAAE,EAE9B,IAAMnC,EAAKQ,GAA4B1B,EAAIqD,EAAa,UAAU,EAClE,GAAInC,GAAM,EAAG,CACX0C,EAAO,EACP,MACF,CACAH,EAAY,OAAO,WAAWG,EAAQ1C,EAAK,EAAE,CAC/C,CAAC,CACH,CAAC,EAEM0C,CACT,CAMA,SAASC,GACP7D,EACA8D,EACAC,EACAC,EACM,CAEN,GADAF,EAAO,aAAa9D,EAAI+D,CAAG,EACvB,CAACC,EAAM,OAEX,IAAM5B,EAAQL,EAAmB/B,CAAE,EACnCoC,EAAM,OAAS,EACf,IAAM3B,EAAQ2B,EAAM,MAChBA,EAAM,QAAQA,EAAM,OAAO,EAE/BA,EAAM,OAASgB,GACbpD,EACA,CACE,KAAMgE,EAAK,MACX,KAAMA,EAAK,UACX,GAAIA,EAAK,QACT,WAAYA,EAAK,eACnB,EACA,IAAM,CACJ,IAAMC,EAAUlC,EAAmB/B,CAAE,EACjCiE,EAAQ,QAAUxD,IAAOwD,EAAQ,OAAS,KAChD,CACF,CACF,CAOA,SAASC,GACPlE,EACAgE,EACAV,EACM,CAEN,GAAItD,EAAG,aAAa,oBAAoB,EAAG,CACzCsD,EAAO,EACP,MACF,CAEA,GAAI,CAACU,EAAM,CACTV,EAAO,EACP,MACF,CAEAtD,EAAG,aAAa,qBAAsB,EAAE,EAExC,IAAMoC,EAAQL,EAAmB/B,CAAE,EACnCoC,EAAM,OAAS,EACf,IAAM3B,EAAQ2B,EAAM,MAChBA,EAAM,QAAQA,EAAM,OAAO,EAE/BA,EAAM,OAASgB,GACbpD,EACA,CACE,KAAMgE,EAAK,MACX,KAAMA,EAAK,UACX,GAAIA,EAAK,QACT,WAAYA,EAAK,eACnB,EACA,IAAM,CACJ,IAAMC,EAAUlC,EAAmB/B,CAAE,EACjCiE,EAAQ,QAAUxD,IAAOwD,EAAQ,OAAS,MAC9CjE,EAAG,gBAAgB,oBAAoB,EACvCsD,EAAO,CACT,CACF,CACF,CAEA,SAASa,GACPnE,EACAoE,EACAC,EACAC,EACM,CACN,GAAI,CAACD,GAAcC,EAAS,CAC1BtE,EAAG,MAAM,QAAUoE,EAAU,GAAK,OAC9BC,GACFpB,GAAcjD,EAAIc,EAAa,CAC7B,GAAGuD,EAAW,MAAO,GAAGA,EAAW,UAAW,GAAGA,EAAW,QAC5D,GAAGA,EAAW,MAAO,GAAGA,EAAW,UAAW,GAAGA,EAAW,OAC9D,CAAC,CAAC,EAEJ,MACF,CAEA,IAAMjC,EAAQL,EAAmB/B,CAAE,EACnCoC,EAAM,OAAS,EACf,IAAM3B,EAAQ2B,EAAM,MAIpB,GAHIA,EAAM,QAAQA,EAAM,OAAO,EAC/BA,EAAM,OAAS,KAEXgC,EAAS,CACXpE,EAAG,MAAM,QAAU,GACnBoC,EAAM,OAASgB,GACbpD,EACA,CACE,KAAMqE,EAAW,MACjB,KAAMA,EAAW,UACjB,GAAIA,EAAW,QACf,WAAYA,EAAW,eACzB,EACA,IAAM,CACJ,IAAMJ,EAAUlC,EAAmB/B,CAAE,EACjCiE,EAAQ,QAAUxD,IAAOwD,EAAQ,OAAS,KAChD,CACF,EACA,MACF,CAEA7B,EAAM,OAASgB,GACbpD,EACA,CACE,KAAMqE,EAAW,MACjB,KAAMA,EAAW,UACjB,GAAIA,EAAW,QACf,WAAYA,EAAW,eACzB,EACA,IAAM,CACJ,IAAMJ,EAAUlC,EAAmB/B,CAAE,EACjCiE,EAAQ,QAAUxD,IACtBT,EAAG,MAAM,QAAU,OACnBiE,EAAQ,OAAS,KACnB,CACF,CACF,CAEA,SAASnE,GAAwBE,EAAad,EAAqB,CACjE,IAAMqF,EAAM,CAACvE,EAAI,GAAG,MAAM,KAAKA,EAAG,iBAAiB,GAAG,CAAC,CAAC,EACxD,QAAWN,KAAQ6E,EAAK,CACtB,IAAMC,EAA+D,CAAC,EACtE,QAAWC,KAAQ,MAAM,KAAK/E,EAAK,UAAU,EAE3C,GAAI,CAAAS,GAAgBsE,EAAK,IAAI,GACzBA,EAAK,MAAM,SAAS,OAAO,EAAG,CAChC,IAAMxF,EAAWW,GAAgB6E,EAAK,KAAK,EAC3CD,EAAQ,KAAK,CAAE,KAAMC,EAAK,KAAM,SAAAxF,CAAS,CAAC,EAC1CS,EAAK,aAAa+E,EAAK,KAAMzF,GAAyBC,EAAUC,CAAI,CAAC,CACvE,CAEEsF,EAAQ,OAAS,GACnBvE,GAAc,IAAIP,EAAM8E,CAAO,CAEnC,CACF,CAwBA,SAASE,GAAmBC,EAAcC,EAAsC,CAE9E,IAAIC,EAAM,EACJC,EAAaH,EAAK,MAAM,gBAAgB,EAC9C,GAAI,CAACG,EAAY,OAAO,KAExB,IAAMC,EAAWD,EAAW,CAAC,EAM7B,GALAD,EAAME,EAAS,OAGXF,GAAOF,EAAK,QAEZA,EAAKE,CAAG,IAAM,KAAO,EAAEF,EAAKE,CAAG,IAAM,KAAOF,EAAKE,EAAM,CAAC,IAAM,KAAM,OAAO,KAE/E,IAAMG,EAAqB,CAAC,EAE5B,KAAOH,EAAMF,EAAK,QAAQ,CACxB,IAAIM,EAAW,GAGf,GAAIN,EAAKE,CAAG,IAAM,KAAOF,EAAKE,EAAM,CAAC,IAAM,IACzCI,EAAW,GACXJ,GAAO,UACEF,EAAKE,CAAG,IAAM,IACvBA,GAAO,MAGP,QAAO,KAIT,IAAMK,EAAYP,EAAK,MAAME,CAAG,EAAE,MAAM,MAAM,EAC9C,GAAI,CAACK,EAAW,OAAO,KACvB,IAAM9E,EAAO8E,EAAU,CAAC,EAGxB,GAFAL,GAAOzE,EAAK,OAER+E,GAAoB,IAAI/E,CAAI,EAAG,MAAO,IAAG,GAG7C,GAAIyE,EAAMF,EAAK,QAAUA,EAAKE,CAAG,IAAM,IAAK,CAC1C,IAAMO,EAAWC,GAAoBV,EAAME,EAAK,IAAK,GAAG,EACxD,GAAI,CAACO,EAAU,OAAO,KAEtB,IAAME,EAAUF,EAAS,MAAM,KAAK,EAC9BG,EAA+B,CAAC,EACtC,QAAWC,KAAOC,GAAcH,CAAO,EAAG,CACxC,IAAMzE,EAAS6E,EAAgBF,EAAKZ,CAAK,EACzC,GAAI,CAAC/D,EAAQ,OAAO,KACpB0E,EAAO,KAAK1E,CAAM,CACpB,CAEAmE,EAAM,KAAK,CAAE,KAAM,OAAQ,KAAA5E,EAAM,SAAA6E,EAAU,OAAAM,CAAO,CAAC,EACnDV,EAAMO,EAAS,IAAM,CACvB,MACEJ,EAAM,KAAK,CAAE,KAAM,OAAQ,KAAA5E,EAAM,SAAA6E,CAAS,CAAC,CAE/C,CAMA,GAHIJ,IAAQF,EAAK,QAGbK,EAAM,SAAW,EAAG,OAAO,KAG/B,IAAMW,EAAWZ,IAAa,QACzB,IAAM,OACN,IAAMH,EAAM,QAAQG,CAAQ,IAAI,GAErC,MAAO,IAAM,CACX,IAAIa,EAAWD,EAAS,EACxB,QAAWE,KAAQb,EAAO,CACxB,GAAIY,GAAO,KACT,OAAIC,EAAK,SAAU,OAKrB,GAAIA,EAAK,OAAS,OAChBD,EAAMA,EAAIC,EAAK,IAAI,MACd,CACL,IAAMC,EAASF,EAAIC,EAAK,IAAI,EAC5B,GAAI,OAAOC,GAAW,WAAY,OAClC,IAAMC,EAAOF,EAAK,OAAQ,IAAIG,GAAMA,EAAG,CAAC,EACxCJ,EAAME,EAAO,MAAMF,EAAKG,CAAI,CAC9B,CACF,CACA,OAAOH,CACT,CACF,CASA,SAASF,EAAgBf,EAAcC,EAAsC,CAE3E,IAAMqB,EAAgBC,GAAgB,IAAIvB,CAAI,EAC9C,GAAIsB,EAAe,OAAOA,EAAcrB,CAAK,EAE7C,IAAMzF,EAASgH,GAAwBxB,EAAMC,CAAK,EAGlD,GAAIzF,IAAW,KAOb,GAAIwF,IAAS,QAAUA,IAAS,SAAWA,IAAS,QAAUA,IAAS,YAAa,CAClF,IAAMiB,EAAMjB,IAAS,OAAS,GAAOA,IAAS,QAAU,GAAQA,IAAS,OAAS,KAAO,OACzFyB,GAAgBzB,EAAM,IAAM,IAAMiB,CAAG,CACvC,SAAWS,GAAc,KAAK1B,CAAI,EAChCyB,GAAgBzB,EAAO2B,GAAM,IAAMA,EAAE,QAAQ3B,CAAI,IAAI,CAAC,UAC7C4B,GAAiB,KAAK5B,CAAI,GAAK6B,GAAiB,KAAK7B,CAAI,EAAG,CACrE,IAAMiB,EAAMjB,EAAK,MAAM,EAAG,EAAE,EAC5ByB,GAAgBzB,EAAM,IAAM,IAAMiB,CAAG,CACvC,SAAWa,GAAU,KAAK9B,CAAI,EAAG,CAC/B,IAAMiB,EAAM,OAAOjB,CAAI,EACvByB,GAAgBzB,EAAM,IAAM,IAAMiB,CAAG,CACvC,KAAO,CACL,IAAMc,EAAW/B,EAAK,MAAMgC,EAAa,EACzC,GAAID,EAAU,CACZ,IAAME,EAAKF,EAAS,CAAC,EAAIG,EAAKH,EAAS,CAAC,EACxCN,GAAgBzB,EAAO2B,GAAM,IACfA,EAAE,QAAQM,CAAE,IAAI,IACNC,CAAE,CACzB,CACH,CACF,CAGF,OAAO1H,CACT,CAMA,SAASgH,GAAwBxB,EAAcC,EAAsC,CACnFD,EAAOA,EAAK,KAAK,EAGjB,IAAMmC,EAAYC,GAAkBpC,CAAI,EACxC,GAAImC,IAAcnC,EAChB,OAAOe,EAAgBoB,EAAWlC,CAAK,EAMzC,GAAI2B,GAAiB,KAAK5B,CAAI,GAAK6B,GAAiB,KAAK7B,CAAI,EAAG,CAC9D,IAAMiB,EAAMjB,EAAK,MAAM,EAAG,EAAE,EAC5B,MAAO,IAAMiB,CACf,CAGA,GAAIa,GAAU,KAAK9B,CAAI,EAAG,CACxB,IAAMiB,EAAM,OAAOjB,CAAI,EACvB,MAAO,IAAMiB,CACf,CAGA,GAAIjB,IAAS,OAAQ,MAAO,IAAM,GAClC,GAAIA,IAAS,QAAS,MAAO,IAAM,GACnC,GAAIA,IAAS,OAAQ,MAAO,IAAM,KAClC,GAAIA,IAAS,YAAa,MAAO,IAAG,GAGpC,GAAI0B,GAAc,KAAK1B,CAAI,EACzB,MAAO,IAAMC,EAAM,QAAQD,CAAI,IAAI,EAMrC,CACE,IAAMqC,EAActC,GAAmBC,EAAMC,CAAK,EAClD,GAAIoC,EAAa,OAAOA,CAC1B,CAGA,IAAMC,EAAmBtC,EAAK,MAAMuC,EAAoB,EACxD,GAAID,EAAkB,CACpB,IAAME,EAAUF,EAAiB,CAAC,EAAG,KAAK,EACpCG,EAAaH,EAAiB,CAAC,EAC/B3B,EAAU2B,EAAiB,CAAC,EAAG,KAAK,EAE1C,GAAI9B,GAAoB,IAAIiC,CAAU,EAAG,MAAO,IAAG,GAEnD,IAAMC,EAAW3B,EAAgByB,EAASvC,CAAK,EAC/C,GAAI,CAACyC,EAAU,OAAO,KAEtB,IAAM9B,EAA+B,CAAC,EACtC,QAAWC,KAAOC,GAAcH,CAAO,EAAG,CACxC,IAAMzE,EAAS6E,EAAgBF,EAAKZ,CAAK,EACzC,GAAI,CAAC/D,EAAQ,OAAO,KACpB0E,EAAO,KAAK1E,CAAM,CACpB,CAEA,MAAO,IAAM,CACX,IAAM0B,EAAO8E,EAAS,EAChBvB,EAASvD,IAAO6E,CAAU,EAChC,GAAI,OAAOtB,GAAW,WAAY,OAClC,IAAMC,EAAOR,EAAO,IAAIS,GAAMA,EAAG,CAAC,EAClC,OAAOF,EAAO,MAAMvD,EAAMwD,CAAI,CAChC,CACF,CAGA,GAAIpB,EAAK,WAAW,GAAG,EAAG,CACxB,IAAM2C,EAAQ5B,EAAgBf,EAAK,MAAM,CAAC,EAAE,KAAK,EAAGC,CAAK,EACzD,GAAI0C,EAAO,MAAO,IAAM,CAACA,EAAM,CACjC,CAGA,IAAMC,EAAe5C,EAAK,MAAM6C,EAAU,EAC1C,GAAID,EAAc,CAChB,IAAME,EAAU/B,EAAgB6B,EAAa,CAAC,EAAI3C,CAAK,EACnDvF,EACEqI,EAASH,EAAa,CAAC,EAM7B,GALII,GAAc,KAAKD,CAAM,EAC3BrI,EAAM,OAAOqI,CAAM,EAEnBrI,EAAMqI,EAAO,MAAM,EAAG,EAAE,EAEtBD,EACF,MAAO,IAAOA,EAAQ,IAAYpI,CAAG,CAEzC,CAGA,GAAIsF,EAAK,WAAW,GAAG,EAAG,CACxB,IAAMS,EAAWC,GAAoBV,EAAM,EAAG,IAAK,GAAG,EACtD,GAAIS,GAAYA,EAAS,MAAQT,EAAK,OAAS,EAAG,CAChD,IAAM2C,EAAQlC,EAAS,MAAM,KAAK,EAClC,GAAIkC,IAAU,GAEZ,MAAO,IAAM,CAAC,EAEhB,IAAMM,EAAWnC,GAAc6B,CAAK,EAC9BO,EAAmC,CAAC,EACtCC,EAAY,GAChB,QAAW9H,KAAM4H,EAAU,CACzB,IAAM/G,EAAS6E,EAAgB1F,EAAG,KAAK,EAAG4E,CAAK,EAC/C,GAAI,CAAC/D,EAAQ,CAAEiH,EAAY,GAAO,KAAO,CACzCD,EAAW,KAAKhH,CAAM,CACxB,CACA,GAAIiH,EACF,MAAO,IAAMD,EAAW,IAAI7B,GAAMA,EAAG,CAAC,CAE1C,CACF,CAGA,IAAM+B,EAAepD,EAAK,MAAMqD,EAAU,EAC1C,GAAID,EAAc,CAChB,IAAME,EAAOvC,EAAgBqC,EAAa,CAAC,EAAG,KAAK,EAAGnD,CAAK,EACrDsD,EAAOxC,EAAgBqC,EAAa,CAAC,EAAG,KAAK,EAAGnD,CAAK,EACrDuD,EAAMzC,EAAgBqC,EAAa,CAAC,EAAG,KAAK,EAAGnD,CAAK,EAC1D,GAAIqD,GAAQC,GAAQC,EAClB,MAAO,IAAMF,EAAK,EAAIC,EAAK,EAAIC,EAAI,CAEvC,CAGA,IAAMC,EAAezD,EAAK,MAAM0D,EAAU,EAC1C,GAAID,EAAc,CAChB,IAAME,EAAO5C,EAAgB0C,EAAa,CAAC,EAAG,KAAK,EAAGxD,CAAK,EACrD2D,EAAQ7C,EAAgB0C,EAAa,CAAC,EAAG,KAAK,EAAGxD,CAAK,EAC5D,GAAI0D,GAAQC,EACV,MAAO,IAAMD,EAAK,GAAKC,EAAM,CAEjC,CAGA,IAAMC,EAAU7D,EAAK,MAAM8D,EAAK,EAChC,GAAID,EAAS,CACX,IAAMF,EAAO5C,EAAgB8C,EAAQ,CAAC,EAAG,KAAK,EAAG5D,CAAK,EAChD2D,EAAQ7C,EAAgB8C,EAAQ,CAAC,EAAG,KAAK,EAAG5D,CAAK,EACvD,GAAI0D,GAAQC,EACV,MAAO,IAAMD,EAAK,GAAKC,EAAM,CAEjC,CAGA,IAAMG,EAAW/D,EAAK,MAAMgE,EAAM,EAClC,GAAID,EAAU,CACZ,IAAMJ,EAAO5C,EAAgBgD,EAAS,CAAC,EAAG,KAAK,EAAG9D,CAAK,EACjD2D,EAAQ7C,EAAgBgD,EAAS,CAAC,EAAG,KAAK,EAAG9D,CAAK,EACxD,GAAI0D,GAAQC,EACV,MAAO,IAAMD,EAAK,GAAKC,EAAM,CAEjC,CAGA,IAAMK,EAAYjE,EAAK,MAAMkE,EAAa,EAC1C,GAAID,EAAW,CACb,IAAMN,EAAO5C,EAAgBkD,EAAU,CAAC,EAAG,KAAK,EAAGhE,CAAK,EAClD2D,EAAQ7C,EAAgBkD,EAAU,CAAC,EAAG,KAAK,EAAGhE,CAAK,EACzD,GAAI0D,GAAQC,EAAO,CACjB,IAAMO,EAAKF,EAAU,CAAC,EACtB,MAAO,IAAM,CACX,IAAMG,EAAIT,EAAK,EAAGU,EAAIT,EAAM,EAC5B,OAAQO,EAAI,CACV,IAAK,MAAO,OAAOC,IAAMC,EACzB,IAAK,MAAO,OAAOD,IAAMC,EACzB,IAAK,KAAM,OAAOD,GAAKC,EACvB,IAAK,KAAM,OAAOD,GAAKC,EACvB,IAAK,IAAK,OAAQD,EAAgBC,EAClC,IAAK,IAAK,OAAQD,EAAgBC,EAClC,IAAK,KAAM,OAAQD,GAAiBC,EACpC,IAAK,KAAM,OAAQD,GAAiBC,CACtC,CACF,CACF,CACF,CAIA,IAAMC,EAAWtE,EAAK,MAAMuE,EAAM,EAClC,GAAID,EAAU,CACZ,IAAMX,EAAO5C,EAAgBuD,EAAS,CAAC,EAAG,KAAK,EAAGrE,CAAK,EACjD2D,EAAQ7C,EAAgBuD,EAAS,CAAC,EAAG,KAAK,EAAGrE,CAAK,EACxD,GAAI0D,GAAQC,EAAO,CACjB,IAAMO,EAAKG,EAAS,CAAC,EACrB,MAAO,IAAM,CACX,IAAMF,EAAIT,EAAK,EAAGU,EAAIT,EAAM,EAC5B,OAAIO,IAAO,IAAaC,EAAaC,EAC7BD,EAAgBC,CAC1B,CACF,CACF,CAGA,IAAMG,EAAWxE,EAAK,MAAMyE,EAAM,EAClC,GAAID,EAAU,CACZ,IAAMb,EAAO5C,EAAgByD,EAAS,CAAC,EAAG,KAAK,EAAGvE,CAAK,EACjD2D,EAAQ7C,EAAgByD,EAAS,CAAC,EAAG,KAAK,EAAGvE,CAAK,EACxD,GAAI0D,GAAQC,EAAO,CACjB,IAAMO,EAAKK,EAAS,CAAC,EACrB,MAAO,IAAM,CACX,IAAMJ,EAAIT,EAAK,EAAaU,EAAIT,EAAM,EACtC,OAAQO,EAAI,CACV,IAAK,IAAK,OAAOC,EAAIC,EACrB,IAAK,IAAK,OAAOD,EAAIC,EACrB,IAAK,IAAK,OAAOD,EAAIC,CACvB,CACF,CACF,CACF,CAGA,IAAMK,EAAY1E,EAAK,MAAM2E,EAAe,EAC5C,GAAID,EAAW,CACb,IAAM9I,EAAM8I,EAAU,CAAC,EAEjBE,EAAwB,CAAC,EACzBC,EAAgC,CAAC,EACnCC,EAAY,EAEVC,EAAK,IAAI,OAAOC,GAAmB,OAAQ,GAAG,EAChDC,EACJ,MAAQA,EAAIF,EAAG,KAAKnJ,CAAG,KAAO,MAAM,CAClCgJ,EAAY,KAAKhJ,EAAI,MAAMkJ,EAAWG,EAAE,KAAK,CAAC,EAC9C,IAAMtC,EAAQ5B,EAAgBkE,EAAE,CAAC,EAAG,KAAK,EAAGhF,CAAK,EACjD,GAAI,CAAC0C,EAAO,OAAO,KACnBkC,EAAW,KAAKlC,CAAK,EACrBmC,EAAYC,EAAG,SACjB,CACA,OAAAH,EAAY,KAAKhJ,EAAI,MAAMkJ,CAAS,CAAC,EAG9B,IAAM,CACX,IAAItK,EAASoK,EAAY,CAAC,EAC1B,QAASnK,EAAI,EAAGA,EAAIoK,EAAW,OAAQpK,IACrCD,GAAU,OAAOqK,EAAWpK,CAAC,EAAG,GAAK,EAAE,EACvCD,GAAUoK,EAAYnK,EAAI,CAAC,GAAK,GAElC,OAAOD,CACT,CACF,CAGA,OAAO,IACT,CAIA,SAAS0K,GAAiBC,EAAuClF,EAA8B,CAC7F,IAAImF,EAASD,EAAM,IAAIlF,CAAK,EAC5B,OAAKmF,IACHA,EAAS,IAAI,IACbD,EAAM,IAAIlF,EAAOmF,CAAM,GAElBA,CACT,CAGA,SAASC,GAAkBrF,EAAsB,CAC/C,OAAIA,EAAK,SAAS,KAAK,EACd,yIAGLA,EAAK,SAAS,IAAI,EACb,+JAEF,iHACT,CAEA,SAASsF,EAAetF,EAAcC,EAA6B,CACjE,IAAMsF,EAAUvF,EAAK,QAAQwF,GAAiB,EAAE,EAAE,KAAK,EACjDL,EAAQD,GAAcO,GAAsBxF,CAAK,EACjDyF,EAASP,EAAM,IAAII,CAAO,EAChC,GAAIG,EAAQ,OAAOA,EAGnB,IAAMC,EAAQ5E,EAAgBwE,EAAStF,CAAK,EAC5C,GAAI0F,EACF,OAAAR,EAAM,IAAII,EAASI,CAAK,EACjBA,EAIT,GAAI,CAACC,EAAkB,CACrBC,EAAI,+DAAgEN,CAAO,EAC3EO,GAAiB,yBAA0BP,EAASF,GAAkBE,CAAO,CAAC,EAC9E,IAAMQ,EAAU,IAAG,GACnB,OAAAZ,EAAM,IAAII,EAASQ,CAAO,EACnBA,CACT,CAIA,IAAMC,EAAgBC,GAAkBV,CAAO,EAC/C,GAAIS,EAAe,CACjB,IAAME,EAAM,0BAA0BF,CAAa,kBACnD,MAAAF,GAAiB,yBAA0BP,EAASW,CAAG,EACjD,IAAI,MAAM,aAAaA,CAAG,KAAKX,CAAO,EAAE,CAChD,CAEA,GAAI,CACF,IAAMlE,EAAK,IAAI,SAAS,UAAW,2BAA2BkE,CAAO,MAAM,EAGrEY,EAAQ,IAAI,MAAM,OAAO,OAAO,IAAI,EAA8B,CACtE,IAAIC,EAAG1L,EAAa,CAAE,OAAOA,KAAOuF,EAAM,OAAS,EACnD,IAAImG,EAAG1L,EAAa,CAGlB,GAAI8F,GAAoB,IAAI9F,CAAG,EAAG,OAClC,IAAM2L,EAAIpG,EAAM,QAAQvF,CAAG,EAC3B,OAAO2L,EAAIA,EAAE,EAAI,MACnB,CACF,CAAC,EACKC,EAAS,IAAMjF,EAAG8E,CAAK,EAC7B,OAAAhB,EAAM,IAAII,EAASe,CAAM,EAClBA,CACT,MAAQ,CACNR,GAAiB,yBAA0BP,EAAS,4IAA4I,EAChM,IAAMgB,EAAS,IAAG,GAClB,OAAApB,EAAM,IAAII,EAASgB,CAAM,EAClBA,CACT,CACF,CAQA,SAASC,GAAaxG,EAAcC,EAA2C,CAC7E,IAAMwG,EAAazG,EAAK,KAAK,EAAE,QAAQ,OAAQ,EAAE,EAAE,KAAK,EACxD,GAAI,CAACyG,EAAY,OAAO,KAExB,IAAMC,EAAYC,GAAeF,EAAYxG,CAAK,EAClD,GAAIyG,EAAW,OAAOA,EAEtB,IAAME,EAAQC,GAAwBJ,CAAU,EAChD,GAAIG,EAAM,OAAS,EAAG,CACpB,IAAME,EAAWF,EAAM,IAAIjF,GAAK6E,GAAa7E,EAAG1B,CAAK,CAAC,EACtD,OAAI6G,EAAS,MAAMC,GAAKA,IAAM,IAAI,EACxBC,GAAa,CACnBC,EAAM,IAAM,CACV,QAAW,KAAKH,EAAU,EAAGE,CAAC,CAChC,CAAC,CACH,EAEK,IACT,CAEA,IAAME,EAASN,EAAM,CAAC,GAAKH,EAGrBU,EAAYD,EAAO,MAAME,EAAY,EAC3C,GAAID,EAAW,CACb,IAAM1L,EAAO0L,EAAU,CAAC,EAClBhD,EAAKgD,EAAU,CAAC,EACtB,MAAO,IAAM,CACXF,EAAM,IAAM,CACV,IAAMhG,EAAMhB,EAAM,QAAQxE,CAAI,IAAI,GAAe,EACjDwE,EAAM,QAAQxE,CAAI,IAAI0I,IAAO,KAAOlD,EAAM,EAAIA,EAAM,CAAC,CACvD,CAAC,CACH,CACF,CAGA,IAAMoG,EAAeH,EAAO,MAAMI,EAAW,EAC7C,GAAID,EAAc,CAChB,IAAMlD,EAAKkD,EAAa,CAAC,EACnB5L,EAAO4L,EAAa,CAAC,EAC3B,MAAO,IAAM,CACXJ,EAAM,IAAM,CACV,IAAMhG,EAAMhB,EAAM,QAAQxE,CAAI,IAAI,GAAe,EACjDwE,EAAM,QAAQxE,CAAI,IAAI0I,IAAO,KAAOlD,EAAM,EAAIA,EAAM,CAAC,CACvD,CAAC,CACH,CACF,CAGA,IAAMsG,EAAcL,EAAO,MAAMM,EAAS,EAC1C,GAAID,GAAeA,EAAY,CAAC,IAAMA,EAAY,CAAC,EAAG,CACpD,IAAM9L,EAAO8L,EAAY,CAAC,EAC1B,MAAO,IAAM,CACXN,EAAM,IAAM,CACVhH,EAAM,QAAQxE,CAAI,IAAI,CAACwE,EAAM,QAAQxE,CAAI,IAAI,CAAC,CAChD,CAAC,CACH,CACF,CAGA,IAAMgM,EAAcP,EAAO,MAAMQ,EAAS,EAC1C,GAAID,EAAa,CACf,IAAMhM,EAAOgM,EAAY,CAAC,EACpBE,EAAU5G,EAAgB0G,EAAY,CAAC,EAAG,KAAK,EAAGxH,CAAK,EAC7D,GAAI0H,EACF,OAAIC,GAAQ/B,EAAI,6BAA6BpK,CAAI,gCAA4B,CAAC,CAACwE,EAAM,QAAQxE,CAAI,EAAG,mBAAoB,CAAC,CAACwE,EAAM,QAAQxE,CAAI,CAAC,EACtI,IAAM,CACXwL,EAAM,IAAM,CACV,IAAMhG,EAAM0G,EAAQ,EAChBC,GAAQ/B,EAAI,WAAWpK,CAAI,MAAMwF,CAAG,UAAUhB,EAAM,QAAQxE,CAAI,IAAI,CAAC,GAAG,EAC5EwE,EAAM,QAAQxE,CAAI,IAAIwF,CAAG,CAC3B,CAAC,CACH,CAEJ,CAGA,IAAM4G,EAAgBX,EAAO,MAAMY,EAAW,EAC9C,GAAID,EAAe,CACjB,IAAMpM,EAAOoM,EAAc,CAAC,EACtB1D,EAAK0D,EAAc,CAAC,EACpBF,EAAU5G,EAAgB8G,EAAc,CAAC,EAAG,KAAK,EAAG5H,CAAK,EAC/D,GAAI0H,EACF,MAAO,IAAM,CACXV,EAAM,IAAM,CACV,IAAM3H,EAAUW,EAAM,QAAQxE,CAAI,IAAI,GAAe,EAC/CwF,EAAM0G,EAAQ,EACpB,OAAQxD,EAAI,CACV,IAAK,KAAMlE,EAAM,QAAQxE,CAAI,IAAI6D,EAAU2B,CAAG,EAAG,MACjD,IAAK,KAAMhB,EAAM,QAAQxE,CAAI,IAAI6D,EAAU2B,CAAG,EAAG,MACjD,IAAK,KAAMhB,EAAM,QAAQxE,CAAI,IAAI6D,EAAU2B,CAAG,EAAG,MACjD,IAAK,KAAMhB,EAAM,QAAQxE,CAAI,IAAI6D,EAAU2B,CAAG,EAAG,KACnD,CACF,CAAC,CACH,CAEJ,CAGA,IAAM8G,EAAeb,EAAO,MAAMc,EAAe,EACjD,GAAID,EAAc,CAChB,IAAME,EAAUF,EAAa,CAAC,EAC9B,MAAO,IAAMG,GAASD,CAAO,CAC/B,CAEA,OAAO,IACT,CAEA,SAASE,GAAanI,EAAcC,EAAkC,CAGpE,IAAIsF,EAAUvF,EAAK,KAAK,EACxB,GAAIuF,EAAQ,WAAW,GAAG,EAAG,CAC3B,IAAM6C,EAAM1H,GAAoB6E,EAAS,EAAG,IAAK,GAAG,EAChD6C,GAAOA,EAAI,MAAQ7C,EAAQ,OAAS,IACtCA,EAAU6C,EAAI,MAAM,KAAK,EAE7B,CACA,IAAMjD,EAAQD,GAAcmD,GAAmBpI,CAAK,EAC9CyF,EAASP,EAAM,IAAII,CAAO,EAChC,GAAIG,EAAQ,OAAOA,EAGnB,IAAMC,EAAQa,GAAajB,EAAStF,CAAK,EACzC,GAAI0F,EAAO,CACT,IAAMnL,EAA6B,CAAE,QAASmL,EAAO,UAAW,EAAK,EACrE,OAAAR,EAAM,IAAII,EAAS/K,CAAM,EAClBA,CACT,CAKA,GAAI,CAACoL,EAAkB,CACrBC,EAAI,6DAA8DN,CAAO,EACzEO,GAAiB,sBAAuBP,EAASF,GAAkBE,CAAO,CAAC,EAC3E,IAAM/K,EAA6B,CACjC,QAAS,IAAM,CAAC,EAChB,UAAW,EACb,EACA,OAAA2K,EAAM,IAAII,EAAS/K,CAAM,EAClBA,CACT,CAIA,IAAMwL,EAAgBC,GAAkBV,CAAO,EAC/C,GAAIS,EAAe,CACjB,IAAME,EAAM,0BAA0BF,CAAa,eACnD,MAAAF,GAAiB,sBAAuBP,EAASW,CAAG,EAC9C,IAAI,MAAM,aAAaA,CAAG,KAAKX,CAAO,EAAE,CAChD,CAEA,GAAI,CAEF,IAAMlE,EAAK,IAAI,SAAS,UAAW,SAAU,QAAS,mBAAmBkE,CAAO,IAAI,EAG9EY,EAAQ,IAAI,MAAM,OAAO,OAAO,IAAI,EAA8B,CACtE,IAAIC,EAAG1L,EAAa,CAGlB,OAAIA,IAAQ,UAAYA,IAAQ,QAAgB,GACzCA,KAAOuF,EAAM,SAAWvF,KAAOuF,EAAM,OAC9C,EACA,IAAImG,EAAG1L,EAAa,CAElB,GAAI8F,GAAoB,IAAI9F,CAAG,EAAG,OAClC,IAAM2L,EAAIpG,EAAM,QAAQvF,CAAG,EAC3B,OAAO2L,EAAIA,EAAE,EAAI,MACnB,EACA,IAAID,EAAG1L,EAAa4N,EAAgB,CAClC,IAAM3G,EAAI1B,EAAM,QAAQvF,CAAG,EAC3B,OAAIiH,GAAGA,EAAE2G,CAAK,EACP,EACT,CACF,CAAC,EAIK9N,EAA6B,CACjC,QAJqBwM,GAAa,CAClCC,EAAM,IAAM5F,EAAG8E,EAAOa,EAAGA,CAAC,CAAC,CAC7B,EAGE,UAAW,EACb,EACA,OAAA7B,EAAM,IAAII,EAAS/K,CAAM,EAClBA,CACT,MAAQ,CACNsL,GAAiB,sBAAuBP,EAAS,4IAA4I,EAC7L,IAAM/K,EAA6B,CACjC,QAAS,IAAM,CAAC,EAChB,UAAW,EACb,EACA,OAAA2K,EAAM,IAAII,EAAS/K,CAAM,EAClBA,CACT,CACF,CAIA,IAAM+N,GAAuB,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAE9E,SAASC,GAAW5M,EAAsC,CACxD,IAAIM,EACJ,GAAI,CACFA,EAAS,KAAK,MAAMN,CAAG,CACzB,MAAQ,CACN,OAAIgM,GACF/B,EAAI,4FAAwFjK,EAAI,MAAM,EAAG,GAAG,CAAC,EAExG,CAAC,CACV,CAEA,QAAWlB,KAAO6N,GACZ7N,KAAOwB,GAAQ,OAAOA,EAAOxB,CAAG,EAEtC,OAAOwB,CACT,CAIA,SAASuM,GAAUC,EAAyB,CAC1C,IAAM9M,EAAM8M,EAAQ,aAAa,kBAAkB,GAAK,KAClDjL,EAAQ+K,GAAW5M,CAAG,EACtB+M,EAAO,OAAO,KAAKlL,CAAK,EAC1BmK,IACF/B,EAAI,oBAAqB8C,EAAK,OAAQ,QAASA,EAAK,KAAK,IAAI,CAAC,EAC1DA,EAAK,SAAW,GAClB9C,EAAI,wDAAoDjK,EAAI,MAAM,EAAG,GAAG,CAAC,GAG7E,IAAMgN,EAAkC,CAAC,EACnCC,EAAkC,CAAC,EAEzC,OAAW,CAACnO,EAAKiF,CAAO,IAAK,OAAO,QAAQlC,CAAK,EAAG,CAClD,GAAM,CAACqL,EAAKC,CAAG,EAAIC,GAAarJ,CAAO,EACvCiJ,EAAQlO,CAAG,EAAIoO,EACfD,EAAQnO,CAAG,EAAIqO,CACjB,CAGA,OAAAH,EAAQ,SAAc,IAAMV,GAErB,CAAE,QAAAU,EAAS,QAAAC,CAAQ,CAC5B,CAOA,IAAMI,GAAgB,IAAI,IAAI,CAE5B,KAAM,YAAa,UAAW,WAC9B,eAAgB,eAAgB,kBAAmB,eAAgB,kBACnE,UAAW,YAEX,cAAe,YAEf,QAAS,UAAW,WAAY,WAAY,OAAQ,OAAQ,cAC5D,WAAY,WAAY,MAAO,MAAO,OAAQ,UAE9C,wBAAyB,cAAe,eACxC,YAAa,aAAc,cAAe,eAC1C,cAAe,eAAgB,YAAa,aAE5C,QAAS,SAET,QAAS,OAAQ,QAAS,iBAAkB,WAE5C,UAAW,UAAW,gBAAiB,mBACvC,WAAY,oBAAqB,oBAAqB,mBACtD,qBAAsB,wBACxB,CAAC,EAED,SAASC,GAAkB7N,EAAsB,CAC/C,OAAO,IAAI,MAAMA,EAAI,CACnB,IAAI8N,EAAQC,EAAM,CAChB,GAAI,OAAOA,GAAS,SAAU,OAAO,QAAQ,IAAID,EAAQC,CAAI,EAC7D,GAAI,CAACH,GAAc,IAAIG,CAAI,EAAG,OAC9B,IAAMnI,EAAM,QAAQ,IAAIkI,EAAQC,CAAI,EACpC,OAAO,OAAOnI,GAAQ,WAAaA,EAAI,KAAKkI,CAAM,EAAIlI,CACxD,EACA,IAAIkI,EAAQC,EAAMd,EAAO,CAEvB,OADI,OAAOc,GAAS,UAChB,CAACH,GAAc,IAAIG,CAAI,EAAU,GAC9B,QAAQ,IAAID,EAAQC,EAAMd,CAAK,CACxC,CACF,CAAC,CACH,CAEA,SAASe,EAAYhO,EAAa4E,EAAcqJ,EAAiC,CAG/E,IAAMC,EAAoC,CACxC,IAAKL,GAAkB7N,CAAE,EACzB,UAAW,CAACI,EAAc+N,IAAqB,CAC7CnO,EAAG,cAAc,IAAI,YAAYI,EAAM,CACrC,QAAS,GACT,SAAU,GACV,OAAA+N,CACF,CAAC,CAAC,CACJ,CACF,EACAvJ,EAAQwJ,GAAiBxJ,EAAOsJ,CAAQ,EAKxC,IAAMG,EAAQC,GAActO,CAAE,EAGxBuO,EAAgB,CAACF,GAASA,EAAM,IAAI,eAAe,EAAKrO,EAAG,aAAa,eAAe,EAAI,KACjG,GAAIuO,EAAc,CAIhB,IAAMC,EAAQD,EAAa,MAAM,qBAAqB,EACtD,QAAWtN,KAAQuN,EAAO,CACxB,IAAMC,EAAUxN,EAAK,KAAK,EAC1B,GAAI,CAACwN,EAAS,SACd,IAAMC,EAAQD,EAAQ,MAAME,EAAW,EACvC,GAAID,EAAO,CACT,IAAMtO,EAAOsO,EAAM,CAAC,EACd/J,EAAO+J,EAAM,CAAC,EAGdE,EAAahK,EAAM,QAAQxE,CAAI,EACrC,OAAOwE,EAAM,QAAQxE,CAAI,EACzB,IAAMyO,EAAW5E,EAAe,IAAItF,CAAI,IAAKC,CAAK,EAC5CkK,EAASC,GAAeF,CAAQ,EACtCjK,EAAM,QAAQxE,CAAI,EAAI0O,EAEjBF,GAEH,OAAOhK,EAAM,QAAQxE,CAAI,CAE7B,CACF,CACF,CAGA,IAAM4O,EAAY,CAACX,GAASA,EAAM,IAAI,WAAW,EAAKrO,EAAG,aAAa,WAAW,EAAI,KACrF,GAAIgP,EAAU,CACZ,IAAMH,EAAW5E,EAAe+E,EAAUpK,CAAK,EACzCqK,EAAUC,EAAe,IAAM,CACnCC,GAAmBnP,EAAIoP,GAAYP,EAAS,CAAC,CAAC,CAChD,CAAC,EACDZ,EAAU,KAAKgB,CAAO,CACxB,CAGA,IAAMI,EAAY,CAAChB,GAASA,EAAM,IAAI,WAAW,EAAKrO,EAAG,aAAa,WAAW,EAAI,KACrF,GAAIqP,EAAU,CACZ,IAAMR,EAAW5E,EAAeoF,EAAUzK,CAAK,EACzCP,EAAahC,GAAoBrC,CAAE,EACzC,GAAIuM,EAAQ,CACV,IAAM+C,EAAMtP,EAAG,QAAQ,YAAY,EAC7BkD,EAAMlD,EAAG,UAAY,IAAI,OAAOA,EAAG,SAAS,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,GAAK,GACtEwK,EAAI,2BAA2B6E,CAAQ,SAASC,CAAG,GAAGpM,CAAG,GAAG,CAC9D,CACA,IAAIqM,EAAc,GACZN,EAAUC,EAAe,IAAM,CACnC,IAAM9K,EAAU,CAAC,CAACyK,EAAS,EACvBtC,GAAQ/B,EAAI,sBAAsB6E,CAAQ,YAAOjL,CAAO,EAAE,EAC9DD,GAAoBnE,EAAmBoE,EAASC,EAAY,CAACkL,CAAW,EACxEA,EAAc,EAChB,CAAC,EACDtB,EAAU,KAAKgB,CAAO,EAClB5K,GACF4J,EAAU,KAAK,IAAM9L,GAAqBnC,CAAiB,CAAC,CAEhE,CAGA,IAAMwP,EAAU,CAACnB,GAASA,EAAM,IAAI,SAAS,EAAKrO,EAAG,aAAa,SAAS,EAAI,KAC/E,GAAIwP,EAAQ,CACV,IAAMX,EAAW5E,EAAeuF,EAAQ5K,CAAK,EACvCP,EAAahC,GAAoBrC,CAAE,EACnCyP,EAAc,SAAS,cAAc,UAAU,EAC/C3L,EAAS9D,EAAG,WACd0P,EAAW,GACXH,EAAc,GAEZN,EAAUC,EAAe,IAAM,CACnC,IAAMS,EAAO,CAAC,CAACd,EAAS,EAEpBc,GAAQ,CAACD,GAEXvN,GAAqBnC,CAAiB,EACtCA,EAAG,gBAAgB,oBAAoB,EACnCuP,GAAelL,EACjBR,GAAiB7D,EAAmB8D,EAAS2L,EAAapL,CAAU,EAEpEP,GAAQ,aAAa9D,EAAIyP,CAAW,EAEtCC,EAAW,IACF,CAACC,GAAQD,IACdH,GAAelL,EACjBH,GAAiBlE,EAAmBqE,EAAY,IAAM,CAChDrE,EAAG,aACL8D,GAAQ,aAAa2L,EAAazP,CAAE,EACpCA,EAAG,OAAO,EAEd,CAAC,GAED8D,GAAQ,aAAa2L,EAAazP,CAAE,EACpCA,EAAG,OAAO,GAEZ0P,EAAW,IAEbH,EAAc,EAChB,CAAC,EAEDtB,EAAU,KAAKgB,CAAO,EAClB5K,GACF4J,EAAU,KAAK,IAAM9L,GAAqBnC,CAAiB,CAAC,CAEhE,CAGA,IAAM4P,EAAa,CAACvB,GAASA,EAAM,IAAI,YAAY,EAAKrO,EAAG,aAAa,YAAY,EAAI,KACxF,GAAI4P,EAAW,CACb,IAAM7B,EAAO6B,EAAU,QAAQzF,GAAiB,EAAE,EAAE,KAAK,EACnD2E,EAASlK,EAAM,QAAQmJ,CAAI,EAC3B8B,EAASjL,EAAM,QAAQmJ,CAAI,EACjC,GAAIe,GAAUe,EAAQ,CACpB,IAAMC,EAAQ9P,EACRiP,EAAUC,EAAe,IAAM,CACnC,IAAMtJ,EAAMkJ,EAAO,EACfgB,EAAM,OAAS,WACjBA,EAAM,QAAU,CAAC,CAAClK,EAElBkK,EAAM,MAAQ,OAAOlK,GAAO,EAAE,CAElC,CAAC,EACDqI,EAAU,KAAKgB,CAAO,EACtB,IAAMc,EAAQD,EAAM,OAAS,WAAa,SAAW,QAC/CE,EAAe,IAAM,CACrBF,EAAM,OAAS,WACjBD,EAAOC,EAAM,OAAO,EACXA,EAAM,OAAS,UAAYA,EAAM,OAAS,QACnDD,EAAO,OAAOC,EAAM,KAAK,CAAC,EAE1BD,EAAOC,EAAM,KAAK,CAEtB,EACAA,EAAM,iBAAiBC,EAAOC,CAAY,EAC1C/B,EAAU,KAAK,IAAM,CACnB6B,EAAM,oBAAoBC,EAAOC,CAAY,CAC/C,CAAC,CACH,CACF,CAIA,IAAMC,EAAqB,CAAC5B,GAAS6B,GAAa7B,EAAO,WAAY,cAAe,YAAY,EAC1F8B,EAAQnQ,EAAG,WACjB,GAAIiQ,EAAoB,QAAS7Q,EAAI,EAAGA,EAAI+Q,EAAM,OAAQ/Q,IAAK,CAC7D,IAAMqF,EAAO0L,EAAM/Q,CAAC,EACdgB,EAAOqE,EAAK,KAElB,GAAIrE,EAAK,WAAW,UAAU,EAAG,CAC/B,IAAM2P,EAAQ3P,EAAK,MAAM,CAAC,EACpBgQ,EAAQtD,GAAarI,EAAK,MAAOG,CAAK,EACtCyL,EAAUD,EAAM,QACtB,GAAI7D,EAAQ,CACV,IAAM+C,EAAMtP,EAAG,QAAQ,YAAY,EAC7BsQ,EAAKtQ,EAAG,GAAK,IAAIA,EAAG,EAAE,GAAK,GAC3BkD,EAAMlD,EAAG,UAAY,IAAI,OAAOA,EAAG,SAAS,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,GAAK,GACtEwK,EAAI,wBAAwBuF,CAAK,KAAKtL,EAAK,KAAK,SAAS6K,CAAG,GAAGgB,CAAE,GAAGpN,CAAG,GAAG,CAC5E,CAMA,GALKkN,EAAM,UAEApQ,EAAG,aAAa,0BAA0B,GACnDA,EAAG,gBAAgB,0BAA0B,EAF7CA,EAAG,aAAa,2BAA4B,aAAa,EAIvDuM,EAAQ,CACV,IAAMgE,EAAU9L,EAAK,MACf+L,EAAiB7E,GAAa,CAClCnB,EAAI,0BAA0BuF,CAAK,KAAKQ,CAAO,IAAK,aAAc5E,EAAE,SAAS,EAC7E0E,EAAQ1E,CAAC,CACX,EACA3L,EAAG,iBAAiB+P,EAAOS,CAAa,EACxCvC,EAAU,KAAK,IAAM,CAAEjO,EAAG,oBAAoB+P,EAAOS,CAAa,CAAG,CAAC,CACxE,MACExQ,EAAG,iBAAiB+P,EAAOM,CAAO,EAClCpC,EAAU,KAAK,IAAM,CAAEjO,EAAG,oBAAoB+P,EAAOM,CAAO,CAAG,CAAC,CAEpE,SAAWjQ,EAAK,WAAW,aAAa,EAAG,CACzC,IAAM8C,EAAM9C,EAAK,MAAM,EAAE,EACnByO,EAAW5E,EAAexF,EAAK,MAAOG,CAAK,EAC3CqK,EAAUC,EAAe,IAAM,CACnClP,EAAG,UAAU,OAAOkD,EAAK,CAAC,CAAC2L,EAAS,CAAC,CACvC,CAAC,EACDZ,EAAU,KAAKgB,CAAO,CACxB,SAAW7O,EAAK,WAAW,YAAY,EAAG,CACxC,IAAMqQ,EAAWrQ,EAAK,MAAM,EAAE,EACxByO,EAAW5E,EAAexF,EAAK,MAAOG,CAAK,EAC3CqK,EAAUC,EAAe,IAAM,CACnC,IAAMtJ,EAAMiJ,EAAS,EACjBjJ,GAAO,MAAQA,IAAQ,GACzB5F,EAAG,gBAAgByQ,CAAQ,EAE3BzQ,EAAG,aAAayQ,EAAU,OAAO7K,CAAG,CAAC,CAEzC,CAAC,EACDqI,EAAU,KAAKgB,CAAO,CACxB,CACF,CAGA,IAAMyB,EAAe,CAACrC,GAASA,EAAM,IAAI,cAAc,EAAKrO,EAAG,aAAa,cAAc,EAAI,KAC9F,GAAI0Q,EAAa,CACf,IAAM3C,EAAO2C,EAAY,QAAQvG,GAAiB,EAAE,EAAE,KAAK,EACrD2E,EAASlK,EAAM,QAAQmJ,CAAI,EAC3B8B,EAASjL,EAAM,QAAQmJ,CAAI,EACjC,GAAIe,GAAUe,EAAQ,CACpB,IAAMxQ,EAAM,SAAW0O,EACvB,GAAI,CACF,IAAM4C,EAAQ,aAAa,QAAQtR,CAAG,EAClCsR,IAAU,MAAMd,EAAO,KAAK,MAAMc,CAAK,CAAC,CAC9C,MAAQ,CAA4B,CACpC,IAAM1B,EAAUC,EAAe,IAAM,CACnC,GAAI,CAAE,aAAa,QAAQ7P,EAAK,KAAK,UAAUyP,EAAO,CAAC,CAAC,CAAG,MAAQ,CAAc,CACnF,CAAC,EACDb,EAAU,KAAKgB,CAAO,CACxB,CACF,CAGA,IAAM2B,EAAY,CAACvC,GAASA,EAAM,IAAI,WAAW,EAAKrO,EAAG,aAAa,WAAW,EAAI,KACrF,GAAI4Q,EAAU,CACZ,IAAM/B,EAAW5E,EAAe2G,EAAUhM,CAAK,EACzCiM,EAAa7Q,EAAG,SAAS,CAAC,EAChC,GAAI6Q,EAAY,CAuBd,IAASC,EAAT,SAA8BpR,EAAkB,CAC9C,IAAMM,EAAKN,EACX,GAAI,MAAM,QAAQM,EAAG,gBAAgB,EAAG,CACtC,QAAWwB,KAAKxB,EAAG,iBACjB,GAAI,CAAEwB,EAAE,CAAG,MAAQ,CAAiC,CAEtD,OAAOxB,EAAG,gBACZ,CACF,EAGS+Q,EAAT,SAA0B7R,EAAe8R,EAAwB,CAC/D,IAAMxR,EAAQF,GAAsBC,EAAUL,CAAI,EAC5C+R,EAAa7C,GAAiBxJ,EAAO,CAAE,KAAA1F,EAAM,MAAA8R,CAAM,CAAC,EACpDE,EAAgC,CAAC,EACvClD,EAAYxO,EAAOyR,EAAYC,CAAa,EAC5C,QAAWC,KAAQ,MAAM,KAAK3R,EAAM,iBAAiB,GAAG,CAAC,EACvDwO,EAAYmD,EAAMF,EAAYC,CAAa,EAE7C,OAAC1R,EAAc,iBAAmB0R,EAC3B1R,CACT,EAGS4R,GAAT,SAA0B1R,EAAYR,EAAe8R,EAAqB,CACxEF,EAAqBpR,CAAI,EACzBK,GAAmBL,EAAiBR,CAAI,EACxC,IAAM+R,EAAa7C,GAAiBxJ,EAAO,CAAE,KAAA1F,EAAM,MAAA8R,CAAM,CAAC,EACpDE,EAAgC,CAAC,EACvClD,EAAYtO,EAAiBuR,EAAYC,CAAa,EACtD,QAAWC,KAAQ,MAAM,KAAMzR,EAAiB,iBAAiB,GAAG,CAAC,EACnEsO,EAAYmD,EAAMF,EAAYC,CAAa,EAE5CxR,EAAa,iBAAmBwR,CACnC,EAlCS,IAAAJ,IAWAC,IAaAK,KA9CT,IAAM7R,EAAWsR,EAAW,UAAU,EAAI,EAE1C7Q,EAAG,YAAY6Q,CAAU,EAGzB,IAAMQ,EAAU9R,EAAS,aAAa,UAAU,EAC1C+R,EAAUD,EACZA,EAAQ,QAAQE,GAAsB,EAAE,EAAE,KAAK,EAC/C,KAGEC,EAAiBnP,GAAoBrC,CAAE,EAEzCyR,EAAsB,CAAC,EACvBC,EAAmB,CAAC,EA6ClBC,GAA6CH,EAAiB,CAClE,SAAW9R,GAAe,CACxB,IAAMkS,EAASlS,EACf,GAAI,CAACkS,EAAO,aAAc,OAC1B,IAAMxP,EAAQL,EAAmB6P,CAAM,EACvCxP,EAAM,OAAS,EACf,IAAM3B,EAAQ2B,EAAM,MAChBA,EAAM,QAAQA,EAAM,OAAO,EAC/BA,EAAM,OAASgB,GACbwO,EACA,CACE,KAAMJ,EAAe,MACrB,KAAMA,EAAe,UACrB,GAAIA,EAAe,QACnB,WAAYA,EAAe,eAC7B,EACA,IAAM,CACJ,IAAMvN,EAAUlC,EAAmB6P,CAAM,EACrC3N,EAAQ,QAAUxD,IAAOwD,EAAQ,OAAS,KAChD,CACF,CACF,EACA,eAAgB,CAACvE,EAAY8D,IAAqB,CAChD,IAAMoO,EAASlS,EACf,GAAI,CAACkS,EAAO,aAAc,CAAEpO,EAAK,EAAG,MAAQ,CAC5CsN,EAAqBpR,CAAI,EACzBwE,GAAiB0N,EAAQJ,EAAgB,IAAM,CAC7ChO,EAAK,CACP,CAAC,CACH,CACF,EAAI,OAEEyL,GAAUC,EAAe,IAAM,CACnC,IAAM2C,EAAWhD,EAAS,EAC1B,GAAI,CAAC,MAAM,QAAQgD,CAAQ,EAAG,CAE5B,QAAWC,KAAKJ,EACdZ,EAAqBgB,CAAC,EACtB9R,EAAG,YAAY8R,CAAC,EAElBL,EAAW,CAAC,EACZC,EAAW,CAAC,EACZ,MACF,CAGA,GAAIF,EAAgB,CAClB,IAAMO,EAAe/R,EAAG,iBAAiB,sBAAsB,EAC/D,QAAWgS,KAAM,MAAM,KAAKD,CAAY,EACtC5P,GAAqB6P,CAAiB,EACtCA,EAAG,gBAAgB,oBAAoB,EACnCA,EAAG,YAAYA,EAAG,WAAW,YAAYA,CAAE,CAEnD,CAGA,IAAMC,EAAY,IAAI,IAAIP,CAAQ,EAElC,GAAIJ,EAAS,CAEX,IAAMnS,EAAS+S,GACblS,EACAyR,EACAI,EACAH,EACCxS,GAAkB,OAAQA,IAAmCoS,CAAO,GAAK,EAAE,EAC3EpS,GAAkB,CACjB,IAAMiT,EAAMN,EAAS,QAAQ3S,CAAI,EACjC,OAAO6R,EAAiB7R,EAAMiT,CAAG,CACnC,EACA,CAACzS,EAAYR,IAAkB,CAC7B,IAAMiT,EAAMN,EAAS,QAAQ3S,CAAI,EACjCkS,GAAiB1R,EAAMR,EAAMiT,CAAG,CAClC,EACA,OACAR,EACF,EAEMS,EAAY,IAAI,IAAIjT,EAAO,KAAK,EACtC,QAAW2S,KAAKG,EACd,GAAI,CAACG,EAAU,IAAIN,CAAC,EAAG,CAErB,GAAKA,EAAc,eAAe,oBAAoB,EAAG,SACzDhB,EAAqBgB,CAAC,CACxB,CAEFL,EAAWtS,EAAO,MAClBuS,EAAWvS,EAAO,KACpB,KAAO,CAGL,IAAMkT,EAA0BR,EAAS,IAAI,CAAC3S,EAAME,MAAO,CAAE,MAAOA,GAAG,OAAQF,CAAK,EAAE,EAGhFC,EAAS+S,GACblS,EAHiByR,EAKjBY,EACAX,EACCY,GAAoBA,EAAE,MACtBA,GAAoBvB,EAAiBuB,EAAE,OAAQA,EAAE,KAAK,EACvD,CAAC5S,EAAY4S,KAAoBlB,GAAiB1R,EAAM4S,GAAE,OAAQA,GAAE,KAAK,EACzE,OACAX,EACF,EAEMS,EAAY,IAAI,IAAIjT,EAAO,KAAK,EACtC,QAAW2S,KAAKG,EACd,GAAI,CAACG,EAAU,IAAIN,CAAC,EAAG,CAErB,GAAKA,EAAc,eAAe,oBAAoB,EAAG,SACzDhB,EAAqBgB,CAAC,CACxB,CAEFL,EAAWtS,EAAO,MAClBuS,EAAWvS,EAAO,KACpB,CACF,CAAC,EACD8O,EAAU,KAAKgB,EAAO,CACxB,CACF,CAGA,IAAMsD,EAAa,CAAClE,GAASA,EAAM,IAAI,YAAY,EAAKrO,EAAG,aAAa,YAAY,EAAI,KACxF,GAAIuS,EAAW,CACb,IAAMC,EAAaD,EAAU,MAAME,EAAQ,EAC3C,GAAID,EAAY,CACd,IAAME,EAAUF,EAAW,CAAC,EAAG,KAAK,EAC9B1E,EAAS0E,EAAW,CAAC,EAAG,KAAK,EAC7BG,EAAYH,EAAW,CAAC,GAAG,KAAK,GAAK,GAEvC1M,EAAS,MACT8M,EAAMF,EACJG,EAAcH,EAAQ,MAAMI,EAAe,EAC7CD,IACF/M,EAAS+M,EAAY,CAAC,EAAG,YAAY,EACrCD,EAAMC,EAAY,CAAC,EAAG,KAAK,GAG7B,IAAIE,EACAC,EACAC,EACJ,QAAWC,KAAOP,EAAU,MAAM,GAAG,EAAE,OAAO,OAAO,EAAG,CACtD,GAAM,CAACQ,EAAGC,CAAC,EAAIF,EAAI,MAAM,GAAG,EAAE,IAAI5M,GAAKA,EAAE,KAAK,CAAC,EAC3C6M,IAAM,UAAWJ,EAAgBK,EAC5BD,IAAM,QAASH,EAAcI,EAC7BD,IAAM,SAAQF,EAAW,SAASG,GAAK,IAAK,EAAE,EACzD,CAGA,GAAM,CAACC,GAAWC,EAAS,EAAI3F,GAAsB,IAAI,EAGzD,GAFA/I,EAAM,QAAQkJ,CAAM,EAAIuF,GACxBzO,EAAM,QAAQkJ,CAAM,EAAIwF,GACpBP,EAAe,CACjB,GAAM,CAACQ,EAAIC,CAAE,EAAI7F,GAAa,EAAK,EACnC/I,EAAM,QAAQmO,CAAa,EAAIQ,EAC/B3O,EAAM,QAAQmO,CAAa,EAAIS,CACjC,CACA,GAAIR,EAAa,CACf,GAAM,CAACS,EAAIC,CAAE,EAAI/F,GAAsB,IAAI,EAC3C/I,EAAM,QAAQoO,CAAW,EAAIS,EAC7B7O,EAAM,QAAQoO,CAAW,EAAIU,CAC/B,CAEA,IAAMC,GAAU,IAAM,CAChBZ,GAAenO,EAAM,QAAQmO,CAAa,EAAG,EAAI,EACrD,MAAMH,EAAK,CAAE,OAAA9M,CAAO,CAAC,EAClB,KAAKkD,GAAKA,EAAE,KAAK,CAAC,EAClB,KAAK4K,GAAQ,CACZN,GAAUM,CAAI,EACVb,GAAenO,EAAM,QAAQmO,CAAa,EAAG,EAAK,CACxD,CAAC,EACA,MAAMc,GAAO,CACRb,GAAapO,EAAM,QAAQoO,CAAW,EAAGa,EAAI,OAAO,EACpDd,GAAenO,EAAM,QAAQmO,CAAa,EAAG,EAAK,CACxD,CAAC,CACL,EAGMnG,EAAU5M,EAAG,aAAa,eAAe,EAO/C,GANI4M,IACFkH,GAAiB,IAAIlH,EAAS+G,EAAO,EACrC1F,EAAU,KAAK,IAAM6F,GAAiB,OAAOlH,CAAO,CAAC,GAGvD+G,GAAQ,EACJV,GAAYA,EAAW,EAAG,CAC5B,IAAM3C,EAAK,YAAYqD,GAASV,CAAQ,EACxChF,EAAU,KAAK,IAAM,cAAcqC,CAAE,CAAC,CACxC,CACF,CACF,CACF,CAWA,IAAMyD,GAAqB,CACzB,cAAe,cAAe,YAAa,eAC3C,kBAAmB,iBAAkB,cAAe,eACpD,kBAAmB,mBAAoB,gBAEvC,mBACF,EAAE,KAAK,GAAG,EAGV,SAASC,GAAahU,EAAsB,CAC1C,IAAMmQ,EAAQnQ,EAAG,WACjB,QAASZ,EAAI,EAAGA,EAAI+Q,EAAM,OAAQ/Q,IAAK,CACrC,IAAMgB,EAAO+P,EAAM/Q,CAAC,EAAG,KACvB,GAAIgB,EAAK,WAAW,WAAW,GAAKA,EAAK,WAAW,WAAW,GAC3DA,EAAK,WAAW,SAAS,GAAKA,EAAK,WAAW,YAAY,GAC1DA,EAAK,WAAW,eAAe,GAAKA,EAAK,WAAW,cAAc,GAClEA,EAAK,WAAW,WAAW,GAAKA,EAAK,WAAW,YAAY,GAC5DA,EAAK,WAAW,UAAU,GAAKA,EAAK,WAAW,aAAa,GAC5DA,EAAK,WAAW,YAAY,GAAKA,EAAK,WAAW,iBAAiB,EACpE,MAAO,EAEX,CACA,MAAO,EACT,CAcA,IAAI6T,EAAiD,KAMrD,SAASC,GAAgBC,EAA4C,CACnE,GAAI,CAACA,GAAO,OAAO,KAAKA,CAAG,EAAE,SAAW,EAAG,CACzCF,EAAgB,KAChB,MACF,CACAA,EAAgB,IAAI,IACpB,QAAW3D,KAAM6D,EACfF,EAAc,IAAI3D,EAAI,IAAI,IAAI6D,EAAI7D,CAAE,CAAE,CAAC,CAE3C,CAOA,SAAS8D,IAAwC,CAI/C,GAHI,CAACH,GAAiBA,EAAc,OAAS,GAGzCA,EAAc,KAAO,IAAK,OAAO,KACrC,IAAMzF,EAAkB,CAAC,EACzB,QAAW8B,KAAM2D,EAAc,KAAK,EAClCzF,EAAM,KAAK,mBAAmB8B,CAAE,IAAI,EAEtC,OAAO9B,EAAM,KAAK,GAAG,CACvB,CAGA,SAASF,GAActO,EAAiC,CACtD,GAAI,CAACiU,EAAe,OAAO,KAC3B,IAAM3D,EAAKtQ,EAAG,aAAa,eAAe,EAC1C,OAAKsQ,EACE2D,EAAc,IAAI3D,CAAE,GAAK,KADhB,IAElB,CAGA,SAASJ,GAAaxC,KAAqB2G,EAA6B,CACtE,QAAWC,KAAS5G,EAClB,QAAWrN,KAAUgU,EACnB,GAAIC,EAAM,WAAWjU,CAAM,EAAG,MAAO,GAGzC,MAAO,EACT,CAEA,SAASkU,EAAWC,EAAqB,CAEvC,GAAKA,EAAa,iBAAkB,CAC9BjI,GAAQ/B,EAAI,uCAAuC,EACvD,MACF,CAEA,IAAM5F,EAAQwI,GAAUoH,CAAI,EACtBvG,EAA4B,CAAC,EAGnCD,EAAYwG,EAAM5P,EAAOqJ,CAAS,EAKlC,IAAIwG,EAAa,EACXC,EAAWN,GAAuB,EACxC,GAAIM,EAAU,CAEZ,IAAMC,EAAUH,EAAK,iBAAiBE,CAAQ,EAC9C,QAAStV,EAAI,EAAGA,EAAIuV,EAAQ,OAAQvV,IAClC4O,EAAY2G,EAAQvV,CAAC,EAAIwF,EAAOqJ,CAAS,EACzCwG,GAEJ,KAAO,CAEL,IAAMG,EAAcJ,EAAK,iBAAiB,GAAG,EAC7C,QAASpV,EAAI,EAAGA,EAAIwV,EAAY,OAAQxV,IAAK,CAC3C,IAAMY,EAAK4U,EAAYxV,CAAC,EACpB4U,GAAahU,CAAE,IACjBgO,EAAYhO,EAAI4E,EAAOqJ,CAAS,EAChCwG,IAEJ,CACF,CAGCD,EAAa,iBAAmBvG,EAEhCuG,EAAa,aAAe5P,EAC5B4P,EAAa,oBAAsBA,EAAK,aAAa,kBAAkB,GAAK,KACzEjI,GAAQ/B,EAAI,0BAAsBiK,EAAY,kBAAmBxG,EAAU,OAAQ,YAAayG,EAAW,aAAe,aAAa,CAC7I,CAMA,SAASG,EAAaL,EAAqB,CACzC,IAAMvG,EAAauG,EAAa,iBAChC,GAAIvG,EAAW,CACb,QAAWzM,KAAKyM,EACd,GAAI,CAAEzM,EAAE,CAAG,MAAQ,CAAiC,CAEtD,OAAQgT,EAAa,iBACrB,OAAQA,EAAa,aACrB,OAAQA,EAAa,mBACvB,CACF,CAQA,IAAIM,EAAqC,KACnCC,GAAe,EACfC,GAAsB,GACxBC,GAAsC,CAAC,EACvCC,GAAqB,GAEzB,SAASC,GAAgBC,EAAgC,CAEvD,QAAShW,EAAI,EAAGA,EAAIgW,EAAS,aAAa,OAAQhW,IAAK,CACrD,IAAMM,EAAO0V,EAAS,aAAahW,CAAC,EACpC,GAAIM,EAAK,WAAaqV,GAAc,SACpC,IAAM/U,EAAKN,EACPM,EAAG,aAAa,kBAAkB,IAChCuM,GAAQ/B,EAAI,iCAAiC,EACjDqK,EAAa7U,CAAE,GAEjB,IAAMqV,EAAUrV,EAAG,iBAAiB,oBAAoB,EACxD,QAASsV,EAAI,EAAGA,EAAID,EAAQ,OAAQC,IAClCT,EAAaQ,EAAQC,CAAC,CAAE,CAE5B,CAGA,QAASlW,EAAI,EAAGA,EAAIgW,EAAS,WAAW,OAAQhW,IAAK,CACnD,IAAMM,EAAO0V,EAAS,WAAWhW,CAAC,EAClC,GAAIM,EAAK,WAAaqV,GAAc,SACpC,IAAM/U,EAAKN,EACX,GAAIM,EAAG,QAAQ,sBAAsB,EAAG,SACpCA,EAAG,aAAa,kBAAkB,IAChCuM,GAAQ/B,EAAI,4CAA4C,EAC5D+J,EAAWvU,CAAE,GAEf,IAAMuV,EAAQvV,EAAG,iBAAiB,oBAAoB,EAClDuM,GAAUgJ,EAAM,OAAS,GAC3B/K,EAAI,0BAA2B+K,EAAM,OAAQ,kCAAkC,EAEjF,QAASD,EAAI,EAAGA,EAAIC,EAAM,OAAQD,IAAK,CACrC,IAAMnE,EAAOoE,EAAMD,CAAC,EAChBnE,EAAK,QAAQ,sBAAsB,GACvCoD,EAAWpD,CAAI,CACjB,CACF,CAGA,GAAIiE,EAAS,OAAS,cAAgBA,EAAS,gBAAkB,mBAAoB,CACnF,IAAMtH,EAASsH,EAAS,OAExBP,EAAa/G,CAAM,EAEfA,EAAO,aAAa,kBAAkB,GACxCyG,EAAWzG,CAAM,CAErB,CACF,CAEA,eAAe0H,IAAoC,CACjD,GAAI,CACF,KAAOP,GAAkB,OAAS,GAAG,CACnC,IAAMrJ,EAAQqJ,GAAkB,OAAO,EAAGD,EAAmB,EAC7D,QAAS5V,EAAI,EAAGA,EAAIwM,EAAM,OAAQxM,IAChC+V,GAAgBvJ,EAAMxM,CAAC,CAAE,EAEvB6V,GAAkB,OAAS,GAC7B,MAAMQ,GAAY,CAEtB,CACF,QAAE,CACAP,GAAqB,GAEjBD,GAAkB,OAAS,GAAK,CAACC,KACnCA,GAAqB,GAChBM,GAAmB,EAE5B,CACF,CAEA,SAASE,GAAgBC,EAAmC,CACtDpJ,GAAQ/B,EAAI,2BAA4BmL,EAAU,OAAQ,aAAa,EAC3EV,GAAkB,KAAK,GAAGU,CAAS,EAC/B,CAAAT,KACJA,GAAqB,GAChBM,GAAmB,EAC1B,CAEA,SAASI,IAAsB,CAC7B,GAAId,EAAW,OACfA,EAAY,IAAI,iBAAiBY,EAAe,EAChD,IAAM5H,EAAS,SAAS,MAAQ,SAAS,gBACrCA,GACFgH,EAAU,QAAQhH,EAAQ,CACxB,UAAW,GACX,QAAS,GACT,WAAY,GACZ,gBAAiB,CAAC,kBAAkB,CACtC,CAAC,CAEL,CAEA,SAAS+H,IAAqB,CACxBf,IACFA,EAAU,WAAW,EACrBA,EAAY,KAEhB,CAIA,SAASgB,IAAoB,CACvBC,IACFC,GAAsB,SAAU,CAAE,iBAAkB,EAAK,CAAC,EAE5D,IAAMC,EAAa,SAAS,iBAAiB,oBAAoB,EAC7D1J,GAAQ/B,EAAI,qBAAsByL,EAAW,OAAQ,UAAU,EACnE,QAAWzB,KAAQ,MAAM,KAAKyB,CAAU,EACtC1B,EAAWC,CAAI,EAGjBoB,GAAc,EACVrJ,GAAQ/B,EAAI,uCAAuC,CACzD,CAGA,SAAS0L,IAAuB,CAC9BL,GAAa,EACb,IAAMI,EAAa,SAAS,iBAAiB,oBAAoB,EACjE,QAAWzB,KAAQ,MAAM,KAAKyB,CAAU,EACtCpB,EAAaL,CAAI,CAErB,CAWA,SAAS2B,GAAMnW,EAAmB,CAC5BA,EAAG,aAAa,kBAAkB,GACpCuU,EAAWvU,CAAE,EAEf,IAAM4U,EAAc5U,EAAG,iBAAiB,oBAAoB,EAC5D,QAAWmR,KAAQ,MAAM,KAAKyD,CAAW,EACvCL,EAAWpD,CAAI,CAEnB,CAQA,SAASiF,GAAQpW,EAAmB,CAC9BA,EAAG,aAAa,kBAAkB,GACpC6U,EAAa7U,CAAE,EAEjB,IAAM4U,EAAc5U,EAAG,iBAAiB,oBAAoB,EAC5D,QAAWmR,KAAQ,MAAM,KAAKyD,CAAW,EACvCC,EAAa1D,CAAI,CAErB,CAGI,OAAO,SAAa,MAClB,SAAS,aAAe,UAC1B,SAAS,iBAAiB,mBAAoB2E,EAAW,EAEzDA,GAAY,GAKhB,SAASO,GAASC,EAAmB,CAAE/J,EAAS+J,CAAI,CAEpD,SAASC,GAAkBC,EAA4B,CACjDC,IAAoBD,IACxBC,EAAkBD,EACdA,IAAS,eAAcjM,EAAmB,IAC1CiM,IAAS,cAAajM,EAAmB,IACzCiM,IAAS,YAAWjM,EAAmB,IAE3CH,GAAuB,IAAI,QAC3B4C,GAAoB,IAAI,QAC1B,CAEA,SAAS0J,GAAcJ,EAAmB,CACxC,GAAIG,IAAoB,UAAW,CACjCjM,EACE,+BAA+BiM,CAAe,8BAChD,EACA,MACF,CACIlM,IAAqB+L,IACzB/L,EAAmB+L,EAGnBlM,GAAuB,IAAI,QAC3B4C,GAAoB,IAAI,QAC1B,CAEA,SAAS2J,IAAoC,CAAE,OAAOF,CAAiB,CAEvE,SAASG,GAAeN,EAAmB,CAAEO,GAAsBP,CAAI,CAGvE,SAASQ,IAAsC,CAC7C,OAAO,MAAM,KAAKC,GAAY,OAAO,CAAC,EAAE,IAAIvV,IAAM,CAAE,GAAGA,CAAE,EAAE,CAC7D,CAGA,SAASwV,IAAyB,CAChCD,GAAY,MAAM,CACpB,CAeA,SAASE,IAA+B,CACtC,IAAMC,EAAQ,SAAS,iBAAiB,oBAAoB,EACtD/X,EAA4B,CAAC,EAEnC,QAAWqV,KAAQ,MAAM,KAAK0C,CAAK,EAAG,CACpC,GAAI1C,EAAK,QAAQ,sBAAsB,EAAG,SAC1C,IAAM5P,EAAS4P,EAAa,aACtB2C,EAAe3C,EAAa,oBAClC,GAAI,CAAC5P,EAAO,SAEZ,IAAMwS,EAA2D,CAAC,EAClE,QAAW/X,KAAO,OAAO,KAAKuF,EAAM,OAAO,EAAG,CAC5C,IAAMgB,EAAMhB,EAAM,QAAQvF,CAAG,EAAG,EAChC+X,EAAO/X,CAAG,EAAI,CAAE,MAAOuG,EAAK,KAAM,OAAOA,CAAI,CAC/C,CAEAzG,EAAO,KAAK,CACV,QAASqV,EACT,GAAIA,EAAK,aAAa,eAAe,GAAKA,EAAK,IAAMA,EAAK,QAAQ,YAAY,EAC9E,OAAA4C,EACA,YAAaD,GAAe,IAC9B,CAAC,CACH,CACA,OAAOhY,CACT,CAMA,SAASkY,GAAcC,EAAkBjY,EAAa4N,EAAsB,CAC1E,IAAMrI,EAAS0S,EAAgB,aAC1B1S,GAAO,QAAQvF,CAAG,GACvBuM,EAAM,IAAM,CAAEhH,EAAM,QAAQvF,CAAG,EAAG4N,CAAK,CAAG,CAAC,CAC7C,CAKA,SAASsK,GAAWD,EAAwB,CAC1C,IAAM1S,EAAS0S,EAAgB,aACzBH,EAAeG,EAAgB,oBACrC,GAAI,CAAC1S,GAAS,CAACuS,EAAa,OAE5B,IAAM7S,EAAU6I,GAAWgK,CAAW,EACtCvL,EAAM,IAAM,CACV,OAAW,CAACvM,EAAKuG,CAAG,IAAK,OAAO,QAAQtB,CAAO,EAC7CM,EAAM,QAAQvF,CAAG,IAAIuG,CAAG,CAE5B,CAAC,CACH,CAIA,IAAI4R,GAAmE,KAEvE,SAASC,IAAgB,CACvB,OAAKD,KACHA,GAAcE,GAAiB,CAC7B,WAAAnD,EACA,aAAAM,EACA,oBAAqB,CACfC,GACFA,EAAU,WAAW,CAEzB,EACA,mBAAoB,CAClB,GAAIA,EAAW,CACb,IAAMhH,EAAS,SAAS,MAAQ,SAAS,gBACrCA,GACFgH,EAAU,QAAQhH,EAAQ,CACxB,UAAW,GACX,QAAS,GACT,WAAY,GACZ,gBAAiB,CAAC,kBAAkB,CACtC,CAAC,CAEL,CACF,EACA,MAAAlC,CACF,CAAC,GAEI4L,EACT,CAGA,SAASG,GAAUC,EAAoBC,EAAoB,CACzDJ,GAAc,EAAEG,EAAWC,CAAI,CACjC","names":["runtime_exports","__export","applyContainmentHints","clearDiagnostics","destroyRuntime","getDiagnostics","getScopes","getUnsafeEvalMode","initRuntime","mount","reconcile","resetScope","setDebug","setDiagnostics","setDirectiveMap","setScopeValue","setUnsafeEval","setUnsafeEvalMode","unmount","yieldToMain","createReactiveSystem","update","notify","unwatched","link","unlink","propagate","checkDirty","shallowPropagate","dep","sub","version","prevDep","nextDep","prevSub","newLink","nextSub","next","stack","top","flags","isValidLink","subSubs","checkDepth","dirty","subs","firstSub","hasMultipleSubs","checkLink","cycle","batchDepth","notifyIndex","queuedLength","activeSub","queued","link","unlink","propagate","checkDirty","shallowPropagate","createReactiveSystem","node","updateComputed","updateSignal","effect","insertIndex","firstInsertedIndex","left","purgeDeps","effectScopeOper","setActiveSub","sub","prevSub","activeSub","startBatch","batchDepth","endBatch","flush","signal","initialValue","signalOper","computed","getter","computedOper","effect","fn","e","prevSub","setActiveSub","link","activeSub","effectOper","updateComputed","c","cycle","prevSub","setActiveSub","oldValue","activeSub","purgeDeps","updateSignal","s","run","flags","checkDirty","flush","notifyIndex","queuedLength","effect","queued","computedOper","subs","shallowPropagate","sub","link","signalOper","value","propagate","batchDepth","effectOper","effectScopeOper","unlink","depsTail","dep","applySignalSet","s","v","equals","prevSub","setActiveSub","prev","next","createSignal","initialValue","options","signal","getter","eq","currentRoot","registerDisposer","dispose","currentRoot","hasActiveRoot","POOL_SIZE","pool","i","POOL_SIZE","internalEffect","fn","dispose","effect","hasActiveRoot","registerDisposer","createComputed","fn","computed","batch","fn","startBatch","endBatch","longestIncreasingSubsequence","arr","n","tails","tailIndices","predecessor","tailsLen","i","val","lo","hi","mid","result","idx","SMALL_LIST_THRESHOLD","reconcileSmall","parent","oldItems","newItems","oldNodes","keyFn","createFn","updateFn","beforeNode","hooks","oldLen","newLen","oldKeys","i","oldIndices","oldUsed","key","found","j","node","allSameOrder","nodes","reusedIndices","reusedPositions","lisOfReused","longestIncreasingSubsequence","lisFlags","li","newNodes","nextSibling","isNew","reconcileList","SMALL_LIST_THRESHOLD","oldKeyMap","oldIdx","getBindTargets","el","targets","attrs","i","name","ownsSubtree","getStateKeys","json","obj","sameShape","keysA","keysB","determineScopeMode","liveEl","newEl","liveModule","newModule","liveStateJSON","newStateJSON","liveKeys","newKeys","_parseTemplate","parseHTML","html","patchAttributes","bindTargets","hasDataShow","hasDataModel","liveHasClassDirectives","liveAttrs","newAttrs","attr","patchTextNodes","liveTexts","newTexts","child","usedLive","liveIdx","newText","newChildIdx","liveText","ref","findTextInsertionRef","lt","newIdx","j","sibling","key","match","diffChildren","liveParent","newParent","config","liveChildren","newChildren","liveKeyed","liveUnkeyed","unkeyedIdx","usedLiveElements","newChild","liveMatch","candidate","replaceInnerContent","replacement","ensurePosition","clone","insertionRef","findInsertionPoint","nestedScopes","nested","parent","_newEl","nextNewChild","nextKey","nextLive","existing","createReconciler","_lastHtml","container","trimmed","scopes","scope","fragment","templateContainer","hasOverlap","liveScopes","newScopes","_refetchRegistry","$refetch","id","fn","_debug","dbg","createChildScope","parent","locals","localGetters","key","target","prop","_unsafeEvalMode","_allowUnsafeEval","_diagnosticsEnabled","args","diagnostics","parseBooleanFlag","raw","normalized","parseUnsafeEvalMode","readRuntimeConfig","config","globalConfig","parsed","script","unsafeFromAttr","modeFromAttr","lockFromAttr","diagnosticsFromAttr","containmentFromAttr","reportDiagnostic","kind","expr","reason","now","existing","detail","buildUnsafeEvalMode","runtimeConfig","configUnsafeMode","_autoContainment","getScheduler","candidate","yieldToMain","scheduler","resolve","applyContainmentHints","root","options","selector","nodes","applied","i","el","contain","contentVisibility","containIntrinsicSize","skipExisting","changed","containCurrent","contentVisCurrent","containSizeCurrent","RE_STRING_SINGLE","RE_STRING_DOUBLE","RE_NUMBER","RE_IDENTIFIER","RE_DOT_ACCESS","RE_BRACKET","RE_TERNARY","RE_NULLISH","RE_AND","RE_OR","RE_COMPARISON","RE_MUL","RE_ADD","RE_TEMPLATE_LIT","RE_TEMPLATE_INTERP","RE_GROUP_METHOD_CALL","RE_STRIP_BRACES","RE_DIGIT_ONLY","RE_POST_INCR","RE_PRE_INCR","RE_TOGGLE","RE_ASSIGN","RE_COMPOUND","RE_IF_PREFIX","RE_COMPUTED","RE_FETCH","RE_FETCH_METHOD","RE_STRIP_ITEM_BRACES","RE_EVENT_REF","RE_REFETCH_CALL","TRANSITION_STATE_SYM","EXPRESSION_CACHE_MAX","expressionCache","cacheExpression","key","factory","first","scopeExpressionCache","scopeHandlerCache","compiledTemplateCache","COMPILED_TEMPLATE_CACHE_MAX","cacheCompiledTemplate","template","UNSAFE_METHOD_NAMES","BLOCKED_METHOD_REGEXES","result","name","escaped","findBlockedMethod","expr","cleaned","dotRe","bracketRe","bracketContents","extractBracketContents","content","fragments","joined","f","results","depth","start","TEXT_BINDING_SYM","toTextValue","value","setElementTextFast","el","next","cache","node","splitCallArgs","raw","out","inSingle","inDouble","i","ch","readBalancedSegment","input","open","close","inTemplate","splitTopLevelStatements","depthParen","depthBrace","depthBracket","stmt","tail","consumeStatement","block","body","rest","parseIfHandler","scope","idx","condSegment","condExpr","parseExpression","thenStmt","thenHandler","parseHandler","elseHandler","elseStmt","e","batch","unwrapOuterParens","segment","inner","compileTemplate","text","cached","statics","dynamics","lastIndex","re","m","templateTexts","evaluateCompiledTemplate","compiled","item","result","i","key","cloneWithTemplateData","template","clone","walker","node","text","compileTemplate","templateTexts","cloneAttributeTemplates","updateTemplateData","el","templateAttrs","DIRECTIVE_ATTR_PREFIXES","isDirectiveAttr","name","prefix","splitClassTokens","raw","parseDurationTokenMs","token","parseClassTokensAndDuration","classes","durationMs","parsed","uniqueTokens","tokens","parseCssTimeListMs","part","ms","maxCombinedTimingsMs","durations","delays","len","max","d","delay","resolveTransitionDurationMs","explicitMs","cs","trans","anim","getTransitionState","existing","TRANSITION_STATE_SYM","created","clearTransitionState","state","parseTransitionSpec","a","base","enter","leave","enterFrom","enterTo","leaveFrom","leaveTo","durationBoth","enterDuration","leaveDuration","removeClasses","cls","addClasses","runTransitionPhase","phaseClasses","onDone","cleanupClasses","done","timeoutId","raf1","raf2","finish","transitionInsert","parent","ref","spec","current","transitionRemove","applyShowVisibility","visible","transition","initial","all","entries","attr","parseChainedAccess","expr","scope","pos","identMatch","rootName","steps","optional","nameMatch","UNSAFE_METHOD_NAMES","balanced","readBalancedSegment","argsRaw","argFns","arg","splitCallArgs","parseExpression","rootExpr","val","step","method","args","fn","cachedFactory","expressionCache","parseExpressionUncached","cacheExpression","RE_IDENTIFIER","s","RE_STRING_SINGLE","RE_STRING_DOUBLE","RE_NUMBER","dotMatch","RE_DOT_ACCESS","p1","p2","unwrapped","unwrapOuterParens","chainResult","groupedCallMatch","RE_GROUP_METHOD_CALL","baseRaw","methodName","baseExpr","inner","bracketMatch","RE_BRACKET","objExpr","rawKey","RE_DIGIT_ONLY","elements","elementFns","allParsed","ternaryMatch","RE_TERNARY","cond","then","els","nullishMatch","RE_NULLISH","left","right","orMatch","RE_OR","andMatch","RE_AND","compMatch","RE_COMPARISON","op","l","r","addMatch","RE_ADD","mulMatch","RE_MUL","tmplMatch","RE_TEMPLATE_LIT","staticParts","dynamicFns","lastIndex","re","RE_TEMPLATE_INTERP","m","getScopeCache","cache","scoped","cspExpressionHint","buildEvaluator","cleaned","RE_STRIP_BRACES","scopeExpressionCache","cached","cspFn","_allowUnsafeEval","dbg","reportDiagnostic","blocked","blockedMethod","findBlockedMethod","msg","proxy","_","g","unsafe","failed","parseHandler","normalized","ifHandler","parseIfHandler","stmts","splitTopLevelStatements","handlers","h","e","batch","single","incrMatch","RE_POST_INCR","preIncrMatch","RE_PRE_INCR","toggleMatch","RE_TOGGLE","assignMatch","RE_ASSIGN","valExpr","_debug","compoundMatch","RE_COMPOUND","refetchMatch","RE_REFETCH_CALL","fetchId","$refetch","buildHandler","seg","scopeHandlerCache","value","FORBIDDEN_STATE_KEYS","parseState","initScope","stateEl","keys","getters","setters","get","set","createSignal","SAFE_EL_PROPS","createSafeElProxy","target","prop","bindElement","disposers","elMagics","detail","createChildScope","known","getDirectives","computedAttr","parts","trimmed","match","RE_COMPUTED","prevGetter","evaluate","getter","createComputed","textExpr","dispose","internalEffect","setElementTextFast","toTextValue","showExpr","tag","initialized","ifExpr","placeholder","inserted","show","modelExpr","setter","input","event","onModelInput","hasColonDirectives","hasAnyPrefix","attrs","built","handler","id","attrVal","tracedHandler","attrName","persistExpr","saved","listExpr","templateEl","disposeCloneBindings","createBoundClone","index","childScope","itemDisposers","desc","updateBoundClone","keyAttr","keyProp","RE_STRIP_ITEM_BRACES","listTransition","oldItems","oldNodes","listHooks","htmlEl","rawItems","n","leavingNodes","ln","prevNodes","reconcileList","idx","nextNodes","wrapped","w","fetchExpr","arrowMatch","RE_FETCH","urlPart","modifiers","url","methodMatch","RE_FETCH_METHOD","loadingTarget","errorTarget","interval","mod","k","v","getTarget","setTarget","gl","sl","ge","se","doFetch","data","err","_refetchRegistry","DIRECTIVE_SELECTOR","hasDirective","_directiveMap","setDirectiveMap","map","buildDirectiveSelector","prefixes","entry","mountScope","root","boundCount","selector","targets","descendants","unmountScope","_observer","ELEMENT_NODE","MUTATION_CHUNK_SIZE","_pendingMutations","_drainingMutations","processMutation","mutation","removed","j","added","drainMutationQueue","yieldToMain","handleMutations","mutations","startObserver","stopObserver","initRuntime","_autoContainment","applyContainmentHints","stateRoots","destroyRuntime","mount","unmount","setDebug","on","setUnsafeEvalMode","mode","_unsafeEvalMode","setUnsafeEval","getUnsafeEvalMode","setDiagnostics","_diagnosticsEnabled","getDiagnostics","diagnostics","clearDiagnostics","getScopes","roots","initialJSON","values","setScopeValue","element","resetScope","_reconciler","getReconciler","createReconciler","reconcile","container","html"]}