@blotch/angular-lynx 22.2.0 → 22.2.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blotch-angular-lynx.mjs","names":[],"sources":["../../src/lib/accessibility/accessibility.ts","../../src/lib/animation/animation.ts","../../src/lib/devtools/performance.ts","../../src/lib/devtools/stats.ts","../../src/lib/devtools/devtools.ts","../../src/lib/data-flow/data-processors.ts","../../src/lib/data-flow/global-data.ts","../../src/lib/data-flow/init-data.ts","../../src/lib/error-handler/lynx-error-handler.ts","../../src/lib/exposure/exposure.ts","../../src/lib/exposure/global-exposure.ts","../../src/lib/font/font.ts","../../src/lib/lazy-bundle/lazy-bundle.ts","../../src/lib/locale/lynx-locale.ts","../../src/lib/locale/providers.ts","../../src/lib/gesture/base-gesture.ts","../../src/lib/gesture/composition.ts","../../src/lib/gesture/types.ts","../../src/lib/gesture/fling-gesture.ts","../../src/lib/gesture/event.ts","../../src/lib/gesture/state-manager.ts","../../src/lib/gesture/gesture-detector.ts","../../src/lib/gesture/const.ts","../../src/lib/gesture/long-press-gesture.ts","../../src/lib/gesture/pan-gesture.ts","../../src/lib/gesture/pinch-gesture.ts","../../src/lib/gesture/rotation-gesture.ts","../../src/lib/gesture/tap-gesture.ts","../../src/lib/lynx-elements/base.ts","../../src/lib/lynx-elements/blur-view.ts","../../src/lib/lynx-elements/cover-view.ts","../../src/lib/forms/lynx-input-value-accessor.ts","../../src/lib/forms/lynx-textarea-value-accessor.ts","../../src/lib/forms/index.ts","../../src/lib/lynx-elements/frame.ts","../../src/lib/lynx-elements/image.ts","../../src/lib/lynx-elements/input.ts","../../src/lib/lynx-elements/list.ts","../../src/lib/lynx-elements/misc.ts","../../src/lib/lynx-elements/overlay.ts","../../src/lib/lynx-elements/refresh.ts","../../src/lib/lynx-elements/scroll-coordinator.ts","../../src/lib/lynx-elements/scroll-view.ts","../../src/lib/lynx-elements/svg.ts","../../src/lib/lynx-elements/text.ts","../../src/lib/lynx-elements/title-bar-view.ts","../../src/lib/lynx-elements/video.ts","../../src/lib/lynx-elements/view.ts","../../src/lib/lynx-elements/viewpager.ts","../../src/lib/lynx-elements/webview.ts","../../src/lib/lynx-elements/index.ts","../../src/lib/lynx-logger/lynx-logger.ts","../../src/lib/native-module/native-module.ts","../../src/lib/renderer/token.ts","../../src/lib/portal/portal.ts","../../src/lib/main-thread/main-thread-fn.ts","../../src/lib/main-thread/background-fn.ts","../../src/lib/main-thread/main-thread-ref.ts","../../src/lib/main-thread/main-thread-element.ts","../../src/lib/main-thread/main-thread-event.ts","../../src/lib/main-thread/main-thread.ts","../../src/lib/resource-prefetch/resource-prefetch.ts","../../src/lib/system-info/system-info.ts","../../src/lib/safe-area/safe-area.ts","../../src/lib/session-storage/session-storage.ts","../../src/lib/text-measure/text-measure.ts","../../src/lib/theme/theme.ts","../../src/lib/transition/lynx-transition.ts","../../src/lib/transition/lynx-transition-group.ts","../../src/lib/animation/noop-animation.ts","../../src/lib/lynx-element/lynx-background-element.ts","../../src/lib/lynx-document/element-creators/create-block-element.ts","../../src/lib/lynx-document/element-creators/create-blur-view-element.ts","../../src/lib/lynx-document/element-creators/create-comment-element.ts","../../src/lib/lynx-document/element-creators/create-cover-view-element.ts","../../src/lib/lynx-document/element-creators/create-default-element.ts","../../src/lib/lynx-document/element-creators/create-for-element.ts","../../src/lib/lynx-document/element-creators/create-frame-element.ts","../../src/lib/lynx-document/element-creators/create-if-element.ts","../../src/lib/lynx-document/element-creators/create-image-element.ts","../../src/lib/lynx-document/element-creators/create-inline-truncation-element.ts","../../src/lib/lynx-document/element-creators/create-input-element.ts","../../src/lib/lynx-document/element-creators/create-list-item-element.ts","../../src/lib/lynx-document/element-creators/create-overlay-element.ts","../../src/lib/lynx-document/element-creators/create-raw-text-element.ts","../../src/lib/lynx-document/element-creators/create-refresh-element.ts","../../src/lib/lynx-document/element-creators/create-scroll-coordinator-element.ts","../../src/lib/lynx-document/element-creators/create-scroll-view-element.ts","../../src/lib/lynx-document/element-creators/create-svg-element.ts","../../src/lib/lynx-document/element-creators/create-text-element.ts","../../src/lib/lynx-document/element-creators/create-title-bar-view-element.ts","../../src/lib/lynx-document/element-creators/create-video-element.ts","../../src/lib/lynx-document/element-creators/create-view-element.ts","../../src/lib/lynx-document/element-creators/create-viewpager-element.ts","../../src/lib/lynx-document/element-creators/create-webview-element.ts","../../src/lib/lynx-document/create-native-ref.ts","../../src/lib/lynx-document/page-ref.ts","../../src/lib/lynx-render-lifecycle.ts","../../src/lib/lynx-element/types.ts","../../src/lib/lynx-element/lynx-element.ts","../../src/lib/lynx-element/lynx-list-element.ts","../../src/lib/lynx-document/lynx-background-document.ts","../../src/lib/lynx-document/element-creators/create-list-element.ts","../../src/lib/lynx-document/element-creators/create-page-element.ts","../../src/lib/lynx-document/lynx-document.ts","../../src/lib/ssr/hydrate-document.ts","../../src/lib/renderer/renderer.ts","../../src/lib/renderer/emulated-lynx-renderer.ts","../../src/lib/renderer/lynx-renderer-factory2.ts","../../src/lib/renderer/providers.ts","../../src/lib/router/lynx-location-strategy.ts","../../src/lib/router/lynx-platform-location.ts","../../src/lib/router/lynx-route-reuse-strategy.ts","../../src/lib/router/lynx-router.ts","../../src/lib/error-reporting.ts","../../src/lib/url/percent-encoding.ts","../../src/lib/url/host.ts","../../src/lib/url/url-record.ts","../../src/lib/url/url-search-params.ts","../../src/lib/url/url.ts","../../src/lib/url/index.ts","../../src/lib/polyfills.ts","../../src/lib/ssr/opcodes.ts","../../src/lib/ssr/build-element-queue.ts","../../src/lib/ssr/serialize-tree.ts","../../src/lib/ssr/ssr-callbacks.ts","../../src/lib/worklet-bridge.ts","../../src/lib/global-callbacks.ts","../../src/lib/lazy-bundle/chunk-loader.ts","../../src/lib/runtime.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\n\n/**\n * Programmatic accessibility control for screen readers on Lynx.\n *\n * Provides two imperative APIs that complement the declarative accessibility\n * attributes (`accessibility-element`, `accessibility-label`, etc.) already\n * available on Lynx element directives.\n *\n * @usageNotes\n * ```typescript\n * const a11y = inject(LynxAccessibility);\n *\n * // Announce a state change to screen readers\n * await a11y.announce('Item added to cart');\n *\n * // Move accessibility focus to a specific element\n * await a11y.requestFocus('#confirmation-message');\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxAccessibility {\n /**\n * Makes screen readers announce the specified text content.\n *\n * Use this to notify visually impaired users of state changes or\n * operation results that aren't reflected by focus movement alone\n * (e.g. toast messages, background task completion, live counters).\n *\n * Wraps `lynx.accessibilityAnnounce()`.\n */\n announce(content: string): Promise<void> {\n if (\n typeof lynx === 'undefined' ||\n typeof (lynx as any).accessibilityAnnounce !== 'function'\n ) {\n return Promise.reject(\n new Error(\n 'lynx.accessibilityAnnounce is not available in this environment',\n ),\n );\n }\n\n return new Promise<void>((resolve) => {\n (lynx as any).accessibilityAnnounce({ content }, () => resolve());\n });\n }\n\n /**\n * Programmatically moves accessibility focus (screen reader cursor)\n * to the element matching the given selector.\n *\n * The target element should have `accessibility-element=\"true\"` set.\n * Only ID selectors are reliably supported (e.g. `'#myElement'`).\n *\n * Wraps `lynx.createSelectorQuery().select(selector).invoke({ method: 'requestAccessibilityFocus' }).exec()`.\n */\n requestFocus(selector: string): Promise<void> {\n if (typeof lynx === 'undefined' || !lynx.createSelectorQuery) {\n return Promise.reject(\n new Error(\n 'lynx.createSelectorQuery is not available in this environment',\n ),\n );\n }\n\n return new Promise<void>((resolve, reject) => {\n lynx\n .createSelectorQuery()\n .select(selector)\n .invoke({\n method: 'requestAccessibilityFocus',\n params: {},\n success: () => resolve(),\n fail: (res) =>\n reject(\n new Error(\n `requestAccessibilityFocus failed (code ${res.code})${res.data ? ': ' + JSON.stringify(res.data) : ''}`,\n ),\n ),\n })\n .exec();\n });\n }\n}\n","import type {\n Animation as LynxJsAnimation,\n AnimationOptions,\n} from '@lynx-js/types/main-thread';\n\nimport type { ElementRef } from '../types/lynx';\n\n/**\n * Extends the official AnimationOptions with Lynx-native property aliases\n * and relaxed types that accept string values (e.g. \"300ms\").\n */\nexport type LynxAnimationOptions = AnimationOptions & {\n iterationCount?: number | string;\n fillMode?: string;\n timingFunction?: string;\n};\n\n/**\n * Shared interface for all animation implementations (real and no-op).\n * Used by `BaseLynxElement.animate()` return type so both `LynxAnimation`\n * (main thread) and `NoopLynxAnimation` (background thread) are valid.\n * Required because LynxAnimation uses ES private fields (#element, #count)\n * which brand the class — TypeScript's structural typing won't accept\n * NoopLynxAnimation as assignable to LynxAnimation. This shared Pick type\n * extracts only the public API both implementations satisfy.\n */\nexport type BaseLynxAnimation = Pick<\n LynxJsAnimation,\n 'id' | 'cancel' | 'pause' | 'play'\n>;\n\n/**\n * Wire-protocol constants for __ElementAnimate operations.\n * Must match the native Lynx engine expectations (see PAPI types).\n */\nconst ANIMATION_START = 0 as const;\nconst ANIMATION_PLAY = 1 as const;\nconst ANIMATION_PAUSE = 2 as const;\nconst ANIMATION_CANCEL = 3 as const;\n\n/**\n * Represents a running animation on a Lynx element.\n * Created by calling `element.animate()` on a LynxElement.\n * Mirrors the Animation class from React Lynx's worklet-runtime.\n */\nexport class LynxAnimation implements Pick<\n LynxJsAnimation,\n 'id' | 'cancel' | 'pause' | 'play'\n> {\n static #count = 0;\n\n readonly id: string;\n readonly #element: ElementRef;\n\n constructor(\n element: ElementRef,\n keyframes: Record<string, string | number>[],\n options: LynxAnimationOptions,\n ) {\n this.#element = element;\n this.id = `__lynx-angular-animation-${LynxAnimation.#count++}`;\n\n // Normalize Web Animation API property names to CSS animation property\n // names that @lynx-js/web-core's __ElementAnimate expects.\n // Native Lynx accepts both, but web-core only maps the CSS variants\n // (iterationCount, timingFunction, fillMode).\n const wireOptions: Record<string, unknown> = { ...options };\n if (options.iterations != null && !('iterationCount' in options)) {\n wireOptions['iterationCount'] =\n options.iterations === Infinity ? 'infinite' : options.iterations;\n }\n if (options.easing != null && !('timingFunction' in options)) {\n wireOptions['timingFunction'] = options.easing;\n }\n if (options.fill != null && !('fillMode' in options)) {\n wireOptions['fillMode'] = options.fill;\n }\n\n // Immediately start the animation on the native element.\n __ElementAnimate(this.#element, [\n ANIMATION_START,\n options.name ?? this.id,\n keyframes,\n wireOptions,\n ]);\n }\n\n play(): void {\n __ElementAnimate(this.#element, [ANIMATION_PLAY, this.id]);\n }\n\n pause(): void {\n __ElementAnimate(this.#element, [ANIMATION_PAUSE, this.id]);\n }\n\n cancel(): void {\n __ElementAnimate(this.#element, [ANIMATION_CANCEL, this.id]);\n }\n}\n","import { Injectable } from '@angular/core';\n\n/**\n * Wraps Lynx's native performance tracing APIs (`lynx.performance`).\n *\n * All methods are no-ops when `lynx.performance` is unavailable (e.g. in tests\n * or non-Lynx environments) or when profiling is not actively recording.\n *\n * @usageNotes\n * ```typescript\n * const perf = inject(LynxPerformance);\n *\n * perf.profileStart('MyComponent::render', { itemCount: 42 });\n * // ... do work ...\n * perf.profileEnd();\n *\n * perf.profileMark('dataLoaded', { source: 'cache' });\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxPerformance {\n #perf: LynxPerformanceAPI | null = this.#resolve();\n\n #resolve(): LynxPerformanceAPI | null {\n if (typeof lynx !== 'undefined' && (lynx as any).performance) {\n return (lynx as any).performance;\n }\n return null;\n }\n\n /**\n * Whether profiling is actively recording traces.\n * Returns false when `lynx.performance` is unavailable.\n */\n isRecording(): boolean {\n return this.#perf?.isProfileRecording?.() ?? false;\n }\n\n /**\n * Begin a named trace. Must be paired with `profileEnd()`.\n * Traces nest — multiple `profileStart` calls create a stack.\n */\n profileStart(\n name: string,\n options?: { flowId?: number; args?: Record<string, unknown> },\n ): void {\n this.#perf?.profileStart?.(name, options);\n }\n\n /**\n * End the current trace (top of the trace stack).\n */\n profileEnd(): void {\n this.#perf?.profileEnd?.();\n }\n\n /**\n * Emit a discrete mark event in the trace timeline.\n */\n profileMark(\n name: string,\n options?: { args?: Record<string, unknown> },\n ): void {\n this.#perf?.profileMark?.(name, options);\n }\n\n /**\n * Generate a unique flow ID for correlating multi-threaded traces.\n */\n profileFlowId(): number {\n return this.#perf?.profileFlowId?.() ?? 0;\n }\n}\n\ntype LynxPerformanceAPI = {\n profileStart?(\n name: string,\n options?: {\n flowId?: number;\n flowIds?: number[];\n args?: Record<string, unknown>;\n },\n ): void;\n profileEnd?(): void;\n profileMark?(\n name: string,\n options?: { args?: Record<string, unknown> },\n ): void;\n profileFlowId?(): number;\n isProfileRecording?(): boolean;\n};\n","import type { DevToolsStats } from './devtools.types';\n\n/**\n * Module-level counters for hot-path instrumentation.\n * Plain object avoids DI/signal overhead on every element operation.\n * Only incremented when __PROFILE__ is true (dead-code-eliminated otherwise).\n */\nexport const devStats: DevToolsStats & { reset(): void } = {\n cdCycles: 0,\n elementCreated: 0,\n elementRemoved: 0,\n flushCount: 0,\n lastCdDurationMs: 0,\n\n reset(): void {\n this.cdCycles = 0;\n this.elementCreated = 0;\n this.elementRemoved = 0;\n this.flushCount = 0;\n this.lastCdDurationMs = 0;\n },\n};\n","import { Injectable, signal, computed } from '@angular/core';\nimport type { DevToolsStats } from './devtools.types';\nimport { devStats } from './stats';\n\n/**\n * High-level DevTools service exposing performance stats as Angular signals.\n *\n * Stats are only meaningful when the app is built with `__PROFILE__` enabled.\n * In production builds, counters are never incremented (the instrumentation\n * code is dead-code-eliminated), so all values remain zero.\n *\n * @usageNotes\n * ```typescript\n * const devtools = inject(LynxDevTools);\n *\n * // Read stats reactively in a template\n * <text>CD cycles: {{ devtools.stats().cdCycles }}</text>\n *\n * // Take a one-shot snapshot\n * const snap = devtools.snapshot();\n * console.log('Elements created:', snap.elementCreated);\n *\n * // Reset counters\n * devtools.reset();\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxDevTools {\n // `#tick` is a \"refresh trigger\" signal. Reading it inside the `stats`\n // computed creates a reactive dependency: when `refresh()` increments it,\n // Angular invalidates the computed and re-runs it, picking up fresh values\n // from the plain `devStats` object. Without this, `stats` would be computed\n // once and never update (plain objects aren't reactive).\n readonly #tick = signal(0);\n\n /**\n * Reactive stats snapshot. Re-reads from `devStats` each time\n * `refresh()` is called, or automatically after `reset()`.\n */\n readonly stats = computed<DevToolsStats>(() => {\n this.#tick();\n return {\n cdCycles: devStats.cdCycles,\n elementCreated: devStats.elementCreated,\n elementRemoved: devStats.elementRemoved,\n flushCount: devStats.flushCount,\n lastCdDurationMs: devStats.lastCdDurationMs,\n };\n });\n\n /**\n * Take a non-reactive snapshot of current counters.\n */\n snapshot(): DevToolsStats {\n return {\n cdCycles: devStats.cdCycles,\n elementCreated: devStats.elementCreated,\n elementRemoved: devStats.elementRemoved,\n flushCount: devStats.flushCount,\n lastCdDurationMs: devStats.lastCdDurationMs,\n };\n }\n\n /**\n * Bump the signal so `stats()` re-evaluates with latest counter values.\n */\n refresh(): void {\n this.#tick.update((n) => n + 1);\n }\n\n /**\n * Zero all counters and update the reactive signal.\n */\n reset(): void {\n devStats.reset();\n this.#tick.update((n) => n + 1);\n }\n}\n","import type {\n DataProcessorDefinition,\n InitData,\n InitDataRaw,\n} from './data-flow.types';\n\n/**\n * Register data processor functions that the native Lynx runtime calls before\n * delivering init data to the app. Maps to the global `processData` callback.\n *\n * Call this before bootstrapApplication so that native data is transformed\n * before LynxInitData receives the first onDataChanged event.\n *\n * @example\n * registerDataProcessors({\n * defaultDataProcessor: (raw) => ({ ...raw, theme: raw.theme ?? 'light' }),\n * });\n * bootstrapApplication(App, appConfig);\n */\nexport const registerDataProcessors = (\n definition: DataProcessorDefinition,\n): void => {\n (globalThis as any).processData = (\n data: InitDataRaw,\n processorName?: string,\n ): InitData => {\n try {\n if (processorName) {\n return (definition.dataProcessors?.[processorName]?.(data) ??\n data) as InitData;\n }\n return (definition.defaultDataProcessor?.(data) ?? data) as InitData;\n } catch {\n // Match React Lynx behavior: a crashing processor returns {} rather than crashing the app.\n return {} as InitData;\n }\n };\n};\n","import { Injectable, signal } from '@angular/core';\nimport type { GlobalData } from './data-flow.types';\n\n@Injectable({ providedIn: 'root' })\nexport class LynxGlobalData {\n // Seeded from lynx.__globalProps at construction time; updated via onGlobalPropsChanged.\n readonly globalData = signal<GlobalData>(\n typeof lynx !== 'undefined'\n ? (lynx.__globalProps as GlobalData)\n : ({} as GlobalData),\n );\n\n constructor() {\n // Only subscribe on the background thread — global props are a host→JS\n // data channel that only fires on the background thread. The main thread\n // check guards against running in the Lepus context where getJSModule\n // doesn't exist and GlobalEventEmitter is not available.\n if (\n typeof lynx === 'undefined' ||\n (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__) ||\n typeof lynx.getJSModule !== 'function'\n )\n return;\n const emitter = lynx.getJSModule('GlobalEventEmitter');\n if (!emitter?.addListener) return;\n emitter.addListener('onGlobalPropsChanged', (...args: unknown[]) =>\n this.globalData.set(args[0] as GlobalData),\n );\n }\n}\n","import { Injectable, signal } from '@angular/core';\nimport type { InitData } from './data-flow.types';\n\n@Injectable({ providedIn: 'root' })\nexport class LynxInitData {\n // Seeded from lynx.__initData at construction time; updated reactively via onDataChanged.\n // __initData is not declared in @lynx-js/types, so we access it via any.\n readonly initData = signal<InitData>(\n typeof lynx !== 'undefined'\n ? ((lynx as any).__initData as InitData)\n : ({} as InitData),\n );\n\n constructor() {\n // Same background-thread-only guard as LynxGlobalData — GlobalEventEmitter\n // is a background-thread API. See global-data.ts for details.\n if (\n typeof lynx === 'undefined' ||\n (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__) ||\n typeof lynx.getJSModule !== 'function'\n )\n return;\n const emitter = lynx.getJSModule('GlobalEventEmitter');\n if (!emitter?.addListener) return;\n emitter.addListener('onDataChanged', (...args: unknown[]) =>\n this.initData.set(args[0] as InitData),\n );\n }\n}\n","import {\n type ErrorDetails,\n type ErrorHandler,\n Injectable,\n} from '@angular/core';\n\n/**\n * Keep the on-device debug string up-to-date. There is no console on device,\n * so components surface this global via a `<text>` element.\n */\nconst recordLastError = (err: Error): void => {\n (globalThis as any).__lynxLastError =\n `${err.name}: ${err.message}\\n${err.stack ?? ''}`;\n};\n\n/**\n * Angular ErrorHandler that routes errors to the native Lynx error reporting API.\n *\n * Automatically provided by provideRenderer(). Also writes to __lynxLastError\n * so components can surface errors as <text> elements (no console on device).\n */\n@Injectable()\nexport class LynxErrorHandler implements ErrorHandler {\n handleError(error: unknown): void {\n const err = error instanceof Error ? error : new Error(String(error));\n recordLastError(err);\n\n // errorCode 1101 = ErrCode::LYNX_ERROR_CODE_LEPUS (matches React Lynx convention).\n if (typeof _ReportError === 'function') {\n _ReportError(err, { errorCode: 1101 });\n }\n }\n\n /**\n * Called by Angular for rendering errors caught by an `@boundary` block.\n *\n * Without this override Angular falls back to `handleError`, which reports a\n * fatal LEPUS error — on device that raises the red error overlay even though\n * the boundary already swapped in its `@error` fallback and the app is still\n * usable. A caught error is recoverable by definition, so it goes to\n * `lynx.reportError` at `warning` level instead: monitoring still sees it,\n * but it isn't treated as a crash.\n *\n * Angular calls this synchronously mid-render, so it must not write to\n * signals (NG0600) — it only touches a plain global and the native bridge.\n */\n onViewError(error: Error, _details: ErrorDetails): void {\n recordLastError(error);\n\n // `lynx` only exists inside the Lynx runtime (not in Node tests or SSR),\n // and `reportError` needs background-thread 2.3+ / main-thread 3.0+.\n if (typeof lynx !== 'undefined' && typeof lynx.reportError === 'function') {\n lynx.reportError(error, { level: 'warning' });\n }\n }\n}\n","import {\n Directive,\n ElementRef,\n inject,\n type OnDestroy,\n signal,\n} from '@angular/core';\nimport type { BaseLynxElement } from '../lynx-element/types';\n\n@Directive({\n selector: '[lynxExposure]',\n exportAs: 'lynxExposure',\n})\nexport class LynxExposure implements OnDestroy {\n readonly #el: BaseLynxElement = inject(ElementRef).nativeElement;\n\n // Whether this element is currently visible in the viewport.\n readonly visible = signal(false);\n\n #removeAppear: (() => void) | null = null;\n #removeDisappear: (() => void) | null = null;\n\n constructor() {\n // `binduiappear` / `binduidisappear` are Lynx-native events fired by the\n // element's UIAppearance system — the equivalent of IntersectionObserver on web.\n // They fire when the element enters or leaves the visible viewport of its\n // scroll container, enabling lazy-load and analytics tracking patterns.\n this.#removeAppear = this.#el.addEventListener('binduiappear', () =>\n this.visible.set(true),\n );\n this.#removeDisappear = this.#el.addEventListener('binduidisappear', () =>\n this.visible.set(false),\n );\n }\n\n ngOnDestroy(): void {\n this.#removeAppear?.();\n this.#removeDisappear?.();\n }\n}\n","import { Injectable, signal } from '@angular/core';\nimport type {\n GlobalExposureEvent,\n ObserverFrameRateOptions,\n} from './exposure.types';\n\n@Injectable({ providedIn: 'root' })\nexport class LynxGlobalExposure {\n // Updated each time the Lynx engine fires a batched 'exposure' event via\n // GlobalEventEmitter. Contains the most recent batch of exposure details.\n readonly exposures = signal<GlobalExposureEvent>([]);\n\n // Updated each time the Lynx engine fires a batched 'disexposure' event.\n readonly disexposures = signal<GlobalExposureEvent>([]);\n\n // Whether the global exposure detection system is currently active.\n // Lynx allows pausing/resuming via stopExposure()/resumeExposure().\n readonly active = signal<boolean>(true);\n\n constructor() {\n // GlobalEventEmitter is only available on the background thread (BTS context).\n // On the main thread, getJSModule may return null or a stub without addListener,\n // and calling it crashes the main-thread Angular app — which handles rendering.\n // Since the main thread app stays broken, all subsequent route renders are blank.\n if (\n typeof lynx === 'undefined' ||\n (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__)\n )\n return;\n const emitter = lynx.getJSModule('GlobalEventEmitter');\n if (!emitter?.addListener) return;\n emitter.addListener('exposure', (...args: unknown[]) =>\n this.exposures.set(args[0] as GlobalExposureEvent),\n );\n emitter.addListener('disexposure', (...args: unknown[]) =>\n this.disexposures.set(args[0] as GlobalExposureEvent),\n );\n }\n\n /**\n * Pauses global exposure detection. Elements with exposure-id stop generating\n * exposure/disexposure GlobalEventEmitter events. Element-level\n * binduiappear/binduidisappear events continue to fire.\n */\n stopExposure(options?: { sendEvent: boolean }): void {\n if (typeof lynx === 'undefined') return;\n lynx.stopExposure(options);\n this.active.set(false);\n }\n\n resumeExposure(): void {\n if (typeof lynx === 'undefined') return;\n lynx.resumeExposure();\n this.active.set(true);\n }\n\n setObserverFrameRate(options?: ObserverFrameRateOptions): void {\n if (typeof lynx === 'undefined') return;\n lynx.setObserverFrameRate(options);\n }\n}\n","import { computed, Injectable, signal } from '@angular/core';\nimport type {\n LynxFontEntry,\n LynxFontFaceConfig,\n LynxFontStatus,\n} from './font.types';\n\n/**\n * Wraps `lynx.addFont()` with a Promise-based API and reactive signal state.\n *\n * Use CSS `@font-face` in stylesheets for fonts known at build time (the\n * standard Angular approach). Use this service only for fonts that must be\n * loaded dynamically at runtime.\n *\n * @usageNotes\n * ```typescript\n * const fontService = inject(LynxFont);\n *\n * await fontService.addFont({\n * fontFamily: 'CustomFont',\n * src: 'https://example.com/custom-font.ttf',\n * });\n *\n * // Reactive state\n * const loaded = fontService.loadedFamilies(); // ReadonlySet<string>\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxFont {\n readonly #fonts = signal<ReadonlyMap<string, LynxFontEntry>>(new Map());\n readonly #pending = new Map<string, Promise<void>>();\n\n readonly fonts = this.#fonts.asReadonly();\n\n readonly loadedFamilies = computed(() => {\n const loaded = new Set<string>();\n for (const [, entry] of this.#fonts()) {\n if (entry.status === 'loaded') {\n loaded.add(entry.fontFamily);\n }\n }\n return loaded as ReadonlySet<string>;\n });\n\n addFont(config: LynxFontFaceConfig): Promise<void> {\n if (typeof lynx === 'undefined') {\n return Promise.reject(\n new Error('lynx.addFont is not available in this environment'),\n );\n }\n\n const { fontFamily, src } = config;\n\n const existing = this.#fonts().get(fontFamily);\n if (existing?.status === 'loaded') {\n return Promise.resolve();\n }\n // Return the already-in-flight promise to deduplicate concurrent callers.\n // Without this guard, two simultaneous addFont() calls would both invoke\n // lynx.addFont() and race to settle the same font.\n if (existing?.status === 'loading') {\n return this.#pending.get(fontFamily)!;\n }\n\n this.#updateEntry(fontFamily, { fontFamily, src, status: 'loading' });\n\n const promise = new Promise<void>((resolve, reject) => {\n (lynx as any).addFont(\n { 'font-family': fontFamily, src },\n (err?: Error) => {\n if (err) {\n this.#updateEntry(fontFamily, {\n fontFamily,\n src,\n status: 'error',\n error: err,\n });\n this.#pending.delete(fontFamily);\n reject(err);\n } else {\n this.#updateEntry(fontFamily, {\n fontFamily,\n src,\n status: 'loaded',\n });\n this.#pending.delete(fontFamily);\n resolve();\n }\n },\n );\n });\n\n this.#pending.set(fontFamily, promise);\n return promise;\n }\n\n isLoaded(fontFamily: string): boolean {\n return this.#fonts().get(fontFamily)?.status === 'loaded';\n }\n\n getStatus(fontFamily: string): LynxFontStatus {\n return this.#fonts().get(fontFamily)?.status ?? 'idle';\n }\n\n #updateEntry(fontFamily: string, entry: LynxFontEntry): void {\n // Clone the Map before mutating — signals use reference equality, so\n // mutating the existing Map in-place wouldn't trigger reactivity.\n const next = new Map(this.#fonts());\n next.set(fontFamily, entry);\n this.#fonts.set(next);\n }\n}\n","import type { Type } from '@angular/core';\n\ndeclare const __MAIN_THREAD__: boolean;\n\n/**\n * Module-level cache so repeat calls to loadLazyBundle() with the same source\n * return the same promise. Angular Router calls loadComponent() on each navigation\n * to a lazy route; without caching, each visit would re-fetch the bundle.\n */\nconst cache = new Map<string, Promise<Type<unknown>>>();\n\n/**\n * Loads an external Lynx component bundle at runtime and returns the Angular\n * component type. Wraps the native `__QueryComponent` PAPI — bundles must be\n * built with `experimental_isLazyBundle: true` in the rsbuild plugin.\n */\nexport const loadLazyBundle = (source: string): Promise<Type<unknown>> => {\n const cached = cache.get(source);\n if (cached) {\n return cached;\n }\n\n const promise = loadBundle(source);\n cache.set(source, promise);\n return promise;\n};\n\nconst loadBundle = (source: string): Promise<Type<unknown>> => {\n if (typeof __QueryComponent !== 'function') {\n return Promise.reject(\n new Error(\n `loadLazyBundle: __QueryComponent is not available. ` +\n `Ensure you are running in a Lynx environment.`,\n ),\n );\n }\n\n if (__MAIN_THREAD__) {\n return loadOnMainThread(source);\n }\n\n return loadOnBackgroundThread(source);\n};\n\n/**\n * Main-thread (Lepus) loading is synchronous — __QueryComponent evaluates the\n * bundle inline and returns immediately. The callback parameter is required by\n * the PAPI signature but never fires on the main thread (it's for background\n * thread async loading). The empty callback is a no-op placeholder.\n */\nconst loadOnMainThread = (source: string): Promise<Type<unknown>> => {\n try {\n const result = __QueryComponent(source, () => {});\n const exports = result.evalResult as Record<string, unknown>;\n const component = (exports?.['default'] ?? exports) as Type<unknown>;\n return Promise.resolve(component);\n } catch (e) {\n // Main thread renders once for first-screen — return a never-resolving\n // promise so Lynx doesn't crash on failed lazy loads (matches React Lynx).\n // The component simply won't appear in the first-screen render, which is\n // acceptable since lazy components are below-the-fold by definition.\n reportError(source, e);\n return new Promise(() => {});\n }\n};\n\n/**\n * Background-thread loading is async — __QueryComponent triggers the native\n * runtime to fetch the .lynx.bundle file, evaluate its JS, and invoke the\n * callback with the result. result.data.evalResult is a function (not a value)\n * that must be called with the source name to execute the bundle's AMD module\n * registration and return the component exports.\n */\nconst loadOnBackgroundThread = (source: string): Promise<Type<unknown>> => {\n return new Promise((resolve, reject) => {\n __QueryComponent(source, (result) => {\n if (result.code === 0) {\n try {\n const exports = result.data.evalResult(source) as Record<\n string,\n unknown\n >;\n const component = (exports?.['default'] ?? exports) as Type<unknown>;\n resolve(component);\n } catch (e) {\n const error = new Error(\n `loadLazyBundle: Failed to evaluate bundle \"${source}\"`,\n { cause: e },\n );\n reportError(source, error);\n reject(error);\n }\n } else {\n const error = new Error(\n `loadLazyBundle: Failed to load bundle \"${source}\" (code: ${result.code})`,\n );\n reportError(source, error);\n reject(error);\n }\n });\n });\n};\n\nconst reportError = (source: string, cause: unknown): void => {\n if (typeof _ReportError === 'function') {\n const error =\n cause instanceof Error\n ? cause\n : new Error(`loadLazyBundle failed for \"${source}\"`);\n _ReportError(error, { errorCode: 6 });\n }\n};\n","import { computed, inject, Injectable } from '@angular/core';\nimport { LynxGlobalData } from '../data-flow/global-data';\n\n/**\n * Pulls a validated `appLocale` string out of a Lynx global-props bag.\n * Shared by `getLynxAppLocale()` and `LynxLocale` so both agree on what\n * counts as \"the host set a locale\" (a non-empty string).\n */\nconst extractAppLocale = (\n globalProps: Record<string, unknown> | undefined,\n): string | undefined => {\n const value = globalProps?.['appLocale'];\n return typeof value === 'string' && value ? value : undefined;\n};\n\n/**\n * Reads `lynx.__globalProps.appLocale` directly, without Angular DI.\n *\n * Use this before `bootstrapApplication()` runs — e.g. to conditionally call\n * `loadTranslations()` — since no injector exists yet at that point. Once the\n * app is bootstrapped, prefer injecting `LynxLocale` for reactive access.\n *\n * Returns `undefined` outside a Lynx environment or when the host hasn't set\n * a locale; callers decide their own fallback.\n *\n * @usageNotes\n * ```typescript\n * if (getLynxAppLocale() === 'fr') {\n * loadTranslations({ 'app.greeting': 'Bonjour le monde !' });\n * }\n *\n * bootstrapApplication(App, appConfig);\n * ```\n */\nexport const getLynxAppLocale = (): string | undefined => {\n if (typeof lynx === 'undefined') {\n return undefined;\n }\n return extractAppLocale(lynx.__globalProps as Record<string, unknown>);\n};\n\n/**\n * Provides reactive access to the current locale on Lynx.\n *\n * Reads `lynx.__globalProps.appLocale` (set by the native host). Falls back to\n * the `sourceLocale` from angular.json (injected as `__LYNX_SOURCE_LOCALE__`\n * at build time), then to `'en-US'`.\n *\n * @usageNotes\n * ```typescript\n * const locale = inject(LynxLocale);\n *\n * // Reactive in templates\n * template: `<text>Current locale: {{ locale.locale() }}</text>`\n *\n * // For LOCALE_ID integration, add provideLocale() to your app config\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxLocale {\n readonly #globalData = inject(LynxGlobalData);\n\n /**\n * The current locale. Reactive — updates when global props change.\n */\n readonly locale = computed(() => {\n const value = extractAppLocale(\n this.#globalData.globalData() as Record<string, unknown>,\n );\n if (value) {\n return value;\n }\n // Fall back to the compile-time source locale from angular.json\n return typeof __LYNX_SOURCE_LOCALE__ !== 'undefined'\n ? __LYNX_SOURCE_LOCALE__\n : 'en-US';\n });\n}\n","import {\n type EnvironmentProviders,\n inject,\n LOCALE_ID,\n makeEnvironmentProviders,\n} from '@angular/core';\nimport { LynxLocale } from './lynx-locale';\n\n/**\n * Provides Angular's `LOCALE_ID` token from the Lynx runtime locale.\n *\n * Add this to your application's providers to automatically configure\n * Angular's locale-aware features (pipes, i18n) with the locale from\n * `lynx.__globalProps.appLocale`.\n *\n * @usageNotes\n * ```typescript\n * bootstrapApplication(App, {\n * providers: [provideRenderer(), provideLocale()],\n * });\n * ```\n */\nexport const provideLocale = (): EnvironmentProviders => {\n return makeEnvironmentProviders([\n {\n provide: LOCALE_ID,\n useFactory: () => inject(LynxLocale).locale(),\n },\n ]);\n};\n","import type { GestureStateManager } from './state-manager';\nimport type { GestureCallback, GestureEvent, GestureType } from './types';\n\nlet nextGestureId = 1;\n\nexport type GestureCallbackWithState<\n TEvent extends GestureEvent = GestureEvent,\n> = (event: TEvent, stateManager: GestureStateManager) => void;\n\nexport abstract class BaseGesture<\n TEvent extends GestureEvent = GestureEvent,\n TSelf extends BaseGesture<TEvent, any> = any,\n> {\n readonly id = nextGestureId++;\n abstract readonly type: GestureType;\n\n /**\n * @internal — accessed by the directive to build the PAPI config.\n * GestureCallback<any> avoids an invariance error when assigning concrete gesture\n * subclasses (e.g. PanGesture) to BaseGesture<GestureEvent, any>. The directive\n * already casts callbacks to any when invoking them, so the wider type is safe.\n */\n _callbacks: Record<string, GestureCallback<any>> = {};\n /**\n * @internal\n */\n _config: Record<string, unknown> = {};\n /**\n * @internal\n */\n _waitFor: BaseGesture[] = [];\n /**\n * @internal\n */\n _simultaneousWith: BaseGesture[] = [];\n /**\n * @internal\n */\n _continueWith: BaseGesture[] = [];\n\n onBegin(cb: GestureCallbackWithState<TEvent>): TSelf {\n this._callbacks['onBegin'] = cb as GestureCallback<TEvent>;\n return this as unknown as TSelf;\n }\n\n /**\n * Fires when the gesture is RECOGNIZED (transitions to active). For a tap this\n * is the only callback that fires exclusively on success — see `onEnd`.\n */\n onStart(cb: GestureCallbackWithState<TEvent>): TSelf {\n this._callbacks['onStart'] = cb as GestureCallback<TEvent>;\n return this as unknown as TSelf;\n }\n\n /**\n * Fires when the gesture ends.\n *\n * For discrete gestures (tap, long-press) LynxGestureDetector normalizes this\n * to fire ONLY when the gesture was actually recognized. Lynx's native engine\n * emits `onEnd` on failure too — the iOS `fail` path calls it — so a drag that\n * overshoots a tap's `maxDistance` would otherwise still trigger `onEnd`. The\n * directive suppresses that failed-gesture `onEnd`; continuous gestures pass\n * through unchanged. See gesture-detector.ts.\n */\n onEnd(cb: GestureCallbackWithState<TEvent>): TSelf {\n this._callbacks['onEnd'] = cb as GestureCallback<TEvent>;\n return this as unknown as TSelf;\n }\n\n onTouchesDown(cb: GestureCallbackWithState<TEvent>): TSelf {\n this._callbacks['onTouchesDown'] = cb as GestureCallback<TEvent>;\n return this as unknown as TSelf;\n }\n\n onTouchesUp(cb: GestureCallbackWithState<TEvent>): TSelf {\n this._callbacks['onTouchesUp'] = cb as GestureCallback<TEvent>;\n return this as unknown as TSelf;\n }\n\n /**\n * Delays this gesture until all listed gestures have failed.\n * Use to give higher-priority gestures (e.g. double-tap) first right of refusal.\n * `as unknown as TSelf` is needed because TypeScript can't prove that `this`\n * satisfies the concrete TSelf bound — the double cast is intentional.\n */\n waitFor(...gestures: BaseGesture[]): TSelf {\n this._waitFor.push(...gestures);\n return this as unknown as TSelf;\n }\n\n /**\n * Allows this gesture and the listed gestures to be active at the same time.\n * Without this, Lynx's gesture system lets only one gesture be active per element.\n */\n simultaneousWith(...gestures: BaseGesture[]): TSelf {\n this._simultaneousWith.push(...gestures);\n return this as unknown as TSelf;\n }\n\n /**\n * This gesture activates after the listed gestures END (not fail).\n * Useful for chaining: e.g. a long-press followed by a drag.\n */\n continueWith(...gestures: BaseGesture[]): TSelf {\n this._continueWith.push(...gestures);\n return this as unknown as TSelf;\n }\n\n enabled(value: boolean): TSelf {\n this._config['enabled'] = value;\n return this as unknown as TSelf;\n }\n}\n\n/**\n * Continuous gestures (pan, fling, rotation, pinch) have an onUpdate callback\n * that fires on every frame while the gesture is active.\n */\nexport abstract class ContinuousGesture<\n TEvent extends GestureEvent = GestureEvent,\n TSelf extends ContinuousGesture<TEvent, any> = any,\n> extends BaseGesture<TEvent, TSelf> {\n onUpdate(cb: GestureCallbackWithState<TEvent>): TSelf {\n this._callbacks['onUpdate'] = cb as GestureCallback<TEvent>;\n return this as unknown as TSelf;\n }\n}\n","import type { BaseGesture } from './base-gesture';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyGesture = BaseGesture<any, any>;\n\nexport class ComposedGesture {\n constructor(\n readonly gestures: AnyGesture[],\n readonly compositionType: 'simultaneous' | 'exclusive' | 'race',\n ) {}\n}\n\nexport const Gesture = {\n // All gestures can recognize simultaneously — none blocks the others.\n Simultaneous(...gestures: AnyGesture[]): ComposedGesture {\n for (const g of gestures) {\n g.simultaneousWith(...gestures.filter((o) => o !== g));\n }\n return new ComposedGesture(gestures, 'simultaneous');\n },\n\n // Gestures are tried in order — each waits for all previous to fail before activating.\n // E.g. Exclusive(doubleTap, singleTap): singleTap waits for doubleTap to fail\n // before it can activate, giving doubleTap priority.\n Exclusive(...gestures: AnyGesture[]): ComposedGesture {\n for (let i = 1; i < gestures.length; i++) {\n gestures[i].waitFor(...gestures.slice(0, i));\n }\n return new ComposedGesture(gestures, 'exclusive');\n },\n\n // First gesture to recognize wins — no explicit dependency relations.\n Race(...gestures: AnyGesture[]): ComposedGesture {\n return new ComposedGesture(gestures, 'race');\n },\n};\n","/**\n * Gesture type IDs matching the Lynx native engine (from @lynx-js/react gesture-runtime).\n */\nexport enum GestureType {\n PAN = 0,\n FLING = 1,\n DEFAULT = 2,\n TAP = 3,\n LONGPRESS = 4,\n ROTATION = 5,\n PINCH = 6,\n NATIVE = 7,\n}\n\nexport enum GestureState {\n UNDETERMINED = 0,\n BEGAN = 1,\n ACTIVE = 2,\n END = 3,\n FAILED = 4,\n CANCELED = 5,\n}\n\nexport type GestureEvent = {\n /**\n * Optional: the native engine conveys the phase through the callback that\n * fires (onBegin/onStart/onUpdate/onEnd), not a field on the event payload,\n * so `state` is usually absent at runtime.\n */\n state?: GestureState;\n /**\n * Absolute (page-relative) coordinates, derived at runtime by mapGestureEvent\n * from the native `pageX`/`pageY`. Optional (was required) because they're\n * only present when the gesture's payload carries coordinates — making the\n * type promise a `number` that isn't always there was a latent footgun.\n */\n absoluteX?: number;\n absoluteY?: number;\n /**\n * The untouched native params dict (Lynx field names: scrollX, pageX, x, y,\n * isAtStart, …). Escape hatch for reading fields that have no flat alias —\n * the flat properties above are derived from it. See mapGestureEvent.\n */\n params?: Record<string, unknown>;\n};\n\nexport type PanGestureEvent = {\n translationX: number;\n translationY: number;\n velocityX: number;\n velocityY: number;\n} & GestureEvent;\n\nexport type TapGestureEvent = {\n x: number;\n y: number;\n} & GestureEvent;\n\nexport type FlingGestureEvent = {\n velocityX: number;\n velocityY: number;\n} & GestureEvent;\n\nexport type PinchGestureEvent = {\n scale: number;\n velocity: number;\n} & GestureEvent;\n\nexport type RotationGestureEvent = {\n rotation: number;\n velocity: number;\n} & GestureEvent;\n\nexport type LongPressGestureEvent = {\n x: number;\n y: number;\n duration: number;\n} & GestureEvent;\n\n/**\n * Bitmask values — combine with bitwise OR for multi-direction fling:\n * e.g. FlingDirection.LEFT | FlingDirection.RIGHT for horizontal fling.\n */\nexport enum FlingDirection {\n RIGHT = 1,\n LEFT = 2,\n UP = 4,\n DOWN = 8,\n}\n\nexport type GestureCallback<TEvent extends GestureEvent = GestureEvent> = (\n event: TEvent,\n) => void;\n","import { ContinuousGesture } from './base-gesture';\nimport {\n type FlingGestureEvent,\n type FlingDirection,\n GestureType,\n} from './types';\n\nexport class FlingGesture extends ContinuousGesture<\n FlingGestureEvent,\n FlingGesture\n> {\n readonly type = GestureType.FLING;\n\n /**\n * FlingDirection is a bitmask — combine values with | for multi-direction:\n * e.g. FlingDirection.LEFT | FlingDirection.RIGHT recognizes horizontal flings.\n */\n direction(dir: FlingDirection): this {\n this._config['direction'] = dir;\n return this;\n }\n\n /**\n * The gesture only recognizes when exactly `count` fingers are involved.\n * Defaults to 1 if not set.\n */\n numberOfPointers(count: number): this {\n this._config['numberOfPointers'] = count;\n return this;\n }\n}\n","import type { GestureEvent } from './types';\n\n/**\n * Per-gesture translation origin. Lynx reports the finger's absolute position on\n * every event but never the accumulated translation, so the directive keeps one\n * of these per active gesture and mapGestureEvent derives translation from it.\n * `null` means \"not yet anchored\" — the next event seeds it.\n */\nexport type GestureOrigin = { x: number | null; y: number | null };\n\nexport const createGestureOrigin = (): GestureOrigin => ({ x: null, y: null });\n\n/**\n * Adapts a raw Lynx gesture event into AngularLynx's flat event shape.\n *\n * The native engine delivers a nested envelope —\n * `{ type, timestamp, target, currentTarget, params: {...}, detail: {...} }`\n * (built by GetCustomEventParam in core/renderer/events/touch_event_handler.cc)\n * — where the gesture data lives under `params`. The iOS handlers\n * (LynxPanGestureHandler/LynxBaseGestureHandler) populate `params` with the\n * finger's *position*: `x`/`y` (element-relative), `pageX`/`pageY` (page-\n * relative), `clientX`/`clientY`, plus `scrollX`/`scrollY` — which are the\n * gesture member's *scroll offset* (0 for a non-scrolling `<view>`), NOT the\n * drag distance. There is no native `translationX`/`translationY`.\n *\n * AngularLynx's public API is react-native-gesture-handler-style\n * (`translationX`, `absoluteX`, …), so we:\n * - map `pageX`/`pageY` → `absoluteX`/`absoluteY`,\n * - spread the raw params so every native field stays reachable by its own name\n * (covers `x`/`y`, `scrollX`/`scrollY`, `isAtStart`/`isAtEnd`, and pinch\n * `scale` / rotation `rotation` etc.),\n * - keep the raw `params` dict as an escape hatch,\n * - and DERIVE `translationX`/`translationY` as the offset from the gesture's\n * origin (see `origin`), since Lynx doesn't provide it. Without this, a handler\n * reading `event.translationX` sees `0` forever (the old scrollX alias) or\n * `undefined` → `NaN`.\n *\n * @param raw The native event envelope.\n * @param name The callback name (onBegin/onStart/onUpdate/onEnd/…) — used to\n * seed the origin at gesture start and clear it at end.\n * @param origin Per-gesture mutable origin; omit for stateless mapping (e.g.\n * discrete gestures like tap where translation is meaningless).\n */\nexport const mapGestureEvent = (\n raw: unknown,\n name?: string,\n origin?: GestureOrigin,\n): GestureEvent => {\n const event = (raw ?? {}) as Record<string, unknown>;\n // Gesture data lives under `params`; fall back to the event itself so a\n // future/alternate envelope (or an already-flat test double) still works.\n const params: Record<string, unknown> =\n event['params'] && typeof event['params'] === 'object'\n ? (event['params'] as Record<string, unknown>)\n : event;\n\n const absoluteX = params['pageX'] as number | undefined;\n const absoluteY = params['pageY'] as number | undefined;\n\n const mapped = {\n ...params,\n params,\n target: event['target'],\n currentTarget: event['currentTarget'],\n absoluteX,\n absoluteY,\n } as GestureEvent & { translationX?: number; translationY?: number };\n\n if (origin) {\n // Anchor the origin at the gesture's first event (or an explicit begin/\n // start), then report translation relative to it. Reset at end so the next\n // gesture measures from its own start.\n if (name === 'onBegin' || name === 'onStart' || origin.x === null) {\n origin.x = absoluteX ?? 0;\n origin.y = absoluteY ?? 0;\n }\n // origin.x/y are guaranteed numeric here: the anchor block above always\n // runs on the first event (origin.x === null) and populates both fields.\n // The `?? 0` fallbacks on absoluteX/Y are the real defense — they come\n // from the native payload and are typed as number|undefined.\n mapped.translationX = (absoluteX ?? 0) - (origin.x as number);\n mapped.translationY = (absoluteY ?? 0) - (origin.y as number);\n if (name === 'onEnd') {\n origin.x = null;\n origin.y = null;\n }\n }\n\n return mapped;\n};\n","import type { ElementRef } from '../types/lynx';\n\n/**\n * Controls gesture state from within a callback.\n * Wraps __SetGestureState and __ConsumeGesture PAPI calls.\n * Passed as the second argument to gesture callbacks so handlers can\n * programmatically drive the gesture state machine (e.g. activate a gesture\n * only when a condition is met, or fail it early to let a competing gesture win).\n */\nexport class GestureStateManager {\n readonly #element: ElementRef;\n readonly #gestureId: number;\n\n constructor(element: ElementRef, gestureId: number) {\n this.#element = element;\n this.#gestureId = gestureId;\n }\n\n /**\n * State codes match Lynx's native gesture state enum:\n * 1 = ACTIVE, 2 = FAILED, 3 = END\n */\n fail(): void {\n __SetGestureState(this.#element, this.#gestureId, 2);\n }\n\n activate(): void {\n __SetGestureState(this.#element, this.#gestureId, 1);\n }\n\n end(): void {\n __SetGestureState(this.#element, this.#gestureId, 3);\n }\n\n /**\n * `{ consume }` stops the gesture from bubbling up to ancestor elements.\n * Use this when this element should handle the gesture exclusively and\n * parent scroll containers or gesture detectors should not also receive it.\n */\n consumeGesture(consume = true): void {\n __ConsumeGesture(this.#element, this.#gestureId, { consume });\n }\n\n /**\n * `{ inner: intercept }` intercepts gestures from DESCENDANT elements —\n * the opposite direction of consumeGesture. Use this on a parent to claim\n * a gesture before children can handle it (e.g. a pull-to-refresh view\n * intercepting scrolls inside its list child).\n */\n interceptGesture(intercept = true): void {\n __ConsumeGesture(this.#element, this.#gestureId, { inner: intercept });\n }\n}\n","import {\n Directive,\n ElementRef,\n inject,\n type OnChanges,\n type OnDestroy,\n type SimpleChanges,\n} from '@angular/core';\nimport type { BaseLynxElement } from '../lynx-element/types';\nimport type { BaseGesture } from './base-gesture';\nimport { ComposedGesture } from './composition';\nimport {\n type GestureOrigin,\n createGestureOrigin,\n mapGestureEvent,\n} from './event';\nimport { GestureStateManager } from './state-manager';\nimport { GestureType } from './types';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyGesture = BaseGesture<any, any>;\ntype GestureInput = AnyGesture | AnyGesture[] | ComposedGesture;\n\n/**\n * Directive that bridges Angular's gesture binding to Lynx's native gesture\n * system (__SetGestureDetector / __RemoveGestureDetector). Accepts a single\n * gesture, an array of gestures, or a ComposedGesture (simultaneous/exclusive).\n * Each gesture is registered with the native engine via its unique numeric ID.\n *\n * Cross-package prerequisite (easy to miss when debugging): the native engine\n * silently ignores every __SetGestureDetector call unless the compiled page\n * config has `enableNewGesture: true`. @blotch/rsbuild-plugin-angular-lynx\n * defaults that flag ON, so this directive works out of the box — but if\n * gestures ever go dead app-wide with no error, that build flag is the first\n * thing to check, not this directive.\n */\n@Directive({\n selector: '[lynxGesture]',\n inputs: ['lynxGesture'],\n})\nexport class LynxGestureDetector implements OnChanges, OnDestroy {\n readonly #el: BaseLynxElement = inject(ElementRef).nativeElement;\n #attachedIds: number[] = [];\n\n lynxGesture!: GestureInput;\n\n /**\n * Full teardown + re-register on every input change. This is safe because\n * gesture IDs are stable (assigned once in BaseGesture constructor), so\n * inter-gesture relationships (waitFor, simultaneousWith) stay valid.\n */\n ngOnChanges(_changes: SimpleChanges): void {\n this.#detachAll();\n const gestures = this.#resolveGestures();\n if (gestures.length === 0) return;\n\n // On the background thread the element is a virtual node with no native\n // handle (.element is undefined); native gesture registration only happens\n // on the main thread, so there's nothing to do here otherwise.\n const elementRef = (this.#el as any).element;\n if (!elementRef) return;\n\n // Force the element onto its own native layer. Lynx \"flattens\" a view that\n // has no event listeners and no non-flatten attributes into its parent's\n // layer for performance, and a flattened view cannot receive its own\n // gestures. Unlike adding a DOM event listener, registering a gesture\n // detector does NOT auto-mark the element non-flatten, so we set it\n // explicitly — mirroring React Lynx's processGesture. `flatten` is an\n // Android-only concept (a no-op on iOS), but it's required for gestures to\n // fire on Android.\n __SetAttribute(elementRef, 'flatten', false);\n\n for (const g of gestures) {\n // GestureStateManager allows callbacks to programmatically fail/activate\n // the gesture (e.g. to implement conditional gesture recognition).\n const stateManager = new GestureStateManager(elementRef, g.id);\n // Per-gesture translation origin, shared across this gesture's callbacks\n // so mapGestureEvent can derive translationX/Y from the finger's absolute\n // position (Lynx reports position each event, never accumulated distance).\n const origin = createGestureOrigin();\n const config = {\n callbacks: buildGestureCallbacks(g, origin, stateManager),\n config: Object.keys(g._config).length > 0 ? g._config : undefined,\n };\n // Relationship map tells the native gesture system how gestures interact:\n // - waitFor: this gesture waits for the dependency to fail before recognizing\n // - simultaneous: both gestures can be active at the same time\n // - continueWith: this gesture activates after the dependency ends\n const relationMap: Record<string, number[]> = {\n waitFor: g._waitFor.map((dep) => dep.id),\n simultaneous: g._simultaneousWith.map((dep) => dep.id),\n continueWith: g._continueWith.map((dep) => dep.id),\n };\n\n __SetGestureDetector(elementRef, g.id, g.type, config, relationMap);\n this.#attachedIds.push(g.id);\n }\n }\n\n ngOnDestroy(): void {\n this.#detachAll();\n }\n\n #detachAll(): void {\n const elementRef = (this.#el as any).element;\n if (!elementRef) return;\n for (const id of this.#attachedIds) {\n try {\n __RemoveGestureDetector(elementRef, id);\n } catch {\n // Element may already be destroyed by the native engine.\n }\n }\n this.#attachedIds = [];\n }\n\n #resolveGestures(): AnyGesture[] {\n if (!this.lynxGesture) return [];\n if (this.lynxGesture instanceof ComposedGesture) {\n return this.lynxGesture.gestures;\n }\n if (Array.isArray(this.lynxGesture)) {\n return this.lynxGesture;\n }\n return [this.lynxGesture];\n }\n}\n\n/**\n * Native gesture callback entry expected by __SetGestureDetector. The callback\n * MUST be an OBJECT (`{ _fn }`), not a raw function: under Lynx's fiber\n * architecture the native binding routes a callable into\n * GestureCallback.lepus_function_, but fiber-arch gesture dispatch only reads\n * lepus_object_ (populated when the callback is an object), so a raw function is\n * silently dropped and the gesture never fires. runtime.ts's runWorklet unwraps\n * `_fn`.\n */\ntype NativeCallbackEntry = {\n name: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n callback: { _fn: (event: any) => void };\n};\n\n/**\n * Builds the native callback list for one gesture, wrapping each user callback\n * as `{ _fn }` and injecting the mapped event plus the stateManager (its second\n * argument, so callbacks can programmatically fail/activate the gesture).\n *\n * Discrete gestures (tap, long-press) get a normalization pass. Lynx's native\n * engine fires `onEnd` on BOTH success and failure — the iOS `fail` path emits\n * it — whereas `onStart` fires only on recognition. To give React-Native-\n * Gesture-Handler-style semantics (where `onEnd` means \"the gesture actually\n * happened\"), we observe `onStart` — registering our own observer when the user\n * didn't — to learn whether the gesture was recognized, then drop the\n * failed-gesture `onEnd`. Continuous gestures pass through untouched.\n */\nconst buildGestureCallbacks = (\n gesture: AnyGesture,\n origin: GestureOrigin,\n stateManager: GestureStateManager,\n): NativeCallbackEntry[] => {\n const wrap = (\n name: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n cb: any,\n ): NativeCallbackEntry => ({\n name,\n callback: {\n _fn: (event: any) =>\n cb(mapGestureEvent(event, name, origin), stateManager),\n },\n });\n\n const userEnd = gesture._callbacks['onEnd'];\n const isDiscrete =\n gesture.type === GestureType.TAP || gesture.type === GestureType.LONGPRESS;\n\n // Only a discrete gesture with an onEnd handler needs success/failure\n // disambiguation; everything else is a straight passthrough.\n if (!isDiscrete || !userEnd) {\n return Object.entries(gesture._callbacks).map(([name, cb]) =>\n wrap(name, cb),\n );\n }\n\n const userStart = gesture._callbacks['onStart'];\n // Per-registration recognition flag: `started` flips true only when the native\n // engine reports the gesture became active (onStart). A failed tap never does.\n const lifecycle = { started: false };\n const callbacks: NativeCallbackEntry[] = [\n {\n name: 'onStart',\n callback: {\n _fn: (event: any) => {\n lifecycle.started = true;\n // Forward only if the user registered onStart — this entry exists\n // primarily as our recognition observer.\n if (userStart) {\n (userStart as (event: unknown, sm: GestureStateManager) => void)(\n mapGestureEvent(event, 'onStart', origin),\n stateManager,\n );\n }\n },\n },\n },\n {\n name: 'onEnd',\n callback: {\n _fn: (event: any) => {\n const recognized = lifecycle.started;\n lifecycle.started = false;\n // Drop the native onEnd that fires when the tap/long-press failed.\n if (recognized) {\n (userEnd as (event: unknown, sm: GestureStateManager) => void)(\n mapGestureEvent(event, 'onEnd', origin),\n stateManager,\n );\n }\n },\n },\n },\n ];\n\n // Pass through every other callback (onBegin, onTouchesDown/Up, …) as-is; only\n // onStart (forced observer) and onEnd (suppressed on failure) are special.\n for (const [name, cb] of Object.entries(gesture._callbacks)) {\n if (name === 'onStart' || name === 'onEnd') continue;\n callbacks.push(wrap(name, cb));\n }\n\n return callbacks;\n};\n","/**\n * Default gesture config values, mirrored from Lynx's own gesture-runtime\n * (references/lynx-stack-main/packages/lynx/gesture-runtime/src/utils/const.ts).\n *\n * Why these defaults live in the JS gesture classes instead of relying on the\n * native handlers' own defaults: the iOS handlers read each config key with\n * `[[config objectForKey:@\"maxDuration\"] floatValue]`, and `[nil floatValue]`\n * is `0`. Those built-in defaults (`maxDistance = 10`, etc.) are only applied\n * when the WHOLE config is absent (`handleConfigMap` early-returns on a nil\n * map). The moment ANY config key is present, every *missing* key reads back as\n * `0` — so sending a partial config like `{ numberOfTaps: 2 }` silently zeroes\n * `maxDuration`/`maxDistance` and the tap fails on a 0ms timer the instant a\n * finger touches down. Initializing the full default set on every gesture\n * guarantees a complete config is always sent. See LynxTapGestureHandler.m /\n * LynxLongPressGestureHandler.m `handleConfigMap`.\n */\n\n/** Max finger travel (px) before a tap/long-press is rejected as a drag. */\nexport const DEFAULT_GESTURE_MAX_DISTANCE = 10;\n\n/** Max time (ms) between finger-down and finger-up for a tap to register. */\nexport const DEFAULT_TAP_MAX_DURATION = 500;\n\n/** Min hold time (ms) before a long-press is recognized. */\nexport const DEFAULT_LONG_PRESS_DURATION = 500;\n\n/** Min finger travel (px) before a pan activates (0 = activates immediately). */\nexport const DEFAULT_PAN_MIN_DISTANCE = 0;\n","import { BaseGesture } from './base-gesture';\nimport {\n DEFAULT_GESTURE_MAX_DISTANCE,\n DEFAULT_LONG_PRESS_DURATION,\n} from './const';\nimport { type LongPressGestureEvent, GestureType } from './types';\n\nexport class LongPressGesture extends BaseGesture<\n LongPressGestureEvent,\n LongPressGesture\n> {\n readonly type = GestureType.LONGPRESS;\n\n /**\n * Seed the FULL default config on construction. Without an explicit\n * `maxDistance`, calling only `minDuration()` would send a partial config and\n * the native handler would read `maxDistance` back as `0` — failing the\n * long-press on the tiniest finger jitter. Mirrors Lynx's own gesture-runtime\n * LongPressGesture defaults. See ./const for the full explanation.\n */\n override _config: Record<string, unknown> = {\n enabled: true,\n minDuration: DEFAULT_LONG_PRESS_DURATION,\n maxDistance: DEFAULT_GESTURE_MAX_DISTANCE,\n };\n\n /**\n * Minimum hold time in ms before the gesture is recognized.\n * Shorter presses are treated as taps and ignored.\n */\n minDuration(ms: number): this {\n this._config['minDuration'] = ms;\n return this;\n }\n\n /**\n * If the finger drifts more than `px` pixels from the initial touch point\n * during the hold, the gesture fails — allowing a scroll to take over.\n */\n maxDistance(px: number): this {\n this._config['maxDistance'] = px;\n return this;\n }\n}\n","import { ContinuousGesture } from './base-gesture';\nimport { DEFAULT_PAN_MIN_DISTANCE } from './const';\nimport { type PanGestureEvent, GestureType } from './types';\n\nexport class PanGesture extends ContinuousGesture<PanGestureEvent, PanGesture> {\n readonly type = GestureType.PAN;\n\n /**\n * Seed the default config on construction so a complete config is always sent\n * to native, keeping behavior consistent with the other gestures. Mirrors\n * Lynx's own gesture-runtime PanGesture defaults. See ./const.\n */\n override _config: Record<string, unknown> = {\n enabled: true,\n minDistance: DEFAULT_PAN_MIN_DISTANCE,\n };\n\n minDistance(distance: number): this {\n this._config['minDistance'] = distance;\n return this;\n }\n\n /**\n * activeOffset: the gesture activates once the finger moves past this\n * threshold. A number means \"any direction\" (symmetrical); a tuple [min, max]\n * means the offset must be within that range. Example: activeOffsetX(20)\n * activates after 20px of horizontal movement.\n */\n activeOffsetX(offset: number | [number, number]): this {\n this._config['activeOffsetX'] = offset;\n return this;\n }\n\n activeOffsetY(offset: number | [number, number]): this {\n this._config['activeOffsetY'] = offset;\n return this;\n }\n\n /**\n * failOffset: if the finger moves past this threshold in the perpendicular\n * direction, the gesture fails (ceding to a competing gesture). Example:\n * failOffsetY(10) on a horizontal pan: if the user moves >10px vertically\n * before activating, the gesture fails and a vertical scroll can take over.\n */\n failOffsetX(offset: number | [number, number]): this {\n this._config['failOffsetX'] = offset;\n return this;\n }\n\n failOffsetY(offset: number | [number, number]): this {\n this._config['failOffsetY'] = offset;\n return this;\n }\n\n minPointers(count: number): this {\n this._config['minPointers'] = count;\n return this;\n }\n\n maxPointers(count: number): this {\n this._config['maxPointers'] = count;\n return this;\n }\n}\n","import { ContinuousGesture } from './base-gesture';\nimport { type PinchGestureEvent, GestureType } from './types';\n\nexport class PinchGesture extends ContinuousGesture<\n PinchGestureEvent,\n PinchGesture\n> {\n readonly type = GestureType.PINCH;\n}\n","import { ContinuousGesture } from './base-gesture';\nimport { type RotationGestureEvent, GestureType } from './types';\n\nexport class RotationGesture extends ContinuousGesture<\n RotationGestureEvent,\n RotationGesture\n> {\n readonly type = GestureType.ROTATION;\n}\n","import { BaseGesture } from './base-gesture';\nimport {\n DEFAULT_GESTURE_MAX_DISTANCE,\n DEFAULT_TAP_MAX_DURATION,\n} from './const';\nimport { type TapGestureEvent, GestureType } from './types';\n\nexport class TapGesture extends BaseGesture<TapGestureEvent, TapGesture> {\n readonly type = GestureType.TAP;\n\n /**\n * Seed the FULL default config on construction. The native iOS handler reads\n * any absent config key as `0` once a config is present, so shipping a partial\n * config (e.g. only `numberOfTaps`) would zero out `maxDuration`/`maxDistance`\n * and make every tap fail instantly. Mirrors Lynx's own gesture-runtime\n * TapGesture defaults. See ./const for the full explanation.\n */\n override _config: Record<string, unknown> = {\n enabled: true,\n maxDuration: DEFAULT_TAP_MAX_DURATION,\n maxDistance: DEFAULT_GESTURE_MAX_DISTANCE,\n };\n\n /**\n * For double/triple tap, pair with waitFor on the single-tap gesture so\n * the single-tap handler doesn't fire prematurely before the count is met.\n *\n * ⚠️ NOT enforced by the Lynx native runtime — no platform handler implements\n * multi-tap counting (a whole-tree search of the Lynx source turns up nothing\n * that reads `numberOfTaps`), so setting this is currently a no-op on-device.\n * To detect a double-tap, time successive taps yourself in the callback. Kept\n * for API parity with Lynx's gesture-runtime.\n */\n numberOfTaps(count: number): this {\n this._config['numberOfTaps'] = count;\n return this;\n }\n\n /**\n * Maximum time between finger-down and finger-up for a tap to register.\n * Touches held longer than this are treated as a long-press.\n */\n maxDuration(ms: number): this {\n this._config['maxDuration'] = ms;\n return this;\n }\n\n /**\n * If the finger travels more than `px` pixels before lifting, the tap fails.\n * Keeps a tap distinct from a small drag.\n */\n maxDistance(px: number): this {\n this._config['maxDistance'] = px;\n return this;\n }\n}\n","import {\n Directive,\n ElementRef,\n inject,\n type OnChanges,\n type SimpleChanges,\n} from '@angular/core';\nimport type { BaseLynxElement } from '../lynx-element/types';\n\n/**\n * @Directive() is required so that ng-packagr's Angular partial compiler\n * recognizes this base class as an Angular artifact. The selector is left\n * empty — the class is never used directly as a directive.\n *\n * DESIGN NOTES — why these are directives, not components:\n *\n * 1. No @Component: Components have their own template (<ng-content/>). When a\n * component wraps content, Angular treats that content as \"projected\" — the\n * native parent is not yet established while Angular initializes projected\n * nodes. Any directive inside the projected content that injects\n * ViewContainerRef (e.g. RouterOutlet) will crash because insertAnchorNode\n * calls renderer.insertBefore(null, anchor) — null being the not-yet-resolved\n * native parent. Using @Directive avoids projection entirely; children are\n * rendered as direct element children just like without LYNX_ELEMENTS.\n *\n * 2. Properties are declared as inputs so that Angular's template checker\n * accepts property bindings like [src]=\"url\" without errors. Angular\n * intercepts these bindings and sets them on the directive instance. The\n * ngOnChanges hook forwards every input change to the native Lynx element\n * via BaseLynxElement.setAttribute(), which calls __SetAttribute — the same\n * endpoint that renderer.setProperty() would reach.\n *\n * 3. Events (bindtap, catchtap, bindinput, bindscroll, …) are NOT declared as\n * @Output() because Angular would intercept them and skip the renderer's\n * listen() call, breaking native Lynx event delivery. They continue to work\n * via renderer.listen() which handles all unrecognized event names.\n */\n@Directive({\n inputs: [\n 'id',\n 'name',\n 'accessibility-element',\n 'accessibility-label',\n 'accessibility-trait',\n 'accessibility-elements',\n 'accessibility-elements-hidden',\n 'accessibility-exclusive-focus',\n 'a11y-id',\n 'user-interaction-enabled',\n 'native-interaction-enabled',\n 'event-through',\n 'hit-slop',\n 'block-native-event',\n 'ignore-focus',\n 'ios-enable-simultaneous-touch',\n 'exposure-id',\n 'exposure-scene',\n 'exposure-area',\n 'exposure-screen-margin-top',\n 'exposure-screen-margin-bottom',\n 'exposure-screen-margin-left',\n 'exposure-screen-margin-right',\n 'exposure-ui-margin-top',\n 'exposure-ui-margin-bottom',\n 'exposure-ui-margin-left',\n 'exposure-ui-margin-right',\n ],\n})\nexport class LynxElementBase implements OnChanges {\n readonly #el: BaseLynxElement = inject(ElementRef).nativeElement;\n\n ngOnChanges(changes: SimpleChanges): void {\n for (const name of Object.keys(changes)) {\n const value = changes[name].currentValue;\n if (value != null) {\n this.#el.setAttribute(name, value);\n } else {\n this.#el.removeAttribute(name);\n }\n }\n }\n // ---- Identity ----------------------------------------------------------\n id?: string;\n /**\n * Named reference accessible via lynx.getElementById / findViewByName.\n */\n name?: string;\n\n // ---- Accessibility -----------------------------------------------------\n /**\n * Whether this element is an accessibility node.\n */\n 'accessibility-element'?: boolean;\n /**\n * Text read aloud by screen readers.\n */\n 'accessibility-label'?: string;\n 'accessibility-trait'?: 'none' | 'button' | 'image' | 'text';\n /**\n * Comma-separated list of child element names that are accessibility nodes.\n */\n 'accessibility-elements'?: string;\n 'accessibility-elements-hidden'?: boolean;\n /**\n * Whether this element exclusively captures accessibility focus.\n */\n 'accessibility-exclusive-focus'?: boolean;\n /**\n * Accessibility identifier (separate from name).\n */\n 'a11y-id'?: string;\n\n // ---- Interaction -------------------------------------------------------\n /**\n * Whether the element receives touch events (default: true).\n */\n 'user-interaction-enabled'?: boolean;\n /**\n * Whether the element receives platform-native gestures.\n */\n 'native-interaction-enabled'?: boolean;\n /**\n * Whether touch events pass through to elements below.\n */\n 'event-through'?: boolean;\n /**\n * Extends the touch target area. Object or CSS-shorthand string.\n */\n 'hit-slop'?: string | object;\n /**\n * Whether the element consumes native iOS/Android gestures.\n */\n 'block-native-event'?: boolean;\n /**\n * Whether focus events are suppressed.\n */\n 'ignore-focus'?: boolean;\n /**\n * Allow simultaneous touch recognition (iOS).\n */\n 'ios-enable-simultaneous-touch'?: boolean;\n\n // ---- Exposure tracking -------------------------------------------------\n /**\n * Unique ID used for impression/exposure analytics.\n */\n 'exposure-id'?: string;\n /**\n * Scene identifier grouping exposure events.\n */\n 'exposure-scene'?: string;\n /**\n * Percentage of the element that must be visible (0–100) to trigger exposure.\n */\n 'exposure-area'?: number;\n /**\n * Extends/shrinks the viewport detection zone (top edge, in px).\n */\n 'exposure-screen-margin-top'?: number | string;\n /**\n * Extends/shrinks the viewport detection zone (bottom edge, in px).\n */\n 'exposure-screen-margin-bottom'?: number | string;\n /**\n * Extends/shrinks the viewport detection zone (left edge, in px).\n */\n 'exposure-screen-margin-left'?: number | string;\n /**\n * Extends/shrinks the viewport detection zone (right edge, in px).\n */\n 'exposure-screen-margin-right'?: number | string;\n /**\n * Adjusts the element's own bounding rect for exposure detection (top, in px).\n */\n 'exposure-ui-margin-top'?: number | string;\n /**\n * Adjusts the element's own bounding rect for exposure detection (bottom, in px).\n */\n 'exposure-ui-margin-bottom'?: number | string;\n /**\n * Adjusts the element's own bounding rect for exposure detection (left, in px).\n */\n 'exposure-ui-margin-left'?: number | string;\n /**\n * Adjusts the element's own bounding rect for exposure detection (right, in px).\n */\n 'exposure-ui-margin-right'?: number | string;\n}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Backdrop blur: blurs the content rendered behind the element, like CSS\n * `backdrop-filter: blur()`. On iOS, `blur-effect=\"glass\"` renders the\n * Liquid Glass material.\n */\n@Directive({\n selector: 'blur-view',\n standalone: true,\n inputs: [\n 'blur-radius',\n 'blur-sampling',\n 'enable-auto-blur',\n 'android-capture-target',\n 'experimental-update-blur-radius',\n 'blur-effect',\n 'spacing',\n 'glass-interactive',\n 'glass-tint-color',\n 'glass-style',\n 'ios-user-interface-style',\n ],\n})\nexport class LynxBlurView extends LynxElementBase {\n /**\n * Gaussian blur radius (Android/iOS/Harmony). @default '0px'\n */\n 'blur-radius'?: string;\n /**\n * Downsampling ratio of the blurred area. Higher is faster but softer (Android). @default 6\n */\n 'blur-sampling'?: number;\n /**\n * Whether the blur updates automatically as content behind it changes (Android). @default true\n */\n 'enable-auto-blur'?: boolean;\n /**\n * Raw id of the view to capture and blur; it must have `flatten=\"false\"` (Android).\n */\n 'android-capture-target'?: string;\n /**\n * Switches the internal blur-buffer refresh path (Android, experimental).\n */\n 'experimental-update-blur-radius'?: boolean;\n /**\n * Blur material (iOS). `glass` renders Liquid Glass; `glass-container`\n * merges nested glass `<blur-view>`s into one combined effect. @default 'light'\n */\n 'blur-effect'?:\n | 'light'\n | 'extra-light'\n | 'dark'\n | 'glass'\n | 'glass-container';\n /**\n * Distance at which glass elements inside a `glass-container` start to merge (iOS). @default 0\n */\n spacing?: number;\n /**\n * Whether the glass reacts to touches (iOS). @default false\n */\n 'glass-interactive'?: boolean;\n /**\n * Tint color applied to the glass (iOS). @default 'transparent'\n */\n 'glass-tint-color'?: string;\n /**\n * Glass variant (iOS). @default 'regular'\n */\n 'glass-style'?: 'regular' | 'clear';\n /**\n * Forces a light or dark appearance for the material (iOS, Lynx 4.1+).\n */\n 'ios-user-interface-style'?: 'dark' | 'light';\n}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Renders its children above embedded native views such as `<webview>`\n * (Clay Windows/macOS only). Has no element-specific attributes.\n */\n@Directive({ selector: 'cover-view', standalone: true })\nexport class LynxCoverView extends LynxElementBase {}\n","import {\n Directive,\n ElementRef,\n Renderer2,\n forwardRef,\n inject,\n} from '@angular/core';\nimport { type ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\n/**\n * ControlValueAccessor for <input> elements. Bridges Angular's form model\n * (reactive forms, template-driven NgModel, Signal Forms [formField]) to Lynx's\n * native events (bindinput, bindblur) instead of the standard DOM input/change events.\n *\n * Activated only when a form directive is present (formControl, formControlName,\n * ngModel, or formField) — bare <input> elements continue to use LynxInput alone.\n */\n@Directive({\n selector:\n 'input[formControlName],input[formControl],input[ngModel],input[formField]',\n standalone: true,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n /* v8 ignore next -- Angular metadata: the forwardRef arrow is only invoked by Angular's directive DI resolution, which happens inside a full template render — the accessor's runtime behavior is covered by direct unit tests below. */\n useExisting: forwardRef(() => LynxInputValueAccessor),\n multi: true,\n },\n ],\n host: {\n // host bindings call renderer.listen() — the correct Lynx event path.\n // @Output() would break delivery (template compiler intercepts it).\n '(bindinput)': 'onInput($event)',\n '(bindblur)': 'onBlur()',\n },\n})\nexport class LynxInputValueAccessor implements ControlValueAccessor {\n readonly #renderer = inject(Renderer2);\n readonly #el = inject(ElementRef);\n #onChange: (value: string) => void = () => {};\n #onTouched: () => void = () => {};\n\n onInput(event: Event): void {\n // Lynx bindinput carries the typed value in event.detail.value, not event.target.value.\n this.#onChange(\n (event as CustomEvent<{ value: string }>).detail?.value ?? '',\n );\n }\n\n onBlur(): void {\n this.#onTouched();\n }\n\n writeValue(value: string): void {\n // __SetAttribute(\"value\", ...) is a no-op on Lynx native inputs: the\n // Android/iOS LynxUIBaseInput class has no @LynxProp handler for \"value\",\n // so attribute changes after the user has typed are silently ignored by the\n // native layer. Without this fix, reactive-form resets (e.g. form.reset())\n // would update the Angular model but leave the native input showing stale text.\n // invoke?.() routes to __InvokeUIMethod(\"setValue\", {value}), which is the\n // only supported path for programmatic text updates. The optional call (?.)\n // is a no-op on the background thread (testing) where invoke isn't available.\n this.#el.nativeElement.invoke?.('setValue', { value: value ?? '' });\n }\n\n registerOnChange(fn: (value: string) => void): void {\n this.#onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.#onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n if (isDisabled) {\n this.#renderer.setAttribute(this.#el.nativeElement, 'disabled', 'true');\n } else {\n this.#renderer.removeAttribute(this.#el.nativeElement, 'disabled');\n }\n }\n}\n","import {\n Directive,\n ElementRef,\n Renderer2,\n forwardRef,\n inject,\n} from '@angular/core';\nimport { type ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\n/**\n * ControlValueAccessor for <textarea> elements. Bridges Angular's form model\n * (reactive forms, template-driven NgModel, Signal Forms [formField]) to Lynx's\n * native events (bindinput, bindblur) instead of the standard DOM input/change events.\n *\n * Activated only when a form directive is present (formControl, formControlName,\n * ngModel, or formField) — bare <textarea> elements continue to use LynxTextarea alone.\n */\n@Directive({\n selector:\n 'textarea[formControlName],textarea[formControl],textarea[ngModel],textarea[formField]',\n standalone: true,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n /* v8 ignore next -- Angular metadata: the forwardRef arrow is only invoked by Angular's directive DI resolution, which happens inside a full template render — the accessor's runtime behavior is covered by direct unit tests below. */\n useExisting: forwardRef(() => LynxTextareaValueAccessor),\n multi: true,\n },\n ],\n host: {\n // host bindings call renderer.listen() — the correct Lynx event path.\n // @Output() would break delivery (template compiler intercepts it).\n '(bindinput)': 'onInput($event)',\n '(bindblur)': 'onBlur()',\n },\n})\nexport class LynxTextareaValueAccessor implements ControlValueAccessor {\n readonly #renderer = inject(Renderer2);\n readonly #el = inject(ElementRef);\n #onChange: (value: string) => void = () => {};\n #onTouched: () => void = () => {};\n\n onInput(event: Event): void {\n // Lynx bindinput carries the typed value in event.detail.value, not event.target.value.\n this.#onChange(\n (event as CustomEvent<{ value: string }>).detail?.value ?? '',\n );\n }\n\n onBlur(): void {\n this.#onTouched();\n }\n\n writeValue(value: string): void {\n // Same root cause as LynxInputValueAccessor: LynxUIBaseInput (the shared\n // native base class for both input and textarea on Android/iOS) has no\n // @LynxProp handler for \"value\", so __SetAttribute is silently ignored\n // after the user has typed. invoke?.() calls __InvokeUIMethod(\"setValue\")\n // which is the correct path for programmatic text updates.\n this.#el.nativeElement.invoke?.('setValue', { value: value ?? '' });\n }\n\n registerOnChange(fn: (value: string) => void): void {\n this.#onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.#onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n if (isDisabled) {\n this.#renderer.setAttribute(this.#el.nativeElement, 'disabled', 'true');\n } else {\n this.#renderer.removeAttribute(this.#el.nativeElement, 'disabled');\n }\n }\n}\n","export { LynxInputValueAccessor } from './lynx-input-value-accessor';\nexport { LynxTextareaValueAccessor } from './lynx-textarea-value-accessor';\n\nimport { LynxInputValueAccessor } from './lynx-input-value-accessor';\nimport { LynxTextareaValueAccessor } from './lynx-textarea-value-accessor';\n\n/**\n * Both Lynx form value accessors as a single importable array.\n */\nexport const LYNX_FORM_ACCESSORS = [\n LynxInputValueAccessor,\n LynxTextareaValueAccessor,\n] as const;\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Embeds a separate Lynx bundle as a nested page.\n */\n@Directive({\n selector: 'frame',\n standalone: true,\n inputs: [\n 'src',\n 'data',\n 'global-props',\n 'auto-width',\n 'auto-height',\n 'preset-width',\n 'preset-height',\n 'enable-multi-async-thread',\n ],\n})\nexport class LynxFrame extends LynxElementBase {\n /**\n * URL of the `.lynx.bundle` file to embed.\n */\n src?: string;\n /**\n * Initial data passed into the embedded page.\n */\n data?: Record<string, unknown>;\n /**\n * Global props forwarded to the embedded page's global scope.\n */\n 'global-props'?: Record<string, unknown>;\n /**\n * Size the frame to match its content width.\n */\n 'auto-width'?: boolean;\n /**\n * Size the frame to match its content height.\n */\n 'auto-height'?: boolean;\n /**\n * Width used before the embedded page reports its content size (e.g. `'200px'`).\n */\n 'preset-width'?: string;\n /**\n * Height used before the embedded page reports its content size (e.g. `'200px'`).\n */\n 'preset-height'?: string;\n /**\n * Override the host's multi-async-thread setting for the embedded page.\n */\n 'enable-multi-async-thread'?: boolean;\n}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Displays raster images, base64 data URIs, and animated GIFs.\n */\n@Directive({\n selector: 'image',\n standalone: true,\n inputs: [\n 'src',\n 'mode',\n 'placeholder',\n 'blur-radius',\n 'cap-insets',\n 'cap-insets-scale',\n 'auto-size',\n 'autoplay',\n 'loop-count',\n 'tint-color',\n 'image-config',\n 'prefetch-width',\n 'prefetch-height',\n 'defer-src-invalidation',\n ],\n})\nexport class LynxImage extends LynxElementBase {\n /**\n * Remote URL, local asset path, or base64 data URI.\n */\n src?: string;\n /**\n * How the image is scaled to fit its container.\n * @default 'scaleToFill'\n */\n mode?: 'scaleToFill' | 'aspectFit' | 'aspectFill' | 'center';\n /**\n * Placeholder image shown while the main image loads.\n */\n placeholder?: string;\n /**\n * Gaussian blur radius applied to the image.\n */\n 'blur-radius'?: string;\n /**\n * Nine-slice cap insets for stretching images (CSS shorthand, e.g. \"10px 10px 10px 10px\").\n */\n 'cap-insets'?: string;\n 'cap-insets-scale'?: number;\n /**\n * Automatically size the element to the image's intrinsic dimensions.\n */\n 'auto-size'?: boolean;\n /**\n * Auto-play for animated GIF images.\n */\n autoplay?: boolean;\n /**\n * Number of times to loop the animation (0 = infinite).\n */\n 'loop-count'?: number;\n /**\n * Tint color applied over the image (CSS color string).\n */\n 'tint-color'?: string;\n /**\n * Bitmap color format hint (Android).\n */\n 'image-config'?: 'ARGB_8888' | 'RGB_565';\n /**\n * Pre-declared width for prefetch optimization.\n */\n 'prefetch-width'?: string;\n 'prefetch-height'?: string;\n /**\n * Keep showing the current image while the new src loads.\n */\n 'defer-src-invalidation'?: boolean;\n}\n","import {\n Directive,\n ElementRef,\n inject,\n type SimpleChanges,\n} from '@angular/core';\nimport type { BaseLynxElement } from '../lynx-element/types';\nimport { LynxElementBase } from './base';\n\n/**\n * Single-line text input field.\n */\n@Directive({\n selector: 'input',\n standalone: true,\n inputs: [\n 'type',\n 'placeholder',\n 'value',\n 'maxlength',\n 'readonly',\n 'disabled',\n 'confirm-type',\n 'input-filter',\n 'show-soft-input-on-focus',\n 'ios-auto-correct',\n 'ios-spell-check',\n 'android-fullscreen-mode',\n 'default-value',\n ],\n})\nexport class LynxInput extends LynxElementBase {\n // Injected separately from LynxElementBase.#el because ES private fields\n // are scoped to the declaring class — the subclass cannot access the parent's\n // #el directly. Both fields resolve to the same LynxElement instance at runtime.\n readonly #el: BaseLynxElement = inject(ElementRef).nativeElement;\n\n override ngOnChanges(changes: SimpleChanges): void {\n if ('value' in changes) {\n // __SetAttribute(\"value\", ...) is a no-op for a Lynx native input once\n // the user has typed into it. LynxUIBaseInput on both Android and iOS\n // registers no @LynxProp handler for \"value\", so attribute mutations never\n // reach the native text field. The only supported path is the setValue\n // UIMethod (__InvokeUIMethod(\"setValue\", {value})).\n //\n // invoke? is an optional call: on the background thread (testing library)\n // LynxBackgroundElement doesn't implement invoke, so it becomes a no-op\n // there, which is correct — UIMethod calls are main-thread only.\n //\n // We strip \"value\" from the changes object before forwarding to the base\n // class so that super.ngOnChanges doesn't also call setAttribute(\"value\"),\n // which would be redundant and would not work anyway.\n this.#el.invoke?.('setValue', {\n value: changes['value'].currentValue ?? '',\n });\n const { value: _ignored, ...rest } = changes;\n if (Object.keys(rest).length) super.ngOnChanges(rest);\n } else {\n super.ngOnChanges(changes);\n }\n }\n\n /**\n * Keyboard type shown when this input gains focus.\n */\n type?: 'text' | 'number' | 'digit' | 'password' | 'tel' | 'email';\n /**\n * Greyed-out hint text shown when the field is empty.\n */\n placeholder?: string;\n /**\n * Current value of the field.\n */\n value?: string;\n /**\n * Maximum character count (-1 = unlimited).\n */\n maxlength?: number;\n /**\n * Whether the field is read-only.\n */\n readonly?: boolean;\n /**\n * Whether the field and keyboard are disabled.\n */\n disabled?: boolean;\n /**\n * Label for the soft-keyboard confirm button. @default 'done'\n */\n 'confirm-type'?: 'search' | 'send' | 'go' | 'done' | 'next';\n /**\n * Input character whitelist — a regular expression pattern string.\n */\n 'input-filter'?: string;\n /**\n * Whether tapping the field shows the soft keyboard. @default true\n */\n 'show-soft-input-on-focus'?: boolean;\n /**\n * Enable auto-correction on iOS.\n */\n 'ios-auto-correct'?: boolean;\n /**\n * Enable spell-checking on iOS.\n */\n 'ios-spell-check'?: boolean;\n /**\n * Enter full-screen editing mode on Android.\n */\n 'android-fullscreen-mode'?: boolean;\n /**\n * Initial content. Applied on first render only and doesn't fire `bindinput`.\n * Prefer `value` (or a form control) when the text must stay in sync.\n */\n 'default-value'?: string;\n}\n\n/**\n * Multi-line text input field.\n */\n@Directive({\n selector: 'textarea',\n standalone: true,\n inputs: [\n 'type',\n 'placeholder',\n 'value',\n 'maxlength',\n 'maxlines',\n 'line-spacing',\n 'readonly',\n 'disabled',\n 'confirm-type',\n 'input-filter',\n 'show-soft-input-on-focus',\n 'bounces',\n 'enable-scroll-bar',\n 'ios-auto-correct',\n 'ios-spell-check',\n 'android-fullscreen-mode',\n 'default-value',\n ],\n})\nexport class LynxTextarea extends LynxElementBase {\n // Same reason as LynxInput.#el — ES private field scoping requires a\n // separate injection even though both resolve to the same element instance.\n readonly #el: BaseLynxElement = inject(ElementRef).nativeElement;\n\n override ngOnChanges(changes: SimpleChanges): void {\n if ('value' in changes) {\n // LynxTextarea shares LynxUIBaseInput as its native base class on both\n // Android and iOS, so it has the same limitation: no @LynxProp for\n // \"value\", making __SetAttribute a no-op for live text updates.\n // The setValue UIMethod is required here for the same reason as LynxInput.\n this.#el.invoke?.('setValue', {\n value: changes['value'].currentValue ?? '',\n });\n const { value: _ignored, ...rest } = changes;\n if (Object.keys(rest).length) super.ngOnChanges(rest);\n } else {\n super.ngOnChanges(changes);\n }\n }\n\n type?: 'text' | 'number' | 'digit' | 'tel' | 'email';\n placeholder?: string;\n value?: string;\n maxlength?: number;\n /**\n * Maximum number of visible lines.\n */\n maxlines?: number;\n /**\n * Extra spacing between lines in px.\n */\n 'line-spacing'?: number;\n readonly?: boolean;\n disabled?: boolean;\n 'confirm-type'?: 'search' | 'send' | 'go' | 'done' | 'next';\n 'input-filter'?: string;\n 'show-soft-input-on-focus'?: boolean;\n bounces?: boolean;\n 'enable-scroll-bar'?: boolean;\n 'ios-auto-correct'?: boolean;\n 'ios-spell-check'?: boolean;\n 'android-fullscreen-mode'?: boolean;\n /**\n * Initial content. Applied on first render only and doesn't fire `bindinput`.\n * Prefer `value` (or a form control) when the text must stay in sync.\n */\n 'default-value'?: string;\n}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * High-performance virtualized list, equivalent to RecyclerView / UITableView.\n */\n@Directive({\n selector: 'list',\n standalone: true,\n inputs: [\n 'list-type',\n 'span-count',\n 'scroll-orientation',\n 'enable-scroll',\n 'enable-nested-scroll',\n 'bounces',\n 'sticky',\n 'sticky-offset',\n 'scroll-bar-enable',\n 'initial-scroll-index',\n 'upper-threshold-item-count',\n 'lower-threshold-item-count',\n 'scroll-event-throttle',\n 'need-visible-item-info',\n 'need-layout-complete-info',\n 'preload-buffer-count',\n 'item-snap',\n 'update-animation',\n 'list-main-axis-gap',\n 'list-cross-axis-gap',\n 'enable-async-list',\n 'enable-insert-platform-view-operation',\n 'experimental-search-ref-anchor-strategy',\n 'harmony-scroll-edge-effect',\n ],\n})\nexport class LynxList extends LynxElementBase {\n /**\n * Layout algorithm.\n * - `'single'` — one item per row/column\n * - `'flow'` — fixed column count, items fill left-to-right\n * - `'waterfall'` — Pinterest-style varying-height columns\n */\n 'list-type'?: 'single' | 'flow' | 'waterfall';\n /**\n * Number of columns (flow/waterfall) or rows (horizontal single).\n */\n 'span-count'?: number;\n /**\n * Scroll axis. @default 'vertical'\n */\n 'scroll-orientation'?: 'vertical' | 'horizontal';\n 'enable-scroll'?: boolean;\n 'enable-nested-scroll'?: boolean;\n bounces?: boolean;\n sticky?: boolean;\n /**\n * Offset in px for sticky items.\n */\n 'sticky-offset'?: number;\n 'scroll-bar-enable'?: boolean;\n /**\n * Scroll to this item index on first render.\n */\n 'initial-scroll-index'?: number;\n /**\n * Number of items from the top that triggers bindscrolltoupper.\n */\n 'upper-threshold-item-count'?: number;\n /**\n * Number of items from the bottom that triggers bindscrolltolower.\n */\n 'lower-threshold-item-count'?: number;\n /**\n * Minimum interval in ms between scroll events.\n */\n 'scroll-event-throttle'?: number;\n /**\n * Include visible item info in scroll event payloads.\n */\n 'need-visible-item-info'?: boolean;\n /**\n * Include layout completion info in events.\n */\n 'need-layout-complete-info'?: boolean;\n /**\n * Number of items to preload beyond the visible area.\n */\n 'preload-buffer-count'?: number;\n /**\n * Snap behavior: `{ factor: 0–1, offset: px }`.\n */\n 'item-snap'?: { factor: number; offset: number };\n /**\n * Insert/remove animation style.\n */\n 'update-animation'?: 'default' | 'none';\n /**\n * Gap between items on the main axis (CSS length).\n */\n 'list-main-axis-gap'?: string;\n /**\n * Gap between columns/rows on the cross axis (CSS length).\n */\n 'list-cross-axis-gap'?: string;\n /**\n * Required by Lynx's native list UI whenever the app uses the standard\n * dual-thread engine strategy (always true for AngularLynx) — without it\n * the native list silently never applies its data source, so\n * `componentAtIndex` is never called and no items render. The renderer\n * sets this to `true` by default at element creation; bind it explicitly\n * only to opt back into the sync (all-on-UI) engine strategy.\n * @default true\n */\n 'enable-async-list'?: boolean;\n /**\n * Insert list-item platform views via the C++ list's operations. Recommended\n * with multi-thread engine strategies. @default false\n */\n 'enable-insert-platform-view-operation'?: boolean;\n /**\n * How the list picks a reference anchor when on-screen items are removed:\n * 0 = none, 1 = toward start, 2 = toward end (experimental). @default 0\n */\n 'experimental-search-ref-anchor-strategy'?: 0 | 1 | 2;\n /**\n * Allow scrolling when the content is smaller than the list (Harmony). @default false\n */\n 'harmony-scroll-edge-effect'?: boolean;\n}\n\n/**\n * Child of `<list>`; represents a single virtualized cell.\n */\n@Directive({\n selector: 'list-item',\n standalone: true,\n inputs: [\n 'item-key',\n 'full-span',\n 'sticky-top',\n 'sticky-bottom',\n 'recyclable',\n 'reuse-identifier',\n 'estimated-main-axis-size-px',\n 'defer',\n ],\n})\nexport class LynxListItem extends LynxElementBase {\n /**\n * Stable unique key for this item — used for diffing and recycling.\n * Must be unique within the list.\n */\n 'item-key'?: string;\n /**\n * Whether this item spans all columns (full-width in flow/waterfall).\n */\n 'full-span'?: boolean;\n /**\n * Stick this item to the top of the list while scrolling.\n */\n 'sticky-top'?: boolean;\n /**\n * Stick this item to the bottom of the list while scrolling.\n */\n 'sticky-bottom'?: boolean;\n /**\n * Whether this item's view can be recycled. @default true\n */\n recyclable?: boolean;\n /**\n * Reuse pool identifier — items with the same identifier share views.\n */\n 'reuse-identifier'?: string;\n /**\n * Estimated item size in px for layout pre-calculation.\n */\n 'estimated-main-axis-size-px'?: number;\n /**\n * Deferred rendering. Pass `true` to defer, or an object to control\n * whether the item unmounts when recycled.\n */\n defer?: boolean | { unmountRecycled?: boolean };\n}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Anonymous grouping element with no visual output.\n */\n@Directive({ selector: 'block', standalone: true })\nexport class LynxBlock extends LynxElementBase {}\n\n/**\n * Lynx native conditional element.\n * Note: Angular's `@if` control flow is a separate, unrelated construct.\n */\n@Directive({ selector: 'if', standalone: true })\nexport class LynxIf extends LynxElementBase {}\n\n/**\n * Lynx native iteration element.\n * Note: Angular's `@for` control flow is a separate, unrelated construct.\n */\n@Directive({ selector: 'for', standalone: true })\nexport class LynxFor extends LynxElementBase {}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Floating layer rendered above the main document flow.\n */\n@Directive({\n selector: 'overlay',\n standalone: true,\n inputs: [\n 'visible',\n 'level',\n 'mode',\n 'ios-enable-swipe-back',\n 'android-navigation-bar-style',\n 'android-overlay-scope',\n ],\n})\nexport class LynxOverlay extends LynxElementBase {\n /**\n * Whether the overlay is shown.\n */\n visible?: boolean;\n /**\n * Z-order layer (higher = above other overlays).\n * 1 = default, 2 = status bar level, 3 = keyboard level, 4 = top.\n */\n level?: 1 | 2 | 3 | 4;\n /**\n * Presentation mode on iOS (`'window'` | `'top'` | `'page'`).\n */\n mode?: string;\n /**\n * Whether the iOS swipe-back gesture dismisses the overlay.\n */\n 'ios-enable-swipe-back'?: boolean;\n /**\n * Android navigation bar background/appearance while the overlay is shown.\n * `transparent` also requires `android-adapt-edge-to-edge`. (Lynx 4.1+) @default 'auto'\n */\n 'android-navigation-bar-style'?: 'auto' | 'light' | 'dark' | 'transparent';\n /**\n * Limit the overlay to the Fragment that owns its LynxView (Android, Lynx 4.3+). @default 'global'\n */\n 'android-overlay-scope'?: 'global' | 'fragment';\n}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Pull-to-refresh container. Accepts `<refresh-header>` and a scrollable `<view>` as direct children.\n */\n@Directive({\n selector: 'refresh',\n standalone: true,\n inputs: ['enable-refresh'],\n})\nexport class LynxRefresh extends LynxElementBase {\n /**\n * Whether dragging down or calling autoStartRefresh can trigger the startrefresh event. @default true\n */\n 'enable-refresh'?: boolean;\n}\n\n/**\n * Customizable header revealed during a pull-to-refresh gesture. Must be a direct child of `<refresh>`.\n */\n@Directive({\n selector: 'refresh-header',\n standalone: true,\n})\nexport class LynxRefreshHeader extends LynxElementBase {}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Nested scroll coordination container. Synchronizes a foldable header, sticky toolbar, and scrollable content slot.\n */\n@Directive({\n selector: 'scroll-coordinator',\n standalone: true,\n inputs: [\n 'enable-scroll',\n 'bounces',\n 'granularity',\n 'header-over-slot',\n 'refresh-mode',\n 'enable-scroll-bar',\n 'android-nested-scroll-as-child',\n 'ios-force-scroll-detach',\n 'ios-scrolls-to-top',\n 'android-adapt-to-empty-slot',\n ],\n})\nexport class LynxScrollCoordinator extends LynxElementBase {\n /**\n * Whether the coordinator can scroll vertically. @default true\n */\n 'enable-scroll'?: boolean;\n /**\n * Enable bounce effect when scrolling past boundary (iOS/Harmony). @default true\n */\n bounces?: boolean;\n /**\n * Event response granularity for bindoffset. @default 0.01\n */\n granularity?: number;\n /**\n * Whether header appears over slot when overflowing. @default false\n */\n 'header-over-slot'?: boolean;\n /**\n * Refresh mode: 'none', 'page', or 'fold' (iOS). @default 'none'\n */\n 'refresh-mode'?: 'none' | 'page' | 'fold';\n /**\n * Show scrollbar during scrolling (iOS/Harmony). @default false\n */\n 'enable-scroll-bar'?: boolean;\n /**\n * Enable nested scroll as child in other scrolling widgets (Android). @default false\n */\n 'android-nested-scroll-as-child'?: boolean;\n /**\n * Force nested-vertical-scroll-behavior invalid (iOS). @default false\n */\n 'ios-force-scroll-detach'?: boolean;\n /**\n * Scroll to top when tapping status bar (iOS). @default false\n */\n 'ios-scrolls-to-top'?: boolean;\n /**\n * Adjust the offset when the active slot is empty or too short to scroll (Android). @default false\n */\n 'android-adapt-to-empty-slot'?: boolean;\n}\n\n/**\n * Header content that scrolls out of view. Must be a direct child of `<scroll-coordinator>`.\n */\n@Directive({\n selector: 'scroll-coordinator-header',\n standalone: true,\n})\nexport class LynxScrollCoordinatorHeader extends LynxElementBase {}\n\n/**\n * Sticky toolbar that remains visible at the top. Must be a direct child of `<scroll-coordinator>`.\n */\n@Directive({\n selector: 'scroll-coordinator-toolbar',\n standalone: true,\n})\nexport class LynxScrollCoordinatorToolbar extends LynxElementBase {}\n\n/**\n * Container for scrollable content (typically a `<list>`). Must be a direct child of `<scroll-coordinator>`.\n */\n@Directive({\n selector: 'scroll-coordinator-slot',\n standalone: true,\n})\nexport class LynxScrollCoordinatorSlot extends LynxElementBase {}\n\n/**\n * Slot variant whose content can be dragged up/down to fold and unfold the\n * header. Must be a direct child of `<scroll-coordinator>`.\n */\n@Directive({\n selector: 'scroll-coordinator-slot-drag',\n standalone: true,\n inputs: ['enable-drag'],\n})\nexport class LynxScrollCoordinatorSlotDrag extends LynxElementBase {\n /**\n * Whether vertical drag gestures fold/unfold the header. @default true\n */\n 'enable-drag'?: boolean;\n}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Scrollable single-child container.\n */\n@Directive({\n selector: 'scroll-view',\n standalone: true,\n inputs: [\n 'scroll-orientation',\n 'enable-scroll',\n 'bounces',\n 'scroll-bar-enable',\n 'upper-threshold',\n 'lower-threshold',\n 'initial-scroll-offset',\n 'initial-scroll-to-index',\n 'enable-nested-scroll',\n 'experimental-android-enable-new-overflow',\n ],\n})\nexport class LynxScrollView extends LynxElementBase {\n /**\n * Scroll axis. @default 'vertical'\n */\n 'scroll-orientation'?: 'vertical' | 'horizontal';\n /**\n * Whether scrolling is enabled. @default true\n */\n 'enable-scroll'?: boolean;\n /**\n * Whether the scroll view bounces past the content edge (iOS/Harmony).\n */\n bounces?: boolean;\n /**\n * Whether the platform scroll indicator is shown.\n */\n 'scroll-bar-enable'?: boolean;\n /**\n * Distance from the top/left edge that triggers bindscrolltoupper.\n */\n 'upper-threshold'?: number;\n /**\n * Distance from the bottom/right edge that triggers bindscrolltolower.\n */\n 'lower-threshold'?: number;\n /**\n * Initial scroll offset in px.\n */\n 'initial-scroll-offset'?: number;\n /**\n * Scroll to item at this index on mount.\n */\n 'initial-scroll-to-index'?: number;\n /**\n * Whether nested scrolling is enabled.\n */\n 'enable-nested-scroll'?: boolean;\n /**\n * Use the new overflow clipping implementation (Android, Lynx 4.2+, experimental). @default true\n */\n 'experimental-android-enable-new-overflow'?: boolean;\n}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Renders SVG content from a URL or an inline XML string.\n */\n@Directive({\n selector: 'svg',\n standalone: true,\n inputs: ['src', 'content', 'current-color'],\n})\nexport class LynxSvg extends LynxElementBase {\n /**\n * URL pointing to an SVG resource.\n */\n src?: string;\n /**\n * Inline SVG XML string.\n */\n content?: string;\n /**\n * Color used for `currentColor` in the SVG. Doesn't override explicit `fill`/`stroke`.\n */\n 'current-color'?: string;\n}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Displays text content. Supports inline child `<text>` elements for mixed styling.\n */\n@Directive({\n selector: 'text',\n standalone: true,\n inputs: [\n 'text-maxline',\n 'text-single-line-vertical-align',\n 'text-selection',\n 'custom-context-menu',\n 'include-font-padding',\n 'tail-color-convert',\n 'text-fake-bold',\n 'custom-text-selection',\n 'android-emoji-compat',\n ],\n})\nexport class LynxText extends LynxElementBase {\n /**\n * Maximum number of lines before truncation with ellipsis.\n */\n 'text-maxline'?: number;\n /**\n * Vertical alignment for single-line text.\n * @default 'normal'\n */\n 'text-single-line-vertical-align'?: 'normal' | 'top' | 'center' | 'bottom';\n /**\n * Whether the user can select the text.\n */\n 'text-selection'?: boolean;\n /**\n * Whether a custom context menu is shown on long-press.\n */\n 'custom-context-menu'?: boolean;\n /**\n * Add extra font padding on Android.\n */\n 'include-font-padding'?: boolean;\n 'tail-color-convert'?: boolean;\n /**\n * Synthesize bold when the font has no bold face (Android/iOS). @default false\n */\n 'text-fake-bold'?: boolean;\n /**\n * Hand selection/copy gestures to your own handlers; requires `text-selection`. @default false\n */\n 'custom-text-selection'?: boolean;\n /**\n * Render emoji with the Emoji2 compatibility library (Android; the app must include it). @default false\n */\n 'android-emoji-compat'?: boolean;\n}\n\n/**\n * Custom content shown at the end of a `<text>` in place of the ellipsis when\n * the text is truncated by `text-maxline`. Must be a direct child of `<text>`.\n */\n@Directive({ selector: 'inline-truncation', standalone: true })\nexport class LynxInlineTruncation extends LynxElementBase {}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Draggable region of a custom window title bar, like CSS `app-region: drag`\n * (Clay Windows/macOS only).\n */\n@Directive({\n selector: 'title-bar-view',\n standalone: true,\n inputs: ['moveable'],\n})\nexport class LynxTitleBarView extends LynxElementBase {\n /**\n * Whether dragging this region moves the window. @default false\n */\n moveable?: boolean;\n}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Native video player (experimental, Lynx 4.1+). Control playback with the\n * `play` / `pause` / `stop` / `seek` UI methods via SelectorQuery.\n */\n@Directive({\n selector: 'video',\n standalone: true,\n inputs: [\n 'src',\n 'loop',\n 'volume',\n 'muted',\n 'speed',\n 'object-fit',\n 'mode',\n 'timeupdate-interval',\n ],\n})\nexport class LynxVideo extends LynxElementBase {\n /**\n * Video URL. Only online network URLs are supported.\n */\n src?: string;\n /**\n * Whether playback loops. @default false\n */\n loop?: boolean;\n /**\n * Playback volume from 0 to 1. @default 1\n */\n volume?: number;\n /**\n * Whether audio is muted. @default false\n */\n muted?: boolean;\n /**\n * Playback rate from 0.1 to 2.0. @default 1\n */\n speed?: number;\n /**\n * How the video is scaled into the element box. @default 'contain'\n */\n 'object-fit'?: 'contain' | 'cover' | 'fill';\n /**\n * How queued UI method calls are executed. @default 'queue'\n */\n mode?: 'queue' | 'direct' | 'latest';\n /**\n * Minimum interval between `bindtimeupdate` events, in seconds. @default 0.33\n */\n 'timeupdate-interval'?: number;\n}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * General-purpose container element, equivalent to HTML `<div>`.\n */\n@Directive({\n selector: 'view',\n standalone: true,\n inputs: [\n 'flatten',\n 'pan-intercept-direction',\n 'pan-intercept-scope',\n 'consume-slide-event',\n 'enable-touch-pseudo-propagation',\n ],\n})\nexport class LynxView extends LynxElementBase {\n /**\n * Flatten the view into its parent's layer (Android only).\n * Improves performance for non-interactive views.\n */\n flatten?: boolean;\n /**\n * Direction of pan-gesture interception.\n * 0 = horizontal, 1 = vertical, 2 = none.\n */\n 'pan-intercept-direction'?: 0 | 1 | 2;\n 'pan-intercept-scope'?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n 'consume-slide-event'?: [number, number][];\n 'enable-touch-pseudo-propagation'?: boolean;\n}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Horizontally swipeable paging container.\n */\n@Directive({\n selector: 'viewpager',\n standalone: true,\n inputs: [\n 'initial-select-index',\n 'enable-scroll',\n 'bounces',\n 'android-always-overscroll',\n 'android-force-can-scroll',\n 'ios-gesture-direction',\n 'ios-gesture-offset',\n 'ios-recognized-gesture-class',\n 'ios-recognized-view-tag',\n 'keep-item-view',\n ],\n})\nexport class LynxViewPager extends LynxElementBase {\n /**\n * Page index to display on first render. @default 0\n */\n 'initial-select-index'?: number;\n /**\n * Whether horizontal scroll gesture is enabled. @default true\n */\n 'enable-scroll'?: boolean;\n /**\n * Whether the pager bounces past edge (iOS/Harmony/Clay). @default true\n */\n bounces?: boolean;\n /**\n * Enable bounce effect at edges on Android. @default false\n */\n 'android-always-overscroll'?: boolean;\n /**\n * Block gesture pass-through to parent on Android. @default false\n */\n 'android-force-can-scroll'?: boolean;\n /**\n * Allow outer container swipe at edges (iOS). @default false\n */\n 'ios-gesture-direction'?: boolean;\n /**\n * Left edge exclusion zone for swipe gesture (iOS, px). @default 0\n */\n 'ios-gesture-offset'?: number;\n /**\n * UIGestureRecognizer class name for simultaneous recognition (iOS).\n */\n 'ios-recognized-gesture-class'?: string;\n /**\n * UIView tag for simultaneous gesture recognition (iOS). @default 0\n */\n 'ios-recognized-view-tag'?: number;\n /**\n * Enable lazy load mode with early exposure. @default false\n */\n 'keep-item-view'?: boolean;\n}\n\n/**\n * Single page container inside a viewpager.\n */\n@Directive({\n selector: 'viewpager-item',\n standalone: true,\n})\nexport class LynxViewPagerItem extends LynxElementBase {}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Native web view that loads a URL or an inline HTML string. Use `<frame>`\n * instead to embed another Lynx bundle.\n */\n@Directive({\n selector: 'webview',\n standalone: true,\n inputs: [\n 'src',\n 'html',\n 'bounces',\n 'scroll-bar-enable',\n 'params',\n 'webview-type',\n 'enable-debug',\n 'initjs',\n 'cookies',\n 'use-osr',\n ],\n})\nexport class LynxWebView extends LynxElementBase {\n /**\n * URL to load. Changing it reloads the page.\n */\n src?: string;\n /**\n * Inline HTML to load. Ignored when `src` is set.\n */\n html?: string;\n /**\n * Enable the bounce effect (iOS). @default false\n */\n bounces?: boolean;\n /**\n * Show the scroll bar (iOS). @default false\n */\n 'scroll-bar-enable'?: boolean;\n /**\n * Params forwarded to a custom web view implementation (Android/iOS).\n */\n params?: Record<string, unknown>;\n /**\n * Which web view implementation (injected via LynxService) to use. @default 'default'\n */\n 'webview-type'?: string;\n /**\n * Allow remote debugging (Chrome DevTools / Safari Web Inspector). @default false\n */\n 'enable-debug'?: boolean;\n /**\n * JavaScript executed when the document is ready (Clay desktop).\n */\n initjs?: string;\n /**\n * Cookies preset before loading (Clay).\n */\n cookies?: {\n name: string;\n value: string;\n domain?: string;\n path?: string;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite: string;\n }[];\n /**\n * Render off-screen (Clay). @default false\n */\n 'use-osr'?: boolean;\n}\n","/**\n * Angular directive stubs for every Lynx native element.\n *\n * Import LYNX_ELEMENTS into any component that uses Lynx elements in its template\n * for IDE autocomplete and zero red squiggles:\n *\n * @Component({\n * imports: [LYNX_ELEMENTS],\n * template: `<view><text>Hello</text></view>`,\n * })\n * export class My {}\n *\n * The rsbuild plugin automatically injects CUSTOM_ELEMENTS_SCHEMA at build time\n * so the build always succeeds even without importing LYNX_ELEMENTS. These stubs\n * are purely for IDE ergonomics.\n *\n * Implementation notes:\n * - These are @Directive, NOT @Component. Using @Component causes Angular to treat\n * the element's children as projected content. Any directive inside projected\n * content that injects ViewContainerRef (e.g. RouterOutlet) crashes at runtime\n * because insertAnchorNode calls renderer.insertBefore(null, anchor) — the parent\n * is not yet resolved while Angular is collecting projected nodes. @Directive has\n * no template, so children are direct element children as expected — identical\n * rendering behavior to not importing LYNX_ELEMENTS at all.\n * - Properties use their Lynx attribute name (kebab-case) so IDE hover shows the\n * exact attribute to use in templates (e.g. 'scroll-orientation').\n * - Properties are declared as inputs (via @Directive({ inputs: [...] })) so\n * Angular's template checker accepts property bindings like [src]=\"url\".\n * Angular intercepts these bindings and sets them on the directive instance.\n * LynxElementBase.ngOnChanges forwards every input change to the native Lynx\n * element via BaseLynxElement.setAttribute() → __SetAttribute().\n * - Events (bindtap, catchtap, bindinput, bindscroll, …) are NOT declared as\n * @Output() because Angular would intercept them and skip the renderer's\n * listen() call, breaking native Lynx event delivery. They continue to work\n * via renderer.listen() which handles all unrecognized event names.\n */\nexport { LynxElementBase } from './base';\nexport { LynxBlurView } from './blur-view';\nexport { LynxCoverView } from './cover-view';\nexport {\n LYNX_FORM_ACCESSORS,\n LynxInputValueAccessor,\n LynxTextareaValueAccessor,\n} from '../forms';\nexport { LynxFrame } from './frame';\nexport { LynxImage } from './image';\nexport { LynxInput, LynxTextarea } from './input';\nexport { LynxList, LynxListItem } from './list';\nexport { LynxBlock, LynxFor, LynxIf } from './misc';\nexport { LynxOverlay } from './overlay';\nexport { LynxRefresh, LynxRefreshHeader } from './refresh';\nexport {\n LynxScrollCoordinator,\n LynxScrollCoordinatorHeader,\n LynxScrollCoordinatorSlot,\n LynxScrollCoordinatorSlotDrag,\n LynxScrollCoordinatorToolbar,\n} from './scroll-coordinator';\nexport { LynxScrollView } from './scroll-view';\nexport { LynxSvg } from './svg';\nexport { LynxInlineTruncation, LynxText } from './text';\nexport { LynxTitleBarView } from './title-bar-view';\nexport { LynxVideo } from './video';\nexport { LynxView } from './view';\nexport { LynxViewPager, LynxViewPagerItem } from './viewpager';\nexport { LynxWebView } from './webview';\n\nimport { LYNX_FORM_ACCESSORS } from '../forms';\nimport { LynxBlurView } from './blur-view';\nimport { LynxCoverView } from './cover-view';\nimport { LynxFrame } from './frame';\nimport { LynxImage } from './image';\nimport { LynxInput, LynxTextarea } from './input';\nimport { LynxList, LynxListItem } from './list';\nimport { LynxBlock, LynxFor, LynxIf } from './misc';\nimport { LynxOverlay } from './overlay';\nimport { LynxRefresh, LynxRefreshHeader } from './refresh';\nimport {\n LynxScrollCoordinator,\n LynxScrollCoordinatorHeader,\n LynxScrollCoordinatorSlot,\n LynxScrollCoordinatorSlotDrag,\n LynxScrollCoordinatorToolbar,\n} from './scroll-coordinator';\nimport { LynxScrollView } from './scroll-view';\nimport { LynxSvg } from './svg';\nimport { LynxInlineTruncation, LynxText } from './text';\nimport { LynxTitleBarView } from './title-bar-view';\nimport { LynxVideo } from './video';\nimport { LynxView } from './view';\nimport { LynxViewPager, LynxViewPagerItem } from './viewpager';\nimport { LynxWebView } from './webview';\n\n/**\n * All Lynx native element directives as a single importable array.\n * Add to the `imports` of any component whose template uses Lynx elements.\n */\nexport const LYNX_ELEMENTS = [\n LynxView,\n LynxText,\n LynxInlineTruncation,\n LynxImage,\n LynxScrollView,\n LynxList,\n LynxListItem,\n LynxBlock,\n LynxIf,\n LynxFor,\n LynxFrame,\n LynxInput,\n LynxTextarea,\n // CVA directives — activate on top of LynxInput/LynxTextarea when form attributes\n // (formControl, formControlName, ngModel, formField) are present on the element.\n ...LYNX_FORM_ACCESSORS,\n LynxOverlay,\n LynxRefresh,\n LynxRefreshHeader,\n LynxScrollCoordinator,\n LynxScrollCoordinatorHeader,\n LynxScrollCoordinatorSlot,\n LynxScrollCoordinatorSlotDrag,\n LynxScrollCoordinatorToolbar,\n LynxSvg,\n LynxViewPager,\n LynxViewPagerItem,\n LynxBlurView,\n LynxVideo,\n LynxWebView,\n LynxCoverView,\n LynxTitleBarView,\n] as const;\n","/**\n * Remote logger service — sends log calls from on-device to the rspeedy dev\n * server via fetch() so they appear in the developer's terminal.\n * All methods are no-ops in production (__DEV__ guard dead-code-eliminated).\n *\n * Threading: Lynx dual-thread model means event handlers run on the main thread\n * (no fetch), while the Angular app runs on the background thread (has fetch).\n * Logs from the main thread are relayed to the background thread via IPC:\n * main thread: lynx.getJSContext().dispatchEvent(...)\n * background thread: lynx.getCoreContext().addEventListener(...)\n * This mirrors how React Lynx's runOnBackground() IPC works.\n */\nimport { Injectable } from '@angular/core';\n\ntype LogLevel = 'log' | 'warn' | 'error' | 'info' | 'debug';\n\ntype LogEntry = {\n level: LogLevel;\n timestamp: number;\n args: string[];\n};\n\n@Injectable({ providedIn: 'root' })\nexport class LynxLogger {\n readonly #url: string = '';\n /**\n * Only set on background thread where fetch is available via tt.define() scope.\n */\n #fetchFn:\n | ((url: string, init?: RequestInit) => Promise<Response>)\n | undefined;\n\n constructor() {\n if (!__DEV__) return;\n\n this.#url = typeof __DEV_LOG_URL__ !== 'undefined' ? __DEV_LOG_URL__ : '';\n if (!this.#url) return;\n\n // Resolve fetch — injected by Lynx's tt.define() into module scope,\n // only available on the background thread.\n try {\n if (typeof fetch === 'function') {\n this.#fetchFn = fetch;\n // In Vitest (jsdom) `fetch` is always a function on the module scope,\n // so the else-if that falls back to `globalThis.fetch` is never\n // reachable. The fallback exists for Lynx's background thread where\n // `fetch` is injected via `tt.define()` instead.\n /* v8 ignore start */\n } else if (typeof (globalThis as any).fetch === 'function') {\n this.#fetchFn = (globalThis as any).fetch;\n }\n /* v8 ignore stop */\n } catch {}\n\n if (!this.#fetchFn) return;\n\n // Background thread only: register IPC listener for log events relayed\n // from the main thread (event handlers, etc.) which cannot use fetch.\n try {\n if (\n typeof lynx !== 'undefined' &&\n typeof lynx.getCoreContext === 'function'\n ) {\n lynx.getCoreContext().addEventListener('__lynx_log__', (event: any) => {\n try {\n this.#postToServer(JSON.parse(event.data as string));\n } catch {}\n });\n }\n } catch {}\n }\n\n log(...args: unknown[]): void {\n this.#send('log', args);\n }\n warn(...args: unknown[]): void {\n this.#send('warn', args);\n }\n error(...args: unknown[]): void {\n this.#send('error', args);\n }\n info(...args: unknown[]): void {\n this.#send('info', args);\n }\n debug(...args: unknown[]): void {\n this.#send('debug', args);\n }\n\n #send(level: LogLevel, args: unknown[]): void {\n if (!this.#url) return;\n const entry: LogEntry = {\n level,\n timestamp: Date.now(),\n args: args.map(String),\n };\n\n if (this.#fetchFn) {\n // Background thread: send directly via fetch.\n this.#postToServer(entry);\n } else {\n // Main thread: no fetch available. Relay to background thread via IPC.\n // Background thread's addEventListener('__lynx_log__') will handle it.\n try {\n if (\n typeof lynx !== 'undefined' &&\n typeof (lynx as any).getJSContext === 'function'\n ) {\n (lynx as any).getJSContext().dispatchEvent({\n type: '__lynx_log__',\n data: JSON.stringify(entry),\n });\n }\n } catch {}\n }\n }\n\n #postToServer(entry: LogEntry): void {\n try {\n this.#fetchFn!(this.#url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ logs: [entry] }),\n }).catch(() => {});\n } catch {}\n }\n}\n","import { Injectable } from '@angular/core';\nimport type { NativeModuleMap } from './native-module.types';\n\n/**\n * Wraps the Lynx native module bridge and JS module registry as an Angular injectable.\n *\n * **Native modules** (`NativeModules` global) let JS code call native platform\n * functions (iOS / Android / HarmonyOS). The host app registers modules on the\n * native side; this service provides typed access from Angular.\n *\n * **JS modules** (`lynx.getJSModule` / `lynx.registerModule`) share JavaScript\n * values within a single LynxView. This is the same API used internally by\n * `LynxInitData` and `LynxGlobalData` (via `GlobalEventEmitter`).\n *\n * @usageNotes\n * ```typescript\n * const modules = inject(LynxNativeModule);\n *\n * // Call a native method (Promise-based wrapper over bridge.call)\n * const result = await modules.call<string>('getDeviceId', {});\n *\n * // Listen for native events\n * modules.on('onDeepLink', (url) => console.log(url));\n *\n * // Access a typed custom native module\n * const storage = modules.getNativeModule('NativeLocalStorageModule');\n * storage?.setStorageItem('key', 'value');\n *\n * // JS module sharing within the LynxView\n * modules.registerJSModule('mySharedState', { count: 0 });\n * const state = modules.getJSModule<{ count: number }>('mySharedState');\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxNativeModule {\n #hasNativeModules(): boolean {\n return (\n typeof NativeModules !== 'undefined' &&\n NativeModules != null &&\n typeof NativeModules.bridge?.call === 'function'\n );\n }\n\n #hasLynx(): boolean {\n return (\n typeof lynx !== 'undefined' && typeof lynx.getJSModule === 'function'\n );\n }\n\n /**\n * Calls a native method via `NativeModules.bridge.call()`.\n *\n * The native callback API is wrapped in a Promise for ergonomic\n * use with `async`/`await`.\n *\n * Returns `undefined` when `NativeModules` is unavailable (web preview, tests).\n */\n call<T = unknown>(\n name: string,\n params: Record<string, unknown> = {},\n ): Promise<T | undefined> {\n if (!this.#hasNativeModules()) {\n return Promise.resolve(undefined);\n }\n\n return new Promise<T>((resolve) => {\n NativeModules.bridge.call(name, params, (...args: unknown[]) => {\n resolve(args[0] as T);\n });\n });\n }\n\n /**\n * Subscribes to a native event via `NativeModules.bridge.on()`.\n *\n * No-op when `NativeModules` is unavailable.\n */\n on(name: string, callback: (...args: unknown[]) => void): void {\n if (!this.#hasNativeModules()) {\n return;\n }\n\n NativeModules.bridge.on(name, callback);\n }\n\n /**\n * Retrieves a custom native module by name from the `NativeModules` global.\n *\n * Augment the {@link NativeModuleMap} interface for type-safe access:\n *\n * ```typescript\n * declare module '@blotch/angular-lynx' {\n * interface NativeModuleMap {\n * NativeLocalStorageModule: { ... };\n * }\n * }\n *\n * const storage = modules.getNativeModule('NativeLocalStorageModule');\n * ```\n *\n * Returns `undefined` when `NativeModules` is unavailable or the module\n * is not registered.\n */\n getNativeModule<K extends string>(\n name: K,\n ): K extends keyof NativeModuleMap ? NativeModuleMap[K] : unknown {\n if (typeof NativeModules === 'undefined' || NativeModules == null) {\n return undefined as any;\n }\n\n return (NativeModules as any)[name];\n }\n\n /**\n * Retrieves a JS module registered within this LynxView.\n *\n * This wraps `lynx.getJSModule()` — the same API used internally\n * for `GlobalEventEmitter`.\n *\n * Returns `undefined` when `lynx` is unavailable or the module\n * is not registered.\n */\n getJSModule<T = unknown>(name: string): T | undefined {\n if (!this.#hasLynx()) {\n return undefined;\n }\n\n return lynx.getJSModule<T>(name);\n }\n\n /**\n * Registers a JS module for sharing within this LynxView.\n *\n * Other code (including native callbacks) can retrieve it via\n * `getJSModule()` or `lynx.getJSModule()`.\n *\n * No-op when `lynx` is unavailable.\n */\n registerJSModule<T extends object>(name: string, module: T): void {\n if (!this.#hasLynx()) {\n return;\n }\n\n lynx.registerModule(name, module);\n }\n}\n","import { InjectionToken } from '@angular/core';\nimport type { LynxDocumentBase } from '../lynx-document';\n\n/**\n * Separate token file breaks the circular import that would result from placing\n * LYNX_DOCUMENT in providers.ts (which imports lynx-document.ts, which would\n * then import providers.ts to read the token).\n */\nexport const LYNX_DOCUMENT = new InjectionToken<LynxDocumentBase>(\n 'lynx-document',\n);\n","import {\n ApplicationRef,\n type ComponentRef,\n type EmbeddedViewRef,\n EnvironmentInjector,\n Injectable,\n type TemplateRef,\n type Type,\n createComponent,\n inject,\n} from '@angular/core';\nimport type { BaseLynxElement } from '../lynx-element';\nimport { LYNX_DOCUMENT } from '../renderer/token';\n\n/**\n * Configuration for creating a portal overlay.\n */\nexport type PortalConfig = {\n /**\n * Overlay z-level (1–4). Higher levels render above lower ones.\n */\n level?: number;\n /**\n * Custom injector for the component's dependency injection context.\n */\n injector?: EnvironmentInjector;\n /**\n * Initial input values to set on the component after creation.\n */\n inputs?: Record<string, unknown>;\n};\n\n/**\n * Handle for managing a portal instance created by {@link LynxPortal}.\n *\n * Call {@link destroy} to tear down the overlay and its content.\n */\nexport class PortalRef<T> {\n readonly #overlay: BaseLynxElement;\n readonly #appRef: ApplicationRef;\n readonly #componentRef: ComponentRef<T> | null;\n readonly #viewRef: EmbeddedViewRef<unknown> | null;\n\n /**\n * @internal\n */\n constructor(\n overlay: BaseLynxElement,\n appRef: ApplicationRef,\n componentRef: ComponentRef<T> | null,\n viewRef: EmbeddedViewRef<unknown> | null,\n ) {\n this.#overlay = overlay;\n this.#appRef = appRef;\n this.#componentRef = componentRef;\n this.#viewRef = viewRef;\n }\n\n /**\n * The component instance. `null` for template portals.\n */\n get instance(): T | null {\n return this.#componentRef?.instance ?? null;\n }\n\n /**\n * Sets a component input. Only works for component portals.\n */\n setInput(name: string, value: unknown): void {\n this.#componentRef?.setInput(name, value);\n }\n\n /**\n * Tears down the portal: destroys the component/template view,\n * detaches from change detection, and removes the native overlay element.\n */\n destroy(): void {\n if (this.#componentRef) {\n this.#appRef.detachView(this.#componentRef.hostView);\n this.#componentRef.destroy();\n }\n if (this.#viewRef) {\n this.#appRef.detachView(this.#viewRef);\n this.#viewRef.destroy();\n }\n this.#overlay.remove();\n }\n}\n\n/**\n * Programmatically renders Angular components or templates inside a native\n * Lynx `<overlay>` element — the equivalent of Angular CDK's\n * `Overlay` / `DomPortalOutlet`.\n *\n * For **declarative** overlays, use `<overlay>` directly in your template.\n * This service is for **imperative** cases: modal dialogs, toast notifications,\n * or any content that needs to be created from code rather than a template.\n *\n * @usageNotes\n * ```typescript\n * const portal = inject(LynxPortal);\n *\n * // Open a component in an overlay\n * const ref = portal.open(ConfirmDialogComponent, {\n * level: 2,\n * inputs: { title: 'Delete item?' },\n * });\n *\n * // Update inputs later\n * ref.setInput('title', 'Are you sure?');\n *\n * // Tear down when done\n * ref.destroy();\n *\n * // Open a template in an overlay\n * const tplRef = portal.openTemplate(myTemplateRef, { level: 1 });\n * tplRef.destroy();\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxPortal {\n readonly #doc = inject(LYNX_DOCUMENT);\n readonly #appRef = inject(ApplicationRef);\n readonly #envInjector = inject(EnvironmentInjector);\n\n /**\n * Creates a native `<overlay>` and renders the given component into it.\n *\n * The component participates in Angular change detection and is fully\n * functional (inputs, outputs, dependency injection, lifecycle hooks).\n */\n open<T>(component: Type<T>, config?: PortalConfig): PortalRef<T> {\n const overlay = this.#createOverlay(config);\n\n const componentRef = createComponent(component, {\n environmentInjector: config?.injector ?? this.#envInjector,\n });\n\n // `config.inputs` is only reachable when a caller passes inputs — the\n // testing path constructs the component fresh in each spec, so leave the\n // loop body ignored: propagating signal inputs requires a change-detection\n // flush that the mocked LYNX_DOCUMENT doesn't drive.\n /* v8 ignore next 5 */\n if (config?.inputs) {\n for (const [key, value] of Object.entries(config.inputs)) {\n componentRef.setInput(key, value);\n }\n }\n\n this.#appRef.attachView(componentRef.hostView);\n overlay.appendChild(componentRef.location.nativeElement);\n\n // createRootElement() returns the existing singleton page element, NOT a new\n // one. The overlay must be a direct child of the page so native Lynx renders\n // it as a top-level overlay above all other content.\n const page = this.#doc.createRootElement();\n page.appendChild(overlay);\n\n return new PortalRef(overlay, this.#appRef, componentRef, null);\n }\n\n /**\n * * Creates a native `<overlay>` and renders the given template into it.\n * *\n * * Use this when you have a `TemplateRef` (from `@ViewChild` or a\n * * template variable) rather than a component class.\n * v8 ignore start -- reaching this path requires a real Angular component render that produces a live TemplateRef; the mocked LYNX_DOCUMENT in the spec doesn't drive one, and viewChild.required doesn't resolve without an appRef flush. Coverage is provided by the on-device examples that use openTemplate.\n */\n openTemplate<C>(\n template: TemplateRef<C>,\n config?: PortalConfig & { context?: C },\n ): PortalRef<null> {\n const overlay = this.#createOverlay(config);\n\n const viewRef = template.createEmbeddedView(\n config?.context ?? ({} as C),\n config?.injector ?? this.#envInjector,\n );\n\n this.#appRef.attachView(viewRef);\n\n for (const node of viewRef.rootNodes) {\n overlay.appendChild(node);\n }\n\n // Same singleton page pattern as open() — overlay goes under the root page.\n const page = this.#doc.createRootElement();\n page.appendChild(overlay);\n\n return new PortalRef(overlay, this.#appRef, null, viewRef);\n }\n /**\n * v8 ignore stop\n */\n\n #createOverlay(config?: PortalConfig): BaseLynxElement {\n const overlay = this.#doc.createElement('overlay');\n overlay.setAttribute('visible', true);\n if (config?.level != null) {\n overlay.setAttribute('level', config.level);\n }\n return overlay;\n }\n}\n","/**\n * Both thread bundles evaluate the same module graph in the same order,\n * so this counter produces matching IDs without a compiler plugin.\n */\nlet nextWorkletId = 0;\n\n/**\n * Type definition for main-thread function handles used by {@link mainThreadFn}.\n */\nexport type MainThreadFnHandle<\n TArgs extends unknown[] = unknown[],\n TReturn = unknown,\n> = {\n readonly _wkltId: string;\n readonly _workletType: 'main-thread';\n readonly __isMainThreadFn: true;\n // Phantom types for call-site type checking — not used at runtime\n readonly __args?: TArgs;\n readonly __return?: TReturn;\n};\n\nexport const mainThreadFn = <TArgs extends unknown[], TReturn>(\n fn: (...args: TArgs) => TReturn,\n): MainThreadFnHandle<TArgs, TReturn> => {\n const id = '__angular_mts_' + nextWorkletId++;\n\n if (__MAIN_THREAD__) {\n globalThis.registerWorklet('main-thread', id, fn);\n }\n\n return {\n _wkltId: id,\n _workletType: 'main-thread',\n __isMainThreadFn: true,\n } as MainThreadFnHandle<TArgs, TReturn>;\n};\n\n/**\n * Reset counter on HMR — called from runtime.ts before modules re-evaluate.\n */\nexport const __resetWorkletCounter = (): void => {\n nextWorkletId = 0;\n};\n","/**\n * Counter stays in sync across threads because the build plugin produces\n * two bundles (main + background) from the same source. Both evaluate the\n * same module graph in the same order, so the N-th backgroundFn() call\n * produces ID '__angular_bg_N' on both threads. The main thread can then\n * dispatch a call to a background function by its _wkltId string, and the\n * background thread resolves it to the correct registered function.\n */\nlet nextBgWorkletId = 0;\n\n/**\n * Type definition for background function handles used by {@link backgroundFn}.\n */\nexport type BackgroundFnHandle<\n TArgs extends unknown[] = unknown[],\n TReturn = unknown,\n> = {\n readonly _wkltId: string;\n readonly _workletType: 'background';\n readonly __isBackgroundFn: true;\n readonly __args?: TArgs;\n readonly __return?: TReturn;\n};\n\nexport const backgroundFn = <TArgs extends unknown[], TReturn>(\n fn: (...args: TArgs) => TReturn,\n): BackgroundFnHandle<TArgs, TReturn> => {\n const id = '__angular_bg_' + nextBgWorkletId++;\n\n if (!__MAIN_THREAD__) {\n globalThis.registerWorklet('background', id, fn);\n }\n\n return {\n _wkltId: id,\n _workletType: 'background',\n __isBackgroundFn: true,\n } as BackgroundFnHandle<TArgs, TReturn>;\n};\n\n/**\n * Reset counter on HMR.\n */\nexport const __resetBgWorkletCounter = (): void => {\n nextBgWorkletId = 0;\n};\n","/**\n * Cross-thread shared reference. The background thread holds the JS object;\n * the main thread accesses it by _wvid lookup in __workletRefMap.\n * When a MainThreadRef is passed as a param to runOnMainThread(), JSON.stringify\n * serializes it via toJSON() → { _wvid: N }. On the main thread, runtime.ts's\n * transformParams() reconstitutes the reference from __workletRefMap[_wvid].\n * Counter stays in sync across threads because both bundles evaluate the\n * same module graph in the same order (same mechanism as mainThreadFn/backgroundFn).\n */\nlet nextRefId = 0;\n\nexport class MainThreadRef<T> {\n readonly _wvid: number;\n #_value: T;\n\n constructor(initValue: T) {\n this._wvid = nextRefId++;\n this.#_value = initValue;\n\n // Only register on the main thread — that's where lookups happen.\n // Background thread keeps its own instance but never registers it;\n // it uses the ref directly via .current.\n if (__MAIN_THREAD__) {\n (globalThis as any).__workletRefMap[this._wvid] = this;\n }\n }\n\n get current(): T {\n return this.#_value;\n }\n\n set current(value: T) {\n this.#_value = value;\n }\n\n /**\n * Serialization hook for cross-thread transfer. JSON.stringify calls this\n * when the ref is passed as a param to dispatchEvent (MTS/background RPC).\n * The receiving thread's transformParams() resolves { _wvid } back to the\n * registered MainThreadRef instance.\n */\n toJSON(): { _wvid: number } {\n return { _wvid: this._wvid };\n }\n}\n\nexport const createMainThreadRef = <T>(initValue: T): MainThreadRef<T> =>\n new MainThreadRef(initValue);\n\n/**\n * Reset counter on HMR.\n */\nexport const __resetRefCounter = (): void => {\n nextRefId = 0;\n};\n","import type { ElementRef } from '../types/lynx';\nimport {\n LynxAnimation,\n type LynxAnimationOptions,\n} from '../animation/animation';\n\n/**\n * Batched flush — coalesces multiple style/attribute mutations into a single\n * native render pass, matching React Lynx's Element.flushElementTree() behavior.\n * Without batching, each setAttribute/setStyleProperty would trigger a separate\n * layout pass. With batching, a handler that sets 5 properties produces 1 flush\n * (on the next microtask) instead of 5, preventing visible frame drops.\n */\nlet willFlush = false;\n\nconst scheduleFlush = (): void => {\n if (willFlush) return;\n willFlush = true;\n // Microtask ensures the flush runs after all synchronous mutations in the\n // current event handler are applied, but before the next frame renders.\n Promise.resolve().then(() => {\n willFlush = false;\n __FlushElementTree();\n });\n};\n\n/**\n * Wraps a native ElementRef (elementRefptr) with the @lynx-js/types\n * MainThread.Element API surface. Created by runWorklet's param transformation\n * so that main-thread event handlers can call setStyleProperty(), setAttribute(),\n * etc. on event.currentTarget.\n */\nexport class MainThreadElement {\n readonly #element: ElementRef;\n\n constructor(element: ElementRef) {\n this.#element = element;\n }\n\n setAttribute(name: string, value: unknown): void {\n __SetAttribute(this.#element, name, value);\n scheduleFlush();\n }\n\n getAttribute(name: string): unknown {\n return __GetAttributeByName(this.#element, name);\n }\n\n getAttributeNames(): string[] {\n return __GetAttributeNames(this.#element);\n }\n\n setStyleProperty(name: string, value: string): void {\n __AddInlineStyle(this.#element, name, value);\n scheduleFlush();\n }\n\n setStyleProperties(styles: Record<string, string>): void {\n for (const key in styles) {\n __AddInlineStyle(this.#element, key, styles[key]!);\n }\n scheduleFlush();\n }\n\n querySelector(selector: string): MainThreadElement | null {\n const ref = __QuerySelector(this.#element, selector, {});\n return ref ? new MainThreadElement(ref) : null;\n }\n\n querySelectorAll(selector: string): MainThreadElement[] {\n return __QuerySelectorAll(this.#element, selector, {}).map(\n (el) => new MainThreadElement(el),\n );\n }\n\n /**\n * Invokes a native UI method on this element (e.g. scrollTo, autoPlay).\n * __InvokeUIMethod is asynchronous — the result arrives in the callback.\n * scheduleFlush() must be called AFTER __InvokeUIMethod so the method\n * invocation is included in the next native render pass.\n */\n invoke(\n methodName: string,\n params?: Record<string, unknown>,\n ): Promise<unknown> {\n return new Promise((resolve, reject) => {\n __InvokeUIMethod(\n this.#element,\n methodName,\n params ?? {},\n (res: { code: number; data: unknown }) => {\n if (res.code === 0) {\n resolve(res.data);\n } else {\n reject(new Error('UI method invoke: ' + JSON.stringify(res)));\n }\n },\n );\n scheduleFlush();\n });\n }\n\n animate(\n keyframes: Record<string, number | string>[],\n options?: number | LynxAnimationOptions,\n ): LynxAnimation {\n const normalizedOptions =\n typeof options === 'number' ? { duration: options } : (options ?? {});\n return new LynxAnimation(this.#element, keyframes, normalizedOptions);\n }\n\n /**\n * Not part of the official @lynx-js/types Element interface, but useful for\n * touch-tracking calculations. Uses __GetComputedStyleByKey when available.\n */\n getBoundingClientRect(): {\n left: number;\n top: number;\n right: number;\n bottom: number;\n width: number;\n height: number;\n } {\n if (typeof __GetComputedStyleByKey !== 'function') {\n return { left: 0, top: 0, right: 0, bottom: 0, width: 0, height: 0 };\n }\n const width =\n parseFloat(__GetComputedStyleByKey(this.#element, 'width')) || 0;\n const height =\n parseFloat(__GetComputedStyleByKey(this.#element, 'height')) || 0;\n const left =\n parseFloat(__GetComputedStyleByKey(this.#element, 'left')) || 0;\n const top = parseFloat(__GetComputedStyleByKey(this.#element, 'top')) || 0;\n return {\n left,\n top,\n right: left + width,\n bottom: top + height,\n width,\n height,\n };\n }\n}\n","import {\n Directive,\n ElementRef,\n inject,\n type OnChanges,\n type OnDestroy,\n type SimpleChanges,\n} from '@angular/core';\nimport type { BaseLynxElement } from '../lynx-element/types';\nimport type { MainThreadFnHandle } from './main-thread-fn';\n\n/**\n * Plain functions are also accepted because the worklet build plugin transforms\n * them into MainThreadFnHandle objects at compile time.\n */\ntype MaybeHandle =\n | MainThreadFnHandle\n | ((...args: any[]) => any)\n | undefined\n | null;\n\n/**\n * Maps directive input names to [eventType, eventName] for Lynx's __AddEvent PAPI.\n * eventType is 'bindEvent' (bubbles) or 'catchEvent' (stops propagation) —\n * these map to Lynx's bind* / catch* event model, not DOM addEventListener.\n */\nconst INPUT_TO_EVENT: Record<string, [string, string]> = {\n mainThreadBindtap: ['bindEvent', 'tap'],\n mainThreadCatchtap: ['catchEvent', 'tap'],\n mainThreadBindtouchstart: ['bindEvent', 'touchstart'],\n mainThreadCatchtouchstart: ['catchEvent', 'touchstart'],\n mainThreadBindtouchmove: ['bindEvent', 'touchmove'],\n mainThreadCatchtouchmove: ['catchEvent', 'touchmove'],\n mainThreadBindtouchend: ['bindEvent', 'touchend'],\n mainThreadCatchtouchend: ['catchEvent', 'touchend'],\n mainThreadBindlongpress: ['bindEvent', 'longpress'],\n mainThreadCatchlongpress: ['catchEvent', 'longpress'],\n mainThreadBindscroll: ['bindEvent', 'scroll'],\n mainThreadCatchscroll: ['catchEvent', 'scroll'],\n mainThreadBindanimationstart: ['bindEvent', 'animationstart'],\n mainThreadBindanimationend: ['bindEvent', 'animationend'],\n mainThreadBindtransitionend: ['bindEvent', 'transitionend'],\n mainThreadBindlayoutchange: ['bindEvent', 'layoutchange'],\n};\n\nconst isMainThreadHandle = (h: MaybeHandle): h is MainThreadFnHandle =>\n !!h &&\n '__isMainThreadFn' in h &&\n !!(h as MainThreadFnHandle).__isMainThreadFn;\n\n/**\n * Bridges Angular template bindings like `(mainThreadBindtap)=\"handler\"` to\n * Lynx's main-thread (Lepus) event dispatch.\n *\n * Why a dedicated directive and not the renderer's listen() path:\n * - Normal `(bindtap)` events are delivered to the background JS thread and\n * incur a thread hop on every dispatch — fine for one-shot taps, but too\n * slow for gesture-driven UI (scroll-tracking, drag, pinch) where the\n * handler needs to mutate styles at native frame rate.\n * - The `mainThreadBind*` / `mainThreadCatch*` family registers the handler\n * as a *worklet* with `_workletType: 'main-thread'`, so Lynx invokes it\n * directly on the Lepus thread where __AddInlineStyle / __SetAttribute are\n * synchronous. There is no thread hop and no background JS involvement.\n * - These inputs cannot be expressed as @Output() because Angular would route\n * them through its own event subscription system and the underlying\n * worklet handle would never be passed to __AddEvent.\n *\n * The worklet plugin (in rsbuild-plugin-angular-lynx) rewrites any function\n * annotated with `'main thread'` directive into a `MainThreadFnHandle`\n * carrying a stable `_wkltId`. That ID is what we hand to __AddEvent here.\n */\n@Directive({\n selector:\n '[mainThreadBindtap],[mainThreadCatchtap],' +\n '[mainThreadBindtouchstart],[mainThreadCatchtouchstart],' +\n '[mainThreadBindtouchmove],[mainThreadCatchtouchmove],' +\n '[mainThreadBindtouchend],[mainThreadCatchtouchend],' +\n '[mainThreadBindlongpress],[mainThreadCatchlongpress],' +\n '[mainThreadBindscroll],[mainThreadCatchscroll],' +\n '[mainThreadBindanimationstart],[mainThreadBindanimationend],' +\n '[mainThreadBindtransitionend],[mainThreadBindlayoutchange]',\n standalone: true,\n inputs: [\n 'mainThreadBindtap',\n 'mainThreadCatchtap',\n 'mainThreadBindtouchstart',\n 'mainThreadCatchtouchstart',\n 'mainThreadBindtouchmove',\n 'mainThreadCatchtouchmove',\n 'mainThreadBindtouchend',\n 'mainThreadCatchtouchend',\n 'mainThreadBindlongpress',\n 'mainThreadCatchlongpress',\n 'mainThreadBindscroll',\n 'mainThreadCatchscroll',\n 'mainThreadBindanimationstart',\n 'mainThreadBindanimationend',\n 'mainThreadBindtransitionend',\n 'mainThreadBindlayoutchange',\n ],\n})\nexport class LynxMainThreadEvent implements OnChanges, OnDestroy {\n readonly #el: BaseLynxElement = inject(ElementRef).nativeElement;\n #registeredEvents: [string, string][] = [];\n\n mainThreadBindtap?: MaybeHandle;\n mainThreadCatchtap?: MaybeHandle;\n mainThreadBindtouchstart?: MaybeHandle;\n mainThreadCatchtouchstart?: MaybeHandle;\n mainThreadBindtouchmove?: MaybeHandle;\n mainThreadCatchtouchmove?: MaybeHandle;\n mainThreadBindtouchend?: MaybeHandle;\n mainThreadCatchtouchend?: MaybeHandle;\n mainThreadBindlongpress?: MaybeHandle;\n mainThreadCatchlongpress?: MaybeHandle;\n mainThreadBindscroll?: MaybeHandle;\n mainThreadCatchscroll?: MaybeHandle;\n mainThreadBindanimationstart?: MaybeHandle;\n mainThreadBindanimationend?: MaybeHandle;\n mainThreadBindtransitionend?: MaybeHandle;\n mainThreadBindlayoutchange?: MaybeHandle;\n\n ngOnChanges(changes: SimpleChanges): void {\n // ElementRef.nativeElement is our BaseLynxElement wrapper; the underlying\n // native handle that __AddEvent expects lives on its `.element` property.\n // We reach in via `any` rather than widening the public type because this\n // back-channel exists only for PAPI calls and shouldn't be part of the\n // public BaseLynxElement contract used elsewhere.\n const elementRef = (this.#el as any).element;\n if (!elementRef) return;\n\n for (const inputName of Object.keys(changes)) {\n const mapping = INPUT_TO_EVENT[inputName];\n if (!mapping) continue;\n\n const [eventType, eventName] = mapping;\n const handle = (this as any)[inputName] as MaybeHandle;\n\n if (isMainThreadHandle(handle)) {\n // type: 'worklet' tells the Lynx engine to invoke this handler via the\n // worklet system (runWorklet) on the main thread, NOT via the normal\n // background-thread event dispatch. _workletType: 'main-thread' ensures\n // the handler runs on the Lepus thread where it can call __AddInlineStyle,\n // __SetAttribute, etc. for 60fps animations without cross-thread latency.\n __AddEvent(elementRef, eventType, eventName, {\n type: 'worklet',\n value: { _wkltId: handle._wkltId, _workletType: 'main-thread' },\n });\n // Track (eventType, eventName) so ngOnDestroy can unregister the same\n // pair. We deliberately don't deduplicate — re-binding the same input\n // overwrites the previous registration at the native level, so a\n // duplicate entry in the array is harmless (the second cleanup is a\n // no-op).\n this.#registeredEvents.push([eventType, eventName]);\n }\n }\n }\n\n ngOnDestroy(): void {\n const elementRef = (this.#el as any).element;\n if (!elementRef) return;\n\n // Lynx's PAPI unregisters an event handler by calling __AddEvent with\n // `undefined` as the handler value — there is no separate __RemoveEvent.\n // Without this cleanup, the worklet handle would keep its registration\n // pointing at a destroyed component, and any subsequent native dispatch\n // would invoke a stale closure (or, worse, leak a reference that pins\n // the component graph).\n for (const [eventType, eventName] of this.#registeredEvents) {\n __AddEvent(elementRef, eventType, eventName, undefined);\n }\n this.#registeredEvents = [];\n }\n}\n","import { Injectable } from '@angular/core';\nimport type { MainThreadFnHandle } from './main-thread-fn';\n\n/**\n * Injectable service for calling main-thread (Lepus) functions. From the\n * background thread it uses Lynx's cross-thread RPC via JSContext events:\n *\n * background calls runOnMainThread(handle, ...args)\n * → dispatches 'Lynx.Worklet.runWorkletCtx' with { worklet, params, resolveId }\n * → main thread's listener (in runtime.ts) invokes the registered worklet fn\n * → dispatches 'Lynx.Worklet.FunctionCallRet' with { resolveId, returnValue }\n * → background thread's listener resolves the Promise\n *\n * This enables background-thread Angular code (services, effects) to trigger\n * main-thread imperative operations (animate, measure, invoke UI methods)\n * with proper async/await ergonomics.\n *\n * It is also safe to call from code already running on the main thread. The\n * renderer registers Angular `(bind*)`/`(catch*)` event handlers as main-thread\n * worklets, so a handler like `(bindtap)=\"flash()\"` executes on the Lepus thread\n * — and any runOnMainThread() call it makes originates there too. Rather than\n * fail (there is no other thread to be \"called from\"), we detect that case and\n * invoke the target worklet in-place, so the same call site works regardless of\n * which thread reaches it.\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxMainThread {\n runOnMainThread<TArgs extends unknown[], TReturn>(\n handle: MainThreadFnHandle<TArgs, TReturn>,\n ...args: TArgs\n ): Promise<TReturn> {\n if (__MAIN_THREAD__) {\n // Already on the main thread — run the worklet directly instead of an RPC\n // round trip to ourselves (which would never be answered). No JSON\n // serialization guard here: args stay in-process, so non-serializable\n // values (element handles, MainThreadRefs) are passed through intact.\n const invokeDirect = (globalThis as any).__lynxRunMainThreadWorklet as\n | ((wkltId: string, a: unknown[]) => TReturn)\n | undefined;\n if (!invokeDirect) {\n return Promise.reject(\n new Error(\n '[angular-lynx] runOnMainThread() called on the main thread before the runtime worklet registry was initialized',\n ),\n );\n }\n try {\n return Promise.resolve(invokeDirect(handle._wkltId, args));\n } catch (e) {\n return Promise.reject(e);\n }\n }\n\n // Cross-thread params are JSON-serialized via dispatchEvent — non-serializable\n // values (functions, circular refs) would silently become null/undefined on the\n // main thread, leading to hard-to-debug runtime errors.\n // `__DEV__` is a build-time `define` set to `false` in the Vitest config,\n // so this dev-only guard is dead code from the test bundle's point of view.\n /* v8 ignore next 9 */\n if (__DEV__) {\n try {\n JSON.stringify(args);\n } catch {\n throw new Error(\n '[angular-lynx] MTS arguments must be JSON-serializable',\n );\n }\n }\n\n const resolveId = (globalThis as any).__lynxMtsNextResolveId();\n const pendingResolvers = (globalThis as any).__lynxMtsPendingResolvers;\n\n return new Promise<TReturn>((resolve, reject) => {\n pendingResolvers[resolveId] = { resolve, reject };\n\n try {\n (lynx as any).getCoreContext().dispatchEvent({\n type: 'Lynx.Worklet.runWorkletCtx',\n data: JSON.stringify({\n worklet: { _wkltId: handle._wkltId },\n params: args,\n resolveId,\n }),\n });\n } catch (e) {\n delete pendingResolvers[resolveId];\n reject(e);\n }\n });\n }\n}\n","import { Injectable } from '@angular/core';\nimport type {\n ResourcePrefetchData,\n ResourcePrefetchResult,\n} from '@lynx-js/types';\n\nexport type { ResourcePrefetchData, ResourcePrefetchResult };\n\n/**\n * Resource priority hint for the native prefetch engine.\n */\nexport type PrefetchPriority = 'high' | 'medium' | 'low';\n\n/**\n * Cache destination for a prefetched resource.\n * - `'disk'` — persists across app sessions (larger resources)\n * - `'bitmap'` — decoded into memory for immediate display (images)\n */\nexport type PrefetchCacheTarget = 'disk' | 'bitmap';\n\n/**\n * Describes a single resource to prefetch.\n */\nexport type PrefetchRequest = {\n /**\n * URL of the resource to prefetch.\n */\n uri: string;\n /**\n * Resource type — determines the native prefetch pipeline.\n */\n type: 'image' | 'video';\n /**\n * Optional priority hint (default determined by native engine).\n */\n priority?: PrefetchPriority;\n /**\n * Where to cache the prefetched resource.\n */\n cacheTarget?: PrefetchCacheTarget;\n /**\n * Custom cache key for manual cache management.\n */\n preloadKey?: string;\n /**\n * Expected resource size in bytes (helps native allocate buffers).\n */\n size?: number;\n};\n\n/**\n * Per-resource result from a prefetch or cancel operation.\n */\nexport type PrefetchResultDetail = {\n code: number;\n msg: string;\n uri: string;\n type: 'image' | 'video';\n};\n\n/**\n * Wraps `lynx.requestResourcePrefetch()` and `lynx.cancelResourcePrefetch()`\n * with a Promise-based API for preloading images and videos into the native\n * cache before they're needed for display.\n *\n * Only available on the background thread — these APIs are not exposed on\n * the main thread.\n *\n * @usageNotes\n * ```typescript\n * const prefetch = inject(LynxResourcePrefetch);\n *\n * // Prefetch a single image\n * const result = await prefetch.request([\n * { uri: 'https://cdn.example.com/hero.jpg', type: 'image' },\n * ]);\n *\n * // Prefetch multiple resources with priority\n * await prefetch.request([\n * { uri: 'https://cdn.example.com/hero.jpg', type: 'image', priority: 'high' },\n * { uri: 'https://cdn.example.com/promo.mp4', type: 'video', priority: 'low' },\n * ]);\n *\n * // Cancel an in-flight prefetch\n * await prefetch.cancel([\n * { uri: 'https://cdn.example.com/promo.mp4', type: 'video' },\n * ]);\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxResourcePrefetch {\n /**\n * Request prefetching of one or more resources into the native cache.\n * Resolves when the native engine acknowledges the request (not necessarily\n * when the download completes).\n */\n request(resources: PrefetchRequest[]): Promise<ResourcePrefetchResult> {\n if (typeof lynx === 'undefined' || !lynx.requestResourcePrefetch) {\n return Promise.reject(\n new Error(\n 'lynx.requestResourcePrefetch is not available in this environment',\n ),\n );\n }\n\n const data = this.#toNativeData(resources);\n\n return new Promise((resolve) => {\n lynx.requestResourcePrefetch(data, resolve);\n });\n }\n\n /**\n * Cancel in-flight prefetch requests for the specified resources.\n * Useful when navigating away before prefetched content is needed.\n */\n cancel(resources: PrefetchRequest[]): Promise<ResourcePrefetchResult> {\n if (typeof lynx === 'undefined' || !lynx.cancelResourcePrefetch) {\n return Promise.reject(\n new Error(\n 'lynx.cancelResourcePrefetch is not available in this environment',\n ),\n );\n }\n\n const data = this.#toNativeData(resources);\n\n return new Promise((resolve) => {\n lynx.cancelResourcePrefetch(data, resolve);\n });\n }\n\n #toNativeData(resources: PrefetchRequest[]): ResourcePrefetchData {\n return {\n data: resources.map((r) => {\n const hasParam =\n r.priority || r.cacheTarget || r.preloadKey || r.size != null;\n if (!hasParam) {\n return { uri: r.uri, type: r.type };\n }\n return {\n uri: r.uri,\n type: r.type,\n param: {\n // Native type requires `size` when `param` is present\n size: r.size ?? 0,\n ...(r.priority && { priority: r.priority }),\n ...(r.cacheTarget && { cacheTarget: r.cacheTarget }),\n ...(r.preloadKey && { preloadKey: r.preloadKey }),\n },\n };\n }),\n };\n }\n}\n","import { Injectable } from '@angular/core';\nimport type { SystemInfo, PlatformType } from '@lynx-js/types';\n\n/**\n * Wraps the global `SystemInfo` object as an Angular injectable,\n * providing device and platform information from the Lynx runtime.\n *\n * `SystemInfo` is populated once when the Lynx view initializes and\n * is read-only for the lifetime of the app — the values never change.\n *\n * @usageNotes\n * ```typescript\n * const systemInfo = inject(LynxSystemInfo);\n *\n * // Device dimensions in physical pixels\n * const { pixelWidth, pixelHeight, pixelRatio } = systemInfo;\n *\n * // Logical screen dimensions (CSS pixels)\n * const cssWidth = systemInfo.screenWidth;\n * const cssHeight = systemInfo.screenHeight;\n *\n * // Platform detection\n * if (systemInfo.platform === 'iOS') {\n * // iOS-specific logic\n * }\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxSystemInfo {\n readonly #info: SystemInfo;\n\n constructor() {\n if (typeof SystemInfo === 'undefined') {\n throw new Error('SystemInfo is not available in this environment');\n }\n this.#info = SystemInfo;\n }\n\n /**\n * The platform of the current device (e.g. `'iOS'`, `'Android'`).\n */\n get platform(): PlatformType {\n return this.#info.platform;\n }\n\n /**\n * The Lynx engine version (e.g. `'3.2'`).\n */\n get engineVersion(): string {\n return this.#info.engineVersion;\n }\n\n /**\n * The current operating system version.\n */\n get osVersion(): string {\n return this.#info.osVersion;\n }\n\n /**\n * Physical pixel width of the device screen.\n */\n get pixelWidth(): number {\n return this.#info.pixelWidth;\n }\n\n /**\n * Physical pixel height of the device screen.\n */\n get pixelHeight(): number {\n return this.#info.pixelHeight;\n }\n\n /**\n * Device pixel ratio (physical pixels per CSS pixel).\n */\n get pixelRatio(): number {\n return this.#info.pixelRatio;\n }\n\n /**\n * The JavaScript engine in use (`'v8'`, `'jsc'`, or `'quickjs'`). Only available on the background thread.\n */\n get runtimeType(): 'v8' | 'jsc' | 'quickjs' {\n return this.#info.runtimeType;\n }\n\n /**\n * Screen width in logical/CSS pixels (`pixelWidth / pixelRatio`).\n */\n get screenWidth(): number {\n return this.#info.pixelWidth / this.#info.pixelRatio;\n }\n\n /**\n * Screen height in logical/CSS pixels (`pixelHeight / pixelRatio`).\n */\n get screenHeight(): number {\n return this.#info.pixelHeight / this.#info.pixelRatio;\n }\n\n /**\n * The theme object, if provided by the host application.\n */\n get theme(): object | undefined {\n return this.#info.theme;\n }\n}\n","import { computed, inject, Injectable } from '@angular/core';\nimport { LynxGlobalData } from '../data-flow/global-data';\nimport { LynxSystemInfo } from '../system-info/system-info';\n\n/**\n * CSS `env()` value for the top safe area inset (notch / status bar).\n */\nexport const SAFE_AREA_INSET_TOP = 'env(safe-area-inset-top)';\n/**\n * CSS `env()` value for the bottom safe area inset (home indicator).\n */\nexport const SAFE_AREA_INSET_BOTTOM = 'env(safe-area-inset-bottom)';\n/**\n * CSS `env()` value for the left safe area inset.\n */\nexport const SAFE_AREA_INSET_LEFT = 'env(safe-area-inset-left)';\n/**\n * CSS `env()` value for the right safe area inset.\n */\nexport const SAFE_AREA_INSET_RIGHT = 'env(safe-area-inset-right)';\n\n/**\n * Provides device adaptation helpers for notch/safe-area-aware layouts.\n *\n * Safe area insets in Lynx are applied via CSS `env(safe-area-inset-*)`,\n * identical to the web platform. This service exposes the `isNotchScreen`\n * flag from the native host as a reactive signal for conditional logic.\n *\n * @usageNotes\n *\n * ### CSS approach (preferred)\n * ```css\n * .container {\n * padding-top: env(safe-area-inset-top);\n * padding-bottom: env(safe-area-inset-bottom);\n * }\n * ```\n *\n * ### Conditional logic in TypeScript\n * ```typescript\n * const safeArea = inject(LynxSafeArea);\n *\n * if (safeArea.isNotchScreen()) {\n * // Adjust layout for notch devices\n * }\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxSafeArea {\n readonly #globalData = inject(LynxGlobalData);\n readonly #systemInfo = inject(LynxSystemInfo);\n\n /**\n * Whether the device has a display notch or cutout. Reactive — updates when global props change.\n */\n readonly isNotchScreen = computed(\n () =>\n !!(this.#globalData.globalData() as Record<string, unknown>)[\n 'isNotchScreen'\n ],\n );\n\n /**\n * The current platform (`'iOS'`, `'Android'`, `'Harmony'`, etc.).\n */\n get platform() {\n return this.#systemInfo.platform;\n }\n}\n","import {\n type Injector,\n DestroyRef,\n inject,\n Injectable,\n signal,\n} from '@angular/core';\nimport type { SessionStorageSubscription } from './session-storage.types';\n\n/**\n * Wraps Lynx's session storage API for sharing data across multiple LynxViews.\n *\n * Session storage is a key-value store that persists for the lifetime of the\n * host app session. Unlike browser localStorage, values are objects (not strings)\n * and reads are asynchronous (callback-based in the native API, Promise-based here).\n *\n * The `setSessionStorageItem` / `getSessionStorageItem` / `subscribeSessionStorage` /\n * `unsubscribeSessionStorage` methods are not declared in `@lynx-js/types`, so we\n * access them via `any` — the APIs are stable and documented on lynxjs.org.\n *\n * The native surface differs by thread, and AngularLynx bootstraps the same\n * component tree on both (see runtime.ts), so this service must detect which\n * thread it's on rather than assume one shape everywhere:\n * - Background thread: `getSessionStorageItem(key, callback)` is async, plus\n * `subscribeSessionStorage`/`unsubscribeSessionStorage` for pub/sub.\n * - Main thread (Lepus engine, see `Utils::CreateLynx` in lynx core): only\n * `setSessionStorageItem`/`getSessionStorageItem` are registered — no\n * subscribe/unsubscribe at all — and `getSessionStorageItem` is\n * *synchronous*, taking just the key and returning the value directly.\n * Calling it with a callback (the background-thread shape) throws a native\n * \"GetSessionStorageItem param size should be 1\" fatal error.\n *\n * @usageNotes\n * ```typescript\n * const sessionStorage = inject(LynxSessionStorage);\n *\n * // Write\n * sessionStorage.setItem('theme', { mode: 'dark' });\n *\n * // One-shot read\n * const theme = await sessionStorage.getItem<{ mode: string }>('theme');\n *\n * // Reactive signal (auto-subscribes, auto-cleans up with injection context)\n * const theme = sessionStorage.watch<{ mode: string }>('theme');\n * // theme() updates whenever another LynxView calls setItem('theme', ...)\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxSessionStorage {\n // In-memory fallback when native session storage is unavailable (web preview, tests, SSR).\n readonly #store = new Map<string, unknown>();\n readonly #listeners = new Map<\n string,\n Map<number, (value: unknown) => void>\n >();\n #nextId = 0;\n\n #hasNativeSessionStorage(): boolean {\n return (\n typeof lynx !== 'undefined' &&\n typeof (lynx as any).setSessionStorageItem === 'function'\n );\n }\n\n /**\n * The main thread's `lynx` global never registers subscribe/unsubscribe\n * (only setSessionStorageItem/getSessionStorageItem exist there), so pub/sub\n * must always fall back to the local listener map on that thread.\n */\n #hasNativeSubscription(): boolean {\n return (\n this.#hasNativeSessionStorage() &&\n !(typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__)\n );\n }\n\n /**\n * Notifies every locally-registered listener for a key. Extracted so the\n * two callers that must drive the local pub/sub layer — the in-memory\n * fallback and the main-thread native path — share one implementation\n * instead of duplicating the map walk (the main-thread path originally\n * omitted it entirely, which is what left watched signals stale).\n *\n * On the main thread native pub/sub does not exist, so {@link watch}'s\n * subscription lives entirely in this local map and only this call reaches\n * it.\n */\n #notifyLocalListeners(key: string, value: unknown): void {\n const keyListeners = this.#listeners.get(key);\n if (keyListeners) {\n for (const [, cb] of keyListeners) cb(value);\n }\n }\n\n /**\n * Stores a value in session storage, shared across all LynxViews.\n * Existing subscribers for this key will be notified of the change.\n *\n * Two main-thread quirks are handled here, both discovered as on-device\n * crashes/bugs in the session-storage example:\n *\n * 1. **Values must be objects.** The main thread's native\n * setSessionStorageItem rejects primitives with a fatal\n * \"SetSessionStorageItem param 1 should be Object\" error, so a bare\n * `setItem('counter', 1)` would crash on Increment. We wrap primitives\n * in `{ __data }` (getItem unwraps them symmetrically).\n *\n * 2. **No native pub/sub.** The main thread registers only get/set — there\n * is no subscribeSessionStorage — so {@link watch}'s subscription falls\n * back to the local listener map (see {@link subscribe}). A native write\n * alone therefore never reaches those listeners: the counter signal stays\n * on its seed value and the UI shows \"not set\" no matter how many times\n * the user taps Increment. We bridge the gap by firing the local\n * listeners ourselves right after the native write.\n *\n * The background thread deliberately does NOT call #notifyLocalListeners:\n * there, watch() subscribes through native subscribeSessionStorage, and the\n * native layer already fans the change out to every LynxView (including this\n * one). Firing local listeners too would double-notify. There is no infinite\n * loop in either case — #notifyLocalListeners only invokes stored callbacks,\n * it never calls setItem back.\n */\n setItem<T = unknown>(key: string, value: T): void {\n if (this.#hasNativeSessionStorage()) {\n // Main thread requires values to be objects; wrap primitives.\n if (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__) {\n const wrapped =\n typeof value === 'object' && value !== null\n ? value\n : { __data: value };\n (lynx as any).setSessionStorageItem(key, wrapped);\n // Native subscribe/unsubscribe don't exist on the main thread, so\n // bridge the write to the local listener map that watch() relies on —\n // without this the watched signal never updates and the UI stays stale.\n this.#notifyLocalListeners(key, value);\n return;\n }\n // Background thread: native pub/sub notifies subscribers, so we don't.\n (lynx as any).setSessionStorageItem(key, value);\n return;\n }\n\n // In-memory fallback (web preview, tests, SSR): the local map is both the\n // store and the pub/sub layer, so write then notify.\n this.#store.set(key, value);\n this.#notifyLocalListeners(key, value);\n }\n\n /**\n * Reads a value from session storage. The native API is callback-based;\n * this wraps it in a Promise for ergonomic use with `async`/`await`.\n *\n * On the main thread, wrapped primitives are unwrapped here to match\n * the user's expectation that the value they stored is the value they get.\n */\n getItem<T = unknown>(key: string): Promise<T> {\n if (this.#hasNativeSessionStorage()) {\n // Main thread: synchronous, single-arg — see the class-level doc comment.\n if (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__) {\n const raw = (lynx as any).getSessionStorageItem(key);\n // Undo setItem's primitive wrapping so callers get back exactly what\n // they stored. The `Object.keys(raw).length === 1` guard is what keeps\n // this from mangling genuine user objects: a real payload that happens\n // to have a `__data` key (e.g. `{ __data, other }`) has more than one\n // key and is returned untouched, so only our own single-key wrapper\n // { __data } is unwrapped.\n const unwrapped =\n raw != null &&\n typeof raw === 'object' &&\n '__data' in raw &&\n Object.keys(raw).length === 1\n ? (raw.__data as T)\n : (raw as T);\n return Promise.resolve(unwrapped);\n }\n\n return new Promise<T>((resolve) => {\n (lynx as any).getSessionStorageItem(key, (value: T) => resolve(value));\n });\n }\n\n return Promise.resolve(this.#store.get(key) as T);\n }\n\n /**\n * Subscribes to changes for a session storage key. The callback fires\n * whenever any LynxView calls `setItem` with the same key.\n *\n * Returns the subscription needed for {@link unsubscribe}.\n */\n subscribe<T = unknown>(\n key: string,\n callback: (value: T) => void,\n ): SessionStorageSubscription {\n if (this.#hasNativeSubscription()) {\n const listenerId: number = (lynx as any).subscribeSessionStorage(\n key,\n callback,\n );\n return { key, listenerId };\n }\n\n const id = this.#nextId++;\n let keyListeners = this.#listeners.get(key);\n if (!keyListeners) {\n keyListeners = new Map();\n this.#listeners.set(key, keyListeners);\n }\n keyListeners.set(id, callback as (value: unknown) => void);\n return { key, listenerId: id };\n }\n\n /**\n * Cancels a session storage subscription created by {@link subscribe}.\n */\n unsubscribe(subscription: SessionStorageSubscription): void {\n if (this.#hasNativeSubscription()) {\n (lynx as any).unsubscribeSessionStorage(\n subscription.key,\n subscription.listenerId,\n );\n return;\n }\n\n this.#listeners.get(subscription.key)?.delete(subscription.listenerId);\n }\n\n /**\n * Creates a reactive signal that tracks a session storage key.\n *\n * Seeds the signal with the current value via `getItem`, then subscribes\n * to future changes. The subscription is automatically cleaned up when the\n * calling component/service is destroyed.\n *\n * Must be called from an injection context (constructor, field initializer,\n * or `runInInjectionContext`) unless an explicit `injector` is provided.\n */\n watch<T = unknown>(\n key: string,\n options?: { injector?: Injector },\n ): ReturnType<typeof signal<T | undefined>> {\n const value = signal<T | undefined>(undefined);\n\n // Seed with current value.\n this.getItem<T>(key).then((v) => value.set(v));\n\n // Subscribe to future changes.\n const subscription = this.subscribe<T>(key, (v) => value.set(v));\n\n // Auto-cleanup when the caller's injection context is destroyed. // The `inject(DestroyRef)` fallback fires only from a live injection\n // context, which the spec doesn't set up — every unit test passes an\n // explicit injector. Consumers exercise the fallback in real Angular\n // apps that call watch() from a component constructor.\n /* v8 ignore next 3 */ const destroyRef = options?.injector\n ? options.injector.get(DestroyRef)\n : inject(DestroyRef);\n destroyRef.onDestroy(() => this.unsubscribe(subscription));\n\n return value;\n }\n}\n","import { Injectable } from '@angular/core';\nimport type { TextInfo, TextMetrics } from '@lynx-js/types';\n\n/**\n * Wraps `lynx.getTextInfo()` for measuring text dimensions and\n * performing line-breaking calculations.\n *\n * Only works with built-in platform fonts. Custom fonts loaded via\n * `@font-face` or `LynxFont` will fall back to the default\n * system font and produce inaccurate measurements.\n *\n * @usageNotes\n * ```typescript\n * const textMeasure = inject(LynxTextMeasure);\n *\n * const { width } = textMeasure.measure('Hello', { fontSize: '16px' });\n *\n * const { content } = textMeasure.measure('Long text...', {\n * fontSize: '14px',\n * maxWidth: '200px',\n * maxLine: 3,\n * });\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxTextMeasure {\n measure(text: string, options: TextInfo): TextMetrics {\n if (typeof lynx === 'undefined') {\n throw new Error('lynx.getTextInfo is not available in this environment');\n }\n\n if (!text) {\n return { width: 0 };\n }\n\n return lynx.getTextInfo(text, options);\n }\n}\n","import { computed, inject, Injectable } from '@angular/core';\nimport { LynxGlobalData } from '../data-flow/global-data';\n\n/**\n * Provides reactive access to the current Lynx theme ('Dark' or 'Light').\n *\n * The theme is driven by `lynx.__globalProps.theme`, which the native host\n * sets based on the OS appearance setting. It updates reactively when the\n * host calls `updateGlobalProps`.\n *\n * @usageNotes\n * ```typescript\n * const theme = inject(LynxTheme);\n *\n * // Reactive in templates\n * template: `<text [style.color]=\"theme.isDarkMode() ? '#fff' : '#000'\">Hello</text>`\n *\n * // Or use CSS variables (preferred for styling — see docs/guide/dark-mode.mdx)\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxTheme {\n readonly #globalData = inject(LynxGlobalData);\n\n /**\n * The current theme: `'Dark'` or `'Light'`. Reactive — updates when global props change.\n */\n readonly theme = computed(() => {\n const value = (this.#globalData.globalData() as Record<string, unknown>)[\n 'theme'\n ];\n return (value as 'Dark' | 'Light') ?? 'Light';\n });\n\n /**\n * Whether the current theme is dark mode. Reactive.\n */\n readonly isDarkMode = computed(() => this.theme() === 'Dark');\n}\n","import {\n Component,\n effect,\n ElementRef,\n inject,\n input,\n output,\n Renderer2,\n signal,\n} from '@angular/core';\n\n/**\n * Animates the enter/leave of projected content using CSS `@keyframes`.\n *\n * Two classes are toggled on the host element:\n *\n * | Phase | Class applied | Plays |\n * |-------|-----------------|----------------------------------------|\n * | Enter | `{name}-enter` | on mount, until `duration` elapses |\n * | Leave | `{name}-leave` | then the element is unmounted |\n *\n * **Why keyframes, not a two-phase CSS `transition`.** The obvious Vue-style\n * approach (mount in a `-enter-from` state, then swap to `-enter-to` one frame\n * later so a `transition` interpolates) needs a real paint gap between the two\n * states. Lynx's background thread — where Angular runs — has no reliable frame\n * boundary: `requestAnimationFrame` is microtask-mapped/absent, and class\n * mutations made from an rAF/`setTimeout` callback don't go through change\n * detection so they never reliably flush to the main thread (the element tree is\n * committed once per CD cycle in `LynxRendererFactory2.end()`). A `@keyframes`\n * animation sidesteps all of it: a SINGLE class, applied inside the effect (a CD\n * pass) so it flushes in the same commit that mounts the element, and the native\n * engine plays the keyframes from 0%. This mirrors the proven single-class\n * pattern in `examples/animations`.\n *\n * Completion is timer-based (`duration`) because the background thread has no\n * `animationend` bridge — `duration` must match your CSS animation length.\n *\n * @usageNotes\n * ```html\n * <lynx-transition [show]=\"isVisible()\" name=\"fade\" [duration]=\"300\">\n * <view class=\"panel\"><text>Hello</text></view>\n * </lynx-transition>\n * ```\n *\n * ```css\n * @keyframes fade-enter { from { opacity: 0; } to { opacity: 1; } }\n * @keyframes fade-leave { from { opacity: 1; } to { opacity: 0; } }\n * .fade-enter { animation: fade-enter 300ms ease both; }\n * .fade-leave { animation: fade-leave 300ms ease both; }\n * ```\n */\n@Component({\n selector: 'lynx-transition',\n standalone: true,\n template: `@if (shouldRender()) {\n <ng-content />\n }`,\n})\nexport class LynxTransition {\n readonly show = input<boolean>(false);\n readonly name = input<string>('v');\n readonly duration = input<number>(300);\n\n readonly afterEnter = output<void>();\n readonly afterLeave = output<void>();\n\n readonly shouldRender = signal(false);\n\n readonly #renderer = inject(Renderer2);\n readonly #el = inject(ElementRef);\n #initialized = false;\n #enterTimer: ReturnType<typeof setTimeout> | null = null;\n #leaveTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor() {\n effect(() => {\n const show = this.show();\n\n // Skip animation on the very first run — sync shouldRender to the initial\n // show value without playing an enter/leave transition. This prevents the\n // component from animating in on page load when it starts as visible.\n if (!this.#initialized) {\n this.#initialized = true;\n this.shouldRender.set(show);\n return;\n }\n\n if (show) {\n this.#enter();\n } else {\n this.#leave();\n }\n });\n }\n\n #enter(): void {\n this.#clearTimers();\n\n const el = this.#el.nativeElement;\n const name = this.name();\n\n // Swap to the enter keyframe and mount in the same change-detection pass, so\n // both are committed to the main thread together and the native engine plays\n // `${name}-enter` from 0% on the freshly-mounted element. Removing a stale\n // leave class first handles a quick hide→show toggle.\n this.#renderer.removeClass(el, `${name}-leave`);\n this.#renderer.addClass(el, `${name}-enter`);\n this.shouldRender.set(true);\n\n // Timer-based completion (no animationend bridge on the background thread).\n // The enter class holds the final frame (animation-fill-mode: both) = the\n // resting state, so it's safe to leave applied until the next leave.\n this.#enterTimer = setTimeout(() => {\n this.#enterTimer = null;\n this.afterEnter.emit();\n }, this.duration());\n }\n\n #leave(): void {\n this.#clearTimers();\n\n const el = this.#el.nativeElement;\n const name = this.name();\n\n this.#renderer.removeClass(el, `${name}-enter`);\n this.#renderer.addClass(el, `${name}-leave`);\n\n // Keep the content mounted until the leave animation finishes, then unmount.\n // shouldRender is a signal, so flipping it runs change detection and flushes\n // the unmount (the leave class stays put; the next enter removes it).\n this.#leaveTimer = setTimeout(() => {\n this.#leaveTimer = null;\n this.shouldRender.set(false);\n this.afterLeave.emit();\n }, this.duration());\n }\n\n #clearTimers(): void {\n if (this.#enterTimer !== null) {\n clearTimeout(this.#enterTimer);\n this.#enterTimer = null;\n }\n if (this.#leaveTimer !== null) {\n clearTimeout(this.#leaveTimer);\n this.#leaveTimer = null;\n }\n }\n}\n","import {\n Component,\n contentChild,\n effect,\n type EmbeddedViewRef,\n inject,\n input,\n output,\n Renderer2,\n TemplateRef,\n viewChild,\n ViewContainerRef,\n type ViewRef,\n} from '@angular/core';\n\ntype ViewEntry<T> = {\n viewRef: EmbeddedViewRef<{ $implicit: T }>;\n item: T;\n leaving: boolean;\n enterTimer: ReturnType<typeof setTimeout> | null;\n leaveTimer: ReturnType<typeof setTimeout> | null;\n};\n\n/**\n * Animates enter/leave of list items using CSS `@keyframes`.\n *\n * Unlike `LynxTransition` (single element), this manages a collection. Items are\n * rendered from a user-provided `<ng-template>`, and the component diffs the list\n * on each change to animate additions and removals.\n *\n * Each item's root element gets a single class toggled: `{name}-enter` on\n * insertion, `{name}-leave` before removal. See `LynxTransition` for why a\n * single `@keyframes` class is used instead of a two-phase CSS `transition` (the\n * two-phase approach can't get a reliable paint gap on Lynx's background thread).\n *\n * @usageNotes\n * ```html\n * <lynx-transition-group [each]=\"items()\" [trackBy]=\"idFn\" name=\"list\" [duration]=\"300\">\n * <ng-template let-item>\n * <view>\n * <text>{{ item.name }}</text>\n * </view>\n * </ng-template>\n * </lynx-transition-group>\n * ```\n *\n * ```css\n * @keyframes list-enter { from { opacity: 0; transform: translateX(30px); } to { opacity: 1; transform: translateX(0); } }\n * @keyframes list-leave { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(-30px); } }\n * .list-enter { animation: list-enter 300ms ease both; }\n * .list-leave { animation: list-leave 300ms ease both; }\n * ```\n */\n@Component({\n selector: 'lynx-transition-group',\n standalone: true,\n template: `<ng-template #anchor />`,\n})\nexport class LynxTransitionGroup<T> {\n readonly each = input<T[]>([]);\n readonly trackBy = input<(item: T) => unknown>((item: any) => item);\n readonly name = input<string>('v');\n readonly duration = input<number>(300);\n\n readonly afterEnter = output<T>();\n readonly afterLeave = output<T>();\n\n readonly itemTemplate = contentChild(TemplateRef);\n\n protected readonly vcr = viewChild.required('anchor', {\n read: ViewContainerRef,\n });\n\n readonly #renderer = inject(Renderer2);\n #entries = new Map<unknown, ViewEntry<T>>();\n #initialized = false;\n\n constructor() {\n effect(() => {\n const items = this.each();\n const trackBy = this.trackBy();\n\n if (!this.#initialized) {\n this.#initialized = true;\n this.#initialRender(items, trackBy);\n return;\n }\n\n this.#reconcile(items, trackBy);\n });\n }\n\n #initialRender(items: T[], trackBy: (item: T) => unknown): void {\n const template = this.itemTemplate();\n if (!template) return;\n for (const item of items) {\n const key = trackBy(item);\n const viewRef = this.vcr().createEmbeddedView(template, {\n $implicit: item,\n });\n this.#entries.set(key, {\n viewRef,\n item,\n leaving: false,\n enterTimer: null,\n leaveTimer: null,\n });\n }\n }\n\n /**\n * Three-phase reconciliation against the trackBy-keyed entry map:\n * 1. Leave pass: items absent from new list get animated out\n * (items that reappear during their leave animation are rescued)\n * 2. Enter pass: new items get created and animated in\n * (retained items get their context updated for change detection)\n * 3. Reorder pass: surviving views are moved to match the new list order via\n * ViewContainerRef.move() (→ Lynx's __InsertElementBefore, which reorders\n * without recreating), while LEAVING views stay pinned in their current\n * slot so they animate out in place instead of jumping to the bottom.\n */\n #reconcile(items: T[], trackBy: (item: T) => unknown): void {\n const newKeys = new Set<unknown>();\n const newKeyOrder: unknown[] = [];\n\n for (const item of items) {\n const key = trackBy(item);\n newKeys.add(key);\n newKeyOrder.push(key);\n }\n\n // Leave: entries not in new list.\n for (const [key, entry] of this.#entries) {\n if (!newKeys.has(key) && !entry.leaving) {\n this.#animateLeave(key, entry);\n } else if (newKeys.has(key) && entry.leaving) {\n // Item reappeared during leave animation — cancel the leave, keep the\n // existing view. This avoids destroying+recreating native elements.\n this.#cancelLeave(key, entry);\n }\n }\n\n // Enter: items in new list but not in entries (or was leaving).\n const template = this.itemTemplate();\n if (!template) return;\n for (const item of items) {\n const key = trackBy(item);\n const existing = this.#entries.get(key);\n\n if (!existing) {\n const viewRef = this.vcr().createEmbeddedView(template, {\n $implicit: item,\n });\n const entry: ViewEntry<T> = {\n viewRef,\n item,\n leaving: false,\n enterTimer: null,\n leaveTimer: null,\n };\n this.#entries.set(key, entry);\n this.#animateEnter(entry);\n // The `else if (!existing.leaving)` false branch is unreachable via\n // normal flow: any entry that was leaving was already rescued in the\n // leave loop above (cancelLeave clears entry.leaving), so by the time\n // we're in the enter loop for a key that IS in newKeys, entry.leaving\n // is always false. Kept as defensive coding for future refactors.\n /* v8 ignore start */\n } else if (!existing.leaving) {\n // Update context for retained items so template bindings reflect\n // the latest item value (handles reference-identity changes).\n existing.item = item;\n existing.viewRef.context.$implicit = item;\n existing.viewRef.markForCheck();\n }\n /* v8 ignore stop */\n }\n\n // Reorder non-leaving views to match new list order.\n this.#reorderViews(newKeyOrder);\n }\n\n /**\n * Reorders mounted views to match the new list order, keeping LEAVING views\n * pinned to their current slot so they animate out where they sit.\n *\n * The naive approach — pack every surviving view into indices 0..N-1 — bubbles\n * a mid-list leaving item to the bottom: to pull the survivors below it up into\n * the low indices, `vcr.move` slides the leaving view past them to the end, so\n * a deleted middle item visibly jumps to the bottom before its leave animation\n * plays there (the reported bug).\n *\n * Instead we build the target order of ALL mounted views: each leaving view\n * keeps the slot it currently occupies, and the survivors fill the remaining\n * slots in `keyOrder`. A pure delete then needs zero moves — the survivors are\n * already in relative order and the leaving item stays put — so it animates out\n * exactly where it was.\n */\n #reorderViews(keyOrder: unknown[]): void {\n const vcr = this.vcr();\n const total = vcr.length;\n if (total === 0) return;\n\n // Reverse-map mounted views → entries so each slot can be classified as a\n // survivor (fillable) or a leaving view (pinned in place).\n const entryByView = new Map<ViewRef, ViewEntry<T>>();\n for (const entry of this.#entries.values()) {\n entryByView.set(entry.viewRef, entry);\n }\n\n // Survivors in their target order — the leaving views are woven in below.\n const survivorViews: ViewRef[] = [];\n for (const key of keyOrder) {\n const entry = this.#entries.get(key);\n // Defensive: any key in `keyOrder` (built from newKeys) has been through\n // the leave/enter pass above, so its entry is present and not leaving.\n // The false branch is unreachable but the guard stays for safety.\n /* v8 ignore next */\n if (entry && !entry.leaving) survivorViews.push(entry.viewRef);\n }\n\n // Weave: a slot currently holding a survivor takes the next survivor in\n // target order; every other slot (a leaving or untracked view) stays put.\n const target: ViewRef[] = [];\n let s = 0;\n for (let i = 0; i < total; i++) {\n const view = vcr.get(i);\n // Defensive guard against a ViewContainerRef returning null for an in-\n // range index (never happens in Angular's Ivy vcr, kept for safety).\n /* v8 ignore next */\n if (!view) continue;\n const entry = entryByView.get(view);\n if (entry && !entry.leaving && s < survivorViews.length) {\n target.push(survivorViews[s++]);\n } else {\n target.push(view);\n }\n }\n\n // Realize the target order. Moving a view to index i only shifts views at\n // >= i, so slots already settled at 0..i-1 stay correct — the pass is stable\n // and skips a move when the view is already in position.\n for (let i = 0; i < target.length; i++) {\n const view = target[i];\n if (vcr.indexOf(view) !== i) {\n vcr.move(view, i);\n }\n }\n }\n\n #animateEnter(entry: ViewEntry<T>): void {\n const rootEl = entry.viewRef.rootNodes[0];\n if (!rootEl) return;\n\n const name = this.name();\n\n // Applied inside the reconcile effect (a change-detection pass), so the\n // class flushes in the same commit that mounts the item — the native engine\n // then plays the ${name}-enter @keyframes from 0%. No requestAnimationFrame\n // (see LynxTransition for why the two-phase transition approach fails here).\n this.#renderer.removeClass(rootEl, `${name}-leave`);\n this.#renderer.addClass(rootEl, `${name}-enter`);\n\n // Timer-based completion (no animationend bridge on the background thread).\n // The enter class holds the final frame (fill: both) = the resting state, so\n // it stays applied until the item leaves; #animateLeave removes it inside the\n // reconcile effect, where a class change flushes reliably.\n entry.enterTimer = setTimeout(() => {\n entry.enterTimer = null;\n this.afterEnter.emit(entry.item);\n }, this.duration());\n }\n\n #animateLeave(key: unknown, entry: ViewEntry<T>): void {\n entry.leaving = true;\n\n const rootEl = entry.viewRef.rootNodes[0];\n if (!rootEl) {\n this.#destroyEntry(key);\n return;\n }\n\n const name = this.name();\n\n this.#renderer.removeClass(rootEl, `${name}-enter`);\n this.#renderer.addClass(rootEl, `${name}-leave`);\n\n // Keep the view mounted until the leave animation finishes, then destroy it.\n entry.leaveTimer = setTimeout(() => {\n entry.leaveTimer = null;\n const item = entry.item;\n this.#destroyEntry(key);\n this.afterLeave.emit(item);\n }, this.duration());\n }\n\n #cancelLeave(_key: unknown, entry: ViewEntry<T>): void {\n // Defensive: cancelLeave is only reached from the leave loop when the\n // entry was actively leaving, which means #animateLeave found a rootEl and\n // scheduled the timer. Both guards' false branches are unreachable via the\n // real code path but stay as safety in case a future refactor changes the\n // preconditions (e.g. leave cancellation from an external caller).\n /* v8 ignore next 4 */\n if (entry.leaveTimer !== null) {\n clearTimeout(entry.leaveTimer);\n entry.leaveTimer = null;\n }\n\n const rootEl = entry.viewRef.rootNodes[0];\n /* v8 ignore next 5 */\n if (rootEl) {\n const name = this.name();\n // Item reappeared mid-leave — drop the leave class so it's visible again.\n this.#renderer.removeClass(rootEl, `${name}-leave`);\n }\n\n entry.leaving = false;\n }\n\n #destroyEntry(key: unknown): void {\n const entry = this.#entries.get(key);\n // The following guards are defensive — every caller looks the entry up\n // from #entries by the same key, and destroyEntry runs after the leave\n // timer fires (which nulls leaveTimer before invoking destroy) OR right\n // from animateLeave's no-rootEl fast path (which never sets either timer).\n // The false branch of `index >= 0` guards against a ViewContainerRef that\n // no longer contains the ViewRef (also never happens in production).\n /* v8 ignore next */\n if (!entry) return;\n\n /* v8 ignore start */\n if (entry.enterTimer !== null) clearTimeout(entry.enterTimer);\n if (entry.leaveTimer !== null) clearTimeout(entry.leaveTimer);\n /* v8 ignore stop */\n\n const index = this.vcr().indexOf(entry.viewRef);\n /* v8 ignore start */\n if (index >= 0) {\n this.vcr().remove(index);\n }\n /* v8 ignore stop */\n this.#entries.delete(key);\n }\n}\n","import type { Animation as LynxJsAnimation } from '@lynx-js/types/main-thread';\n\n/**\n * A no-op animation returned when `animate()` is called on the background\n * thread where `__ElementAnimate` is unavailable. Provides the same API\n * surface as `LynxAnimation` so callers can call `.cancel()`, `.pause()`,\n * `.play()` without crashing — the calls simply do nothing.\n *\n * Fixes: \"Uncaught Error: animate() is only available on the main thread\"\n * in the Go web preview (and any background-thread context).\n *\n * Why needed: In the Lynx dual-thread model, Angular runs on the background\n * thread where __ElementAnimate doesn't exist. Previously, calling\n * element.animate() from a component (e.g. the animations example's \"Tap to\n * pulse\" button) would throw, crashing the Go web preview on the docs site.\n *\n * Approach: Return a silent no-op instead of throwing. This matches how\n * @lynx-js/web-core itself handles __ElementAnimate on the server — it's\n * defined as `() => {}` (a no-op). We mirror that graceful degradation here.\n * Alternatives considered:\n * - Cross-thread bridge via lynx.getCoreContext().dispatchEvent() — correct\n * long-term but complex; LynxBackgroundElement doesn't hold a native ref.\n * - Removing animate() from the example — wrong because it's the primary\n * demonstration of the JS animate API.\n */\nexport class NoopLynxAnimation implements Pick<\n LynxJsAnimation,\n 'id' | 'cancel' | 'pause' | 'play'\n> {\n static #count = 0;\n\n readonly id: string;\n\n constructor() {\n this.id = `__lynx-angular-noop-animation-${NoopLynxAnimation.#count++}`;\n }\n\n play(): void {\n // No-op — animation cannot run on the background thread.\n }\n\n pause(): void {\n // No-op — animation cannot run on the background thread.\n }\n\n cancel(): void {\n // No-op — animation cannot run on the background thread.\n }\n}\n","import type { LynxAnimationOptions } from '../animation/animation';\nimport { NoopLynxAnimation } from '../animation/noop-animation';\nimport type { BaseLynxElement } from './types';\n\n/**\n * Virtual element for the background thread where no native PAPI functions exist.\n * Maintains an in-memory linked-list tree (parent/child/sibling pointers) that\n * mirrors what LynxDocument builds on the main thread. Used by:\n * - Angular's change detection (reads parentNode/nextSibling for view insertion)\n * - querySelector/querySelectorAll (for testing and background-thread lookups)\n * - LynxBackgroundDocument (creates these instead of native elements)\n *\n * Props, styles, classes, and events are stored in Maps/Sets but never sent to\n * native — they exist so component code can read back what it set without\n * crashing, and so the testing library can inspect element state.\n */\nexport class LynxBackgroundElement implements BaseLynxElement {\n isRootPageElement = false;\n tagName = '';\n\n #props = new Map<string, any>();\n #styles = new Map<string, any>();\n #classes = new Set<string>();\n #events = new Map<string, (event: any) => any>();\n #parent: LynxBackgroundElement | null = null;\n #firstChild: LynxBackgroundElement | null = null;\n #lastChild: LynxBackgroundElement | null = null;\n #previousSibling: LynxBackgroundElement | null = null;\n #nextSibling: LynxBackgroundElement | null = null;\n\n setProperty(name: string, value: any): void {\n this.#props.set(name, value);\n }\n setAttribute(name: string, value: any): void {\n this.#props.set(name, value);\n }\n getAttribute(name: string): string | null {\n return this.#props.get(name) ?? null;\n }\n removeAttribute(name: string): void {\n this.#props.delete(name);\n }\n setStyle(key: string, value: unknown): void {\n this.#styles.set(key, value);\n }\n removeStyle(key: string): void {\n this.#styles.delete(key);\n }\n setInlineStyles(inlineStyle: string): void {\n const styles = inlineStyle\n .split(';')\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n for (const s of styles) {\n const [key, value] = s.split(':').map((s) => s.trim());\n this.setStyle(key, value);\n }\n }\n\n insertBefore(\n newChild: LynxBackgroundElement,\n refChild: LynxBackgroundElement | null,\n ): void {\n if (newChild.isRootPageElement) return;\n if (refChild == null) {\n this.appendChild(newChild);\n return;\n }\n if (!refChild.#previousSibling) {\n this.#firstChild = newChild;\n } else {\n refChild.#previousSibling.#nextSibling = newChild;\n }\n newChild.#previousSibling = refChild.#previousSibling;\n refChild.#previousSibling = newChild;\n newChild.#nextSibling = refChild;\n newChild.#parent = this;\n }\n\n appendChild(newChild: LynxBackgroundElement): void {\n if (newChild.isRootPageElement) return;\n if (!this.#firstChild) {\n this.#firstChild = newChild;\n this.#lastChild = newChild;\n } else {\n // Invariant: firstChild and lastChild are always both set or both null.\n // The linked-list bookkeeping in appendChild/insertBefore/remove never\n // leaves one non-null and the other null. This throw is unreachable\n // defensive code and stays as a load-bearing assertion.\n /* v8 ignore next 5 */\n if (!this.#lastChild) {\n throw new Error(\n 'Invariant violation: lastChild is null while firstChild is not null.',\n );\n }\n this.#lastChild.#nextSibling = newChild;\n newChild.#previousSibling = this.#lastChild;\n this.#lastChild = newChild;\n }\n newChild.#parent = this;\n }\n\n addClass(name: string): void {\n this.#classes.add(name);\n }\n removeClass(name: string): void {\n this.#classes.delete(name);\n }\n remove(): void {\n if (this.isRootPageElement) return;\n if (!this.#parent) {\n return;\n }\n if (this.#previousSibling) {\n this.#previousSibling.#nextSibling = this.#nextSibling;\n } else {\n this.#parent.#firstChild = this.#nextSibling;\n }\n if (this.#nextSibling) {\n this.#nextSibling.#previousSibling = this.#previousSibling;\n } else {\n this.#parent.#lastChild = this.#previousSibling;\n }\n this.#nextSibling = null;\n this.#previousSibling = null;\n this.#parent = null;\n }\n\n parentNode(): BaseLynxElement | null {\n return this.#parent;\n }\n nextSibling(): BaseLynxElement | null {\n return this.#nextSibling;\n }\n querySelector(selector: string): BaseLynxElement | null {\n // Depth-first search: check each child, then recurse into its subtree.\n // This matches browser semantics — the first pre-order match wins.\n let child = this.#firstChild;\n while (child) {\n if (child.#matchesSelector(selector)) {\n return child;\n }\n const found = child.querySelector(selector);\n if (found) return found;\n child = child.#nextSibling;\n }\n return null;\n }\n\n querySelectorAll(selector: string): BaseLynxElement[] {\n const results: LynxBackgroundElement[] = [];\n this.#collectMatches(selector, results);\n return results;\n }\n\n /**\n * Collects all descendants (pre-order DFS) that match the selector.\n */\n #collectMatches(selector: string, results: LynxBackgroundElement[]): void {\n let child = this.#firstChild;\n while (child) {\n if (child.#matchesSelector(selector)) {\n results.push(child);\n }\n child.#collectMatches(selector, results);\n child = child.#nextSibling;\n }\n }\n\n /**\n * Supports the CSS selector subset Angular actually needs: tag names, class\n * selectors, ID selectors, and simple attribute selectors — all combinable\n * as a compound selector (e.g. \"view.active[id=foo]\").\n * Combinators (space, >, ~, +) are not supported on the background thread\n * because Angular's renderer doesn't use them at this layer.\n */\n #matchesSelector(selector: string): boolean {\n let remaining = selector.trim();\n\n // Reject any selector that contains a combinator we cannot handle.\n if (/[\\s>~+]/.test(remaining)) return false;\n\n let tagName: string | null = null;\n const classes: string[] = [];\n const attrs: [string, string | null][] = [];\n\n // Optional leading tag name (e.g. \"view\", \"scroll-view\").\n const tagMatch = remaining.match(/^([a-zA-Z][a-zA-Z0-9_-]*)/);\n if (tagMatch) {\n tagName = tagMatch[1];\n remaining = remaining.slice(tagMatch[0].length);\n }\n\n // Parse the rest as class / id / attribute tokens.\n while (remaining.length > 0) {\n const classMatch = remaining.match(/^\\.([a-zA-Z0-9_-]+)/);\n if (classMatch) {\n classes.push(classMatch[1]);\n remaining = remaining.slice(classMatch[0].length);\n continue;\n }\n\n const idMatch = remaining.match(/^#([a-zA-Z0-9_-]+)/);\n if (idMatch) {\n // #id is sugar for [id=\"…\"]\n attrs.push(['id', idMatch[1]]);\n remaining = remaining.slice(idMatch[0].length);\n continue;\n }\n\n // [attr] or [attr=value] or [attr=\"value\"]\n const attrMatch = remaining.match(\n /^\\[([a-zA-Z0-9_-]+)(?:=[\"']?([^\"'\\]]*)[\"']?)?\\]/,\n );\n if (attrMatch) {\n attrs.push([attrMatch[1], attrMatch[2] ?? null]);\n remaining = remaining.slice(attrMatch[0].length);\n continue;\n }\n\n // Unrecognized token — no match.\n return false;\n }\n\n // Empty selector matches nothing.\n if (!tagName && classes.length === 0 && attrs.length === 0) return false;\n\n if (tagName && this.#props.get('tagName') !== tagName) return false;\n\n for (const cls of classes) {\n if (!this.#classes.has(cls)) return false;\n }\n\n for (const [attr, value] of attrs) {\n const stored = this.#props.get(attr);\n if (value === null) {\n // [attr] presence check — element must have the attribute set.\n if (stored === undefined || stored === null) return false;\n } else {\n if (String(stored) !== value) return false;\n }\n }\n\n return true;\n }\n /**\n * Previously threw: `throw new Error('animate() is only available on the\n * main thread')`. This crashed the Go web preview on the docs site because\n * the animations example's (bindtap) handler calls el.nativeElement.animate()\n * which lands here on the background thread. Returning a no-op is safe —\n * the animation won't visually play, but the caller's code (including\n * .cancel() / .pause() / .play() chains) continues without error.\n */\n animate(\n _keyframes: Record<string, string | number>[],\n _options?: number | LynxAnimationOptions,\n ): NoopLynxAnimation {\n // __ElementAnimate is a main-thread PAPI function — it does not exist\n // on the background thread. Return a no-op animation so callers don't\n // crash; the animation simply won't play. This matches web-core's\n // behavior where __ElementAnimate is a no-op in preview environments.\n /* v8 ignore next 6 -- build-time __DEV__ define is false in vitest, so the guarded warn is dead code from the test bundle's point of view. */\n if (__DEV__) {\n console.warn(\n '[angular-lynx] animate() called on background thread — animation will not play. ' +\n 'Use a main-thread script for imperative animations.',\n );\n }\n return new NoopLynxAnimation();\n }\n\n addEventListener(name: string, cb: (event: any) => any): () => void {\n this.#events.set(name, cb);\n return () => {\n this.#events.delete(name);\n };\n }\n}\n","import type { ElementRef } from '../../types/lynx';\n\n// __CreateElement('block', pageId) creates a plain generic FiberElement whose\n// tag happens to be the string \"block\" — it is NOT the native BlockElement\n// C++ subclass (only __CreateBlock() constructs that). A generic element\n// isn't layout-only, so it reaches the native painting pipeline and tries to\n// create a real UI for tag \"block\", which no platform registers a UI class\n// for, crashing with \"block ui not found when create UI\" (native only — the\n// web platform's generic __CreateElement path renders a plain DOM element\n// and never hits this).\n//\n// React Lynx (the production reference) never creates \"block\"/\"if\"/\"for\"\n// tagged elements at all for this purpose. Its equivalent invisible grouping\n// container is __CreateWrapperElement, whose WrapperElement C++ class always\n// sets is_layout_only_ = true unconditionally, which the native painting\n// pipeline skips (ElementContainer::CreatePaintingNode short-circuits on\n// IsLayoutOnly()) — so it never needs a registered native UI at all. It's\n// implemented on both native and the web platform (unlike __CreateBlock).\nexport const createBlockElement = (pageId: number): ElementRef => {\n return __CreateWrapperElement(pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\n/**\n * Native backdrop blur (Lynx 4.0+). Blurs whatever is rendered BEHIND the\n * element, like CSS `backdrop-filter: blur()`, which Lynx doesn't support as a\n * style. On iOS 26+ `blur-effect=\"glass\"` renders Apple's Liquid Glass\n * material. It must be a real `blur-view`: the unknown-tag view fallback would\n * silently ignore every blur attribute and render a plain view with no blur.\n */\nexport const createBlurViewElement = (pageId: number): ElementRef => {\n return __CreateElement('blur-view', pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\n/**\n * Angular uses comment nodes as insertion anchors for dynamic views\n * (createComponent, @if, @for, @switch). Lynx has no comment primitive, so we\n * use an invisible <view> (display:none) — still a valid tree participant that\n * supports __InsertElementBefore / __GetParent / __NextElement, unlike\n * __CreateNonElement which crashes on those.\n *\n * Extracted so both LynxDocument.createComment and createNativeRefByTag build\n * the anchor identically. The display:none is applied here directly (not through\n * a cached setStyle), so a recreated anchor stays invisible even though that\n * style is NOT in the element's recreation style cache.\n */\nexport const createCommentElement = (pageId: number): ElementRef => {\n const element = __CreateView(pageId);\n __AddInlineStyle(element, 'display', 'none');\n return element;\n};\n","import type { ElementRef } from '../../types/lynx';\n\n/**\n * Clay desktop (Windows/macOS) container that renders its subtree into a\n * platform overlay surface ABOVE embedded native views (e.g. a `<webview>`),\n * which normally paint over regular Lynx content. Has no effect on mobile.\n */\nexport const createCoverViewElement = (pageId: number): ElementRef => {\n return __CreateElement('cover-view', pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\nexport const createDefaultElement = (\n tag: string,\n pageId: number,\n): ElementRef => {\n console.warn(`Unknown element tag \"${tag}\". Falling back to view element.`);\n return __CreateView(pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\n// Use __CreateElement('for') instead of __CreateFor() — see create-if-element.ts\n// for the full rationale. Same cross-platform compatibility requirement applies here.\nexport const createForElement = (pageId: number): ElementRef => {\n return __CreateElement('for', pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\n/**\n * Native frame element — embeds a nested Lynx page (similar to HTML iframe).\n * Attributes (src, data, global-props) and events (bindload) are set via\n * standard __SetAttribute/__AddEvent by Angular template bindings.\n */\nexport const createFrameElement = (pageId: number): ElementRef => {\n return __CreateFrame(pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\n// Use __CreateElement('if') instead of __CreateIf().\n// The Lynx web platform only implements the generic __CreateElement and does not\n// expose the specialized __CreateIf/__CreateFor/__CreateBlock globals, so using\n// those would throw at runtime on web. React Lynx (the production reference) also\n// never calls the specialized forms — __CreateElement with a tag string is the\n// idiomatic, cross-platform path.\nexport const createIfElement = (pageId: number): ElementRef => {\n return __CreateElement('if', pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\nexport const createImageElement = (pageId: number): ElementRef => {\n const element = __CreateImage(pageId);\n\n // Lynx <image> has no intrinsic \"natural\" defaults the way the web <img>\n // does — without an explicit mode the native layer falls back to\n // platform-specific behavior (iOS = scaleAspectFill, Android = matrix),\n // which produces inconsistent visuals across devices. Setting these in the\n // creator (rather than relying on per-component config) means every <image>\n // rendered through AngularLynx starts from the same well-defined baseline,\n // matching React Lynx's defaults so behavior is portable across renderers.\n //\n // - mode: 'aspectFit' — preserves aspect ratio inside the box (letterboxes\n // rather than stretching). Mirrors the web's `object-fit: contain` and is\n // the safest default for unknown image dimensions.\n // - fadeIn: true — avoids the harsh \"pop\" when an async-loaded image swaps\n // in over a transparent slot, which is visually jarring on mobile.\n // - loadingPlaceholder: '' — explicitly clears the slot. Without this,\n // some native pools reuse the previous element's placeholder, leaking\n // imagery between recycled list items.\n //\n // Users can still override any of these via [mode]/[fadeIn]/[loadingPlaceholder]\n // bindings, which flow through ngOnChanges → __SetAttribute on the directive.\n __SetConfig(element, {\n mode: 'aspectFit',\n fadeIn: true,\n loadingPlaceholder: '',\n });\n\n return element;\n};\n","import type { ElementRef } from '../../types/lynx';\n\n/**\n * Child of `<text>` that replaces the default ellipsis with custom content\n * when the text is truncated by `text-maxline`. Lynx's text layout only\n * recognizes it by this tag — as a view fallback it would render inline as\n * ordinary content instead of appearing only on truncation.\n */\nexport const createInlineTruncationElement = (pageId: number): ElementRef => {\n return __CreateElement('inline-truncation', pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\n/**\n * XElements — use generic __CreateElement (no dedicated creation functions).\n * Require native-side input plugin to be registered by the app host.\n */\nexport const createInputElement = (\n tag: 'input' | 'textarea',\n pageId: number,\n): ElementRef => {\n const element = __CreateElement(tag, pageId);\n\n // Native Lynx inputs have no intrinsic height or border (unlike HTML inputs),\n // so provide sensible defaults so the element is always visible.\n __AddInlineStyle(element, 'height', tag === 'textarea' ? '80px' : '40px');\n __AddInlineStyle(element, 'border', '1px solid');\n\n return element;\n};\n","import type { ElementRef } from '../../types/lynx';\n\n/**\n * list requires native list-item elements via __CreateElement, not plain views.\n * The native componentAtIndex callback returns this element ID to the engine,\n * which expects a list-item type — using __CreateView crashes the native side.\n */\nexport const createListItemElement = (pageId: number): ElementRef => {\n return __CreateElement('list-item', pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\n/**\n * Native overlay — renders outside the Lynx document flow on a separate\n * rendering layer. Used for modals, bottom sheets, and dialogs that need\n * to cover the entire embedded page. Controlled via the `visible` attribute.\n */\nexport const createOverlayElement = (pageId: number): ElementRef => {\n return __CreateElement('overlay', pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\nexport const createRawTextElement = (value: string): ElementRef => {\n return __CreateRawText(value);\n};\n","import type { ElementRef } from '../../types/lynx';\n\nexport const createRefreshElement = (pageId: number): ElementRef => {\n return __CreateElement('refresh', pageId);\n};\n\nexport const createRefreshHeaderElement = (pageId: number): ElementRef => {\n return __CreateElement('refresh-header', pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\nexport const createScrollCoordinatorElement = (pageId: number): ElementRef => {\n return __CreateElement('scroll-coordinator', pageId);\n};\n\nexport const createScrollCoordinatorHeaderElement = (\n pageId: number,\n): ElementRef => {\n return __CreateElement('scroll-coordinator-header', pageId);\n};\n\nexport const createScrollCoordinatorToolbarElement = (\n pageId: number,\n): ElementRef => {\n return __CreateElement('scroll-coordinator-toolbar', pageId);\n};\n\nexport const createScrollCoordinatorSlotElement = (\n pageId: number,\n): ElementRef => {\n return __CreateElement('scroll-coordinator-slot', pageId);\n};\n\n// Draggable variant of the slot: the slot content can be dragged up/down to\n// fold/unfold the header (toggled by `enable-drag`).\nexport const createScrollCoordinatorSlotDragElement = (\n pageId: number,\n): ElementRef => {\n return __CreateElement('scroll-coordinator-slot-drag', pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\n/**\n * No __SetConfig needed — bounces defaults to true per the API.\n * All scroll-view properties (scroll-orientation, enable-scroll, etc.)\n * are attributes, set via __SetAttribute by Angular template bindings.\n */\nexport const createScrollViewElement = (pageId: number): ElementRef => {\n return __CreateScrollView(pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\n/**\n * SVG is a native Lynx element — the engine parses the SVG content\n * (set via the `content` attribute) on a background thread and renders\n * it as a single native view. No individual SVG child nodes are created.\n */\nexport const createSvgElement = (pageId: number): ElementRef => {\n return __CreateElement('svg', pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\nexport const createTextElement = (pageId: number): ElementRef => {\n return __CreateText(pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\nexport const createTitleBarViewElement = (pageId: number): ElementRef => {\n return __CreateElement('title-bar-view', pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\n/**\n * Native video player (experimental, Lynx 4.1+). Playback is driven by UI\n * methods (`play`, `pause`, `stop`, `seek`) invoked through SelectorQuery, not\n * by attributes — there is no `autoplay`.\n */\nexport const createVideoElement = (pageId: number): ElementRef => {\n return __CreateElement('video', pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\nexport const createViewElement = (pageId: number): ElementRef => {\n return __CreateView(pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\nexport const createViewPagerElement = (pageId: number): ElementRef => {\n return __CreateElement('viewpager', pageId);\n};\n\nexport const createViewPagerItemElement = (pageId: number): ElementRef => {\n return __CreateElement('viewpager-item', pageId);\n};\n","import type { ElementRef } from '../../types/lynx';\n\n/**\n * Native platform web view (WKWebView / android.webkit.WebView) that loads a\n * URL (`src`) or inline HTML (`html`). Unlike `<frame>`, which embeds another\n * Lynx bundle, this hosts real web content.\n */\nexport const createWebViewElement = (pageId: number): ElementRef => {\n return __CreateElement('webview', pageId);\n};\n","import type { ElementRef } from '../types/lynx';\n// Import each creator by its DIRECT file path, NOT the element-creators barrel.\n// The barrel re-exports createListElement/createPageElement, which import\n// LynxElement — routing through it would form a cycle (LynxElement imports this\n// module). The individual creators below import only PAPI globals and types.\nimport { createBlockElement } from './element-creators/create-block-element';\nimport { createBlurViewElement } from './element-creators/create-blur-view-element';\nimport { createCommentElement } from './element-creators/create-comment-element';\nimport { createCoverViewElement } from './element-creators/create-cover-view-element';\nimport { createDefaultElement } from './element-creators/create-default-element';\nimport { createForElement } from './element-creators/create-for-element';\nimport { createFrameElement } from './element-creators/create-frame-element';\nimport { createIfElement } from './element-creators/create-if-element';\nimport { createImageElement } from './element-creators/create-image-element';\nimport { createInlineTruncationElement } from './element-creators/create-inline-truncation-element';\nimport { createInputElement } from './element-creators/create-input-element';\nimport { createListItemElement } from './element-creators/create-list-item-element';\nimport { createOverlayElement } from './element-creators/create-overlay-element';\nimport { createRawTextElement } from './element-creators/create-raw-text-element';\nimport {\n createRefreshElement,\n createRefreshHeaderElement,\n} from './element-creators/create-refresh-element';\nimport {\n createScrollCoordinatorElement,\n createScrollCoordinatorHeaderElement,\n createScrollCoordinatorSlotDragElement,\n createScrollCoordinatorSlotElement,\n createScrollCoordinatorToolbarElement,\n} from './element-creators/create-scroll-coordinator-element';\nimport { createScrollViewElement } from './element-creators/create-scroll-view-element';\nimport { createSvgElement } from './element-creators/create-svg-element';\nimport { createTextElement } from './element-creators/create-text-element';\nimport { createTitleBarViewElement } from './element-creators/create-title-bar-view-element';\nimport { createVideoElement } from './element-creators/create-video-element';\nimport { createViewElement } from './element-creators/create-view-element';\nimport {\n createViewPagerElement,\n createViewPagerItemElement,\n} from './element-creators/create-viewpager-element';\nimport { createWebViewElement } from './element-creators/create-webview-element';\n\n/**\n * Creates a raw native ElementRef for a logical tag, WITHOUT wrapping it in a\n * LynxElement. One tag→`__Create*` dispatch shared by two callers:\n *\n * - `LynxDocument.createElement` — wraps the ref in a LynxElement and sets\n * `tagName`.\n * - `LynxElement.#recreateSubtree` — re-creates a fresh native ref for an\n * element whose painting node was destroyed by a cross-flush removal (Lynx\n * has no API to resurrect a torn-down painting node, so a remounted element\n * must be rebuilt — see that method).\n *\n * Deliberately excludes 'list' and 'page': 'list' returns a `LynxListElement`\n * (a wrapper, not a raw ref) whose children are driven by update-list-info, and\n * 'page' is the singleton root created once by `createRootElement`. Neither is\n * ever recreated, so both are guarded out at the call sites — and importing\n * their creators here would pull `LynxElement` into this module, forming an\n * import cycle (lynx-document already imports LynxElement).\n */\nexport const createNativeRefByTag = (\n tag: string,\n pageId: number,\n text?: string,\n): ElementRef => {\n switch (tag) {\n case 'view':\n return createViewElement(pageId);\n case 'image':\n return createImageElement(pageId);\n case 'text':\n return createTextElement(pageId);\n case 'inline-truncation':\n return createInlineTruncationElement(pageId);\n case 'raw-text':\n return createRawTextElement(text ?? '');\n case 'scroll-view':\n return createScrollViewElement(pageId);\n case 'list-item':\n return createListItemElement(pageId);\n case 'block':\n return createBlockElement(pageId);\n case 'if':\n return createIfElement(pageId);\n case 'for':\n return createForElement(pageId);\n case 'frame':\n return createFrameElement(pageId);\n case 'input':\n case 'textarea':\n return createInputElement(tag, pageId);\n case 'overlay':\n return createOverlayElement(pageId);\n case 'svg':\n return createSvgElement(pageId);\n case 'viewpager':\n return createViewPagerElement(pageId);\n case 'viewpager-item':\n return createViewPagerItemElement(pageId);\n case 'refresh':\n return createRefreshElement(pageId);\n case 'refresh-header':\n return createRefreshHeaderElement(pageId);\n case 'title-bar-view':\n return createTitleBarViewElement(pageId);\n case 'scroll-coordinator':\n return createScrollCoordinatorElement(pageId);\n case 'scroll-coordinator-header':\n return createScrollCoordinatorHeaderElement(pageId);\n case 'scroll-coordinator-toolbar':\n return createScrollCoordinatorToolbarElement(pageId);\n case 'scroll-coordinator-slot':\n return createScrollCoordinatorSlotElement(pageId);\n case 'scroll-coordinator-slot-drag':\n return createScrollCoordinatorSlotDragElement(pageId);\n case 'blur-view':\n return createBlurViewElement(pageId);\n case 'webview':\n return createWebViewElement(pageId);\n case 'video':\n return createVideoElement(pageId);\n case 'cover-view':\n return createCoverViewElement(pageId);\n case 'comment':\n return createCommentElement(pageId);\n // Unknown tags become views rather than passing straight through to\n // __CreateElement(tag) the way React Lynx does. Angular renders every\n // component HOST element (<app-card>, <ng-component>) through this same\n // createElement path, and those must become real layout containers —\n // Lynx has no native UI registered for arbitrary selector names. React has\n // no host elements, so it can afford the pass-through. The cost is that\n // every native Lynx tag needs an explicit case above, or it silently\n // degrades to a view.\n default:\n return createDefaultElement(tag, pageId);\n }\n};\n","import type { ElementRef } from '../types/lynx';\n\n/**\n * Exposed for SSR encode — ssrEncode() needs the raw page ElementRef to walk\n * the native tree. Only set on the main thread after createRootElement().\n *\n * Lives in its own file to avoid a circular import between lynx-element.ts\n * (which reads this) and lynx-document.ts (which writes this and imports\n * LynxElement). Direct mutation via setPageElementRef() keeps the ESM live\n * binding intact for all importers.\n */\nexport let __pageElementRef: ElementRef | null = null;\n\nexport const setPageElementRef = (ref: ElementRef | null): void => {\n __pageElementRef = ref;\n};\n\n/**\n * Unique ID of the root page element — the parent ID every `__Create*` call\n * needs. `LynxElement.#recreateSubtree()` uses this to build a fresh native ref\n * for a remounted element without holding a reference to `LynxDocument` (which\n * would form an import cycle: lynx-document imports LynxElement). Returns 0 if\n * called before the root exists, which never happens during change detection.\n */\nexport const getPageId = (): number =>\n __pageElementRef ? __GetElementUniqueID(__pageElementRef) : 0;\n","// cspell:words ULLONG\n/**\n * Tracks whether we're still inside the native engine's very first\n * LoadTemplate → renderPage call, and lets callers defer work until it's\n * safely finished.\n *\n * Why this exists: a `<list>`'s `componentAtIndex` callback (registered via\n * `__CreateList`) always runs in the main-thread \"Lepus\" QuickJS context,\n * invoked synchronously and reentrantly by native's own list layout pass\n * whenever the list's data changes and a layout tick runs. That reentrancy is\n * fine in steady state (React Lynx relies on it on every scroll). We defer the\n * list's FIRST `update-list-info` + layout-triggering flush out of the initial\n * bootstrap so it doesn't run while still nested inside native's very first\n * `renderPage()` call — React Lynx likewise performs its first list flush from\n * a normal task after the initial render, not synchronously within it. Native\n * performs its own implicit flush once `renderPage()` returns, so nothing is\n * lost by waiting; we only avoid driving a list layout from inside a call\n * frame native hasn't finished unwinding.\n *\n * (Historical note: earlier revisions of this file blamed a stack-depth\n * overflow — Lynx's Lepus context runs with `LEPUS_SetMaxStackSize(ULLONG_MAX)`,\n * so its JS stack-overflow guard is disabled. That turned out NOT to be the\n * first-render crash: the actual trigger was a `WeakSet.has()` call on the\n * `componentAtIndex` path (see create-list-element.ts / lynx-list-element.ts),\n * which crashed identically even from a shallow, freshly-scheduled task. This\n * deferral is retained as correct lifecycle ordering, not as a stack-depth\n * workaround.)\n *\n * Note a Promise/`await` continuation does NOT escape the nesting: LEPUS\n * drains all pending microtasks before a native→JS call frame unwinds, so even\n * `bootstrapApplication`'s `await firstValueFrom(pageReady)` still executes\n * nested inside the original `renderPage()` call, not after it returns. The\n * only genuine escape is a macrotask: `setTimeout` schedules a fresh top-level\n * task that native's message loop invokes only after the current call frame\n * (and all its microtasks) have fully unwound — a primitive this runtime\n * already relies on (see runtime.ts's zoneless CD scheduler polyfill).\n */\n// Module-level so the flag is shared across every element/renderer in the app:\n// there is exactly one initial renderPage() call per page, so a single global\n// latch (rather than per-list state) correctly gates ALL first-render work.\n// Starts true and only ever flips to false once — it never resets, because\n// \"first render\" happens exactly once per bootstrap (HMR re-bootstraps go\n// through the `prev` path in runtime.ts, not this latch).\nlet firstRenderPending = true;\nconst deferredCallbacks: Array<() => void> = [];\n\n/**\n * True until the initial bootstrap render has fully returned. Callers on the\n * re-entrant list path (LynxListElement._processUpdate, LynxRendererFactory2.end)\n * check this to decide whether it's safe to drive a layout-triggering flush\n * now, or whether they must defer — see this file's top doc comment.\n */\nexport const isFirstRenderPending = (): boolean => firstRenderPending;\n\n/**\n * Called exactly once by bootstrapApplication() after Angular's bootstrap\n * resolves. Flips the latch so all subsequent updates run inline, then drains\n * anything parked via runAfterFirstRender() during bootstrap.\n *\n * The drain uses setTimeout(0), NOT queueMicrotask: the parked work (a list's\n * first layout flush) must run on a call stack that has genuinely unwound past\n * native's original renderPage() call. A microtask would still execute nested\n * inside it — LEPUS drains all microtasks before a native→JS frame unwinds —\n * so only a macrotask provides the clean top-level task we need (see this\n * file's top doc comment for the full reasoning).\n */\nexport const markFirstRenderComplete = (): void => {\n firstRenderPending = false;\n if (deferredCallbacks.length === 0) return;\n const callbacks = deferredCallbacks.splice(0);\n setTimeout(() => {\n for (const callback of callbacks) callback();\n }, 0);\n};\n\n/**\n * Runs `callback` immediately if the first render has already completed,\n * or queues it to run once it has (see markFirstRenderComplete()).\n */\nexport const runAfterFirstRender = (callback: () => void): void => {\n if (!firstRenderPending) {\n callback();\n return;\n }\n deferredCallbacks.push(callback);\n};\n\n// True only while a renderer begin()/end() change-detection cycle is executing\n// (set by LynxRendererFactory2). Native element creation/attachment that happens\n// while this is FALSE is happening OUTSIDE Angular's change-detection flush —\n// the canonical case is a lazy-loaded route component instantiated by\n// RouterOutlet DURING navigation, before Angular's next tick. end() only flushes\n// per CD cycle, so such content is committed to the fiber tree yet never laid out\n// or painted until an unrelated later CD flushes (e.g. a tap). The <list> path\n// already guards this (LynxListElement.#scheduleUpdate); scheduleSettleFlush()\n// in lynx-element.ts is the equivalent guard for every other element, and it\n// reads this flag to know a flush is not already coming from end().\nlet insideChangeDetection = false;\n\nexport const setInsideChangeDetection = (value: boolean): void => {\n insideChangeDetection = value;\n};\n\nexport const isInsideChangeDetection = (): boolean => insideChangeDetection;\n","export type LynxEventType =\n | 'bindEvent'\n | 'catchEvent'\n | 'capture-bindEvent'\n | 'capture-catchEvent'\n | 'global-bindEvent';\n\nexport const EVENT_PREFIXES: [string, LynxEventType][] = [\n ['capture-bind', 'capture-bindEvent'],\n ['capture-catch', 'capture-catchEvent'],\n ['global-bind', 'global-bindEvent'],\n ['catch', 'catchEvent'],\n ['bind', 'bindEvent'],\n];\n\nimport type { Element as LynxJsElement } from '@lynx-js/types/main-thread';\n\n/**\n * Uses BaseLynxAnimation (not LynxAnimation) so both the real main-thread\n * implementation and the background-thread NoopLynxAnimation satisfy this\n * interface without requiring inheritance or unsafe casts.\n */\nimport type {\n BaseLynxAnimation,\n LynxAnimationOptions,\n} from '../animation/animation';\n\nexport type BaseLynxElement = Pick<LynxJsElement, 'setAttribute'> & {\n tagName: string;\n setProperty(name: string, value: any): void;\n getAttribute(name: string): string | null;\n removeAttribute(name: string): void;\n setStyle(key: string, value: unknown): void;\n removeStyle(key: string): void;\n setInlineStyles(inlineStyle: string): void;\n insertBefore(\n newChild: BaseLynxElement,\n refChild: BaseLynxElement | null,\n ): void;\n appendChild(newChild: BaseLynxElement): void;\n addClass(name: string): void;\n removeClass(name: string): void;\n remove(): void;\n parentNode(): BaseLynxElement | null;\n nextSibling(): BaseLynxElement | null;\n querySelector(selector: string): BaseLynxElement | null;\n querySelectorAll(selector: string): BaseLynxElement[];\n addEventListener(name: string, cb: (event: any) => any): () => void;\n animate(\n keyframes: Record<string, string | number>[],\n options?: number | LynxAnimationOptions,\n ): BaseLynxAnimation;\n /**\n * Invokes a native UI method on this element (e.g. setValue, scrollTo).\n *\n * Marked optional because it only exists on the main thread: LynxElement\n * implements it via __InvokeUIMethod, while LynxBackgroundElement (used in\n * tests and the background-thread context) does not — UIMethod calls have no\n * meaning outside the native render thread. Callers should use invoke?.() so\n * they become no-ops in test/background environments rather than crashing.\n */\n invoke?(methodName: string, params?: Record<string, unknown>): void;\n};\n","// cspell:words Textish\nimport {\n LynxAnimation,\n type LynxAnimationOptions,\n} from '../animation/animation';\nimport { devStats } from '../devtools/stats';\n// Imported by DIRECT file path (not the ../lynx-document barrel) on purpose:\n// the barrel re-exports LynxDocument, which imports LynxElement — pulling it in\n// here would form an import cycle. These two files import only element-creators\n// and types, so this path is cycle-free.\nimport { createNativeRefByTag } from '../lynx-document/create-native-ref';\nimport { getPageId } from '../lynx-document/page-ref';\nimport {\n isFirstRenderPending,\n isInsideChangeDetection,\n} from '../lynx-render-lifecycle';\nimport type { ElementRef } from '../types/lynx';\nimport {\n type BaseLynxElement,\n EVENT_PREFIXES,\n type LynxEventType,\n} from './types';\n\n/**\n * True if attaching `candidate` under `parent` would form a cycle — i.e.\n * `candidate` is `parent` itself or an ancestor of `parent` in the native tree.\n *\n * Lynx's element APIs do NOT guard against this. `FiberElement::InsertNode`\n * auto-reparents a node that still has a parent, but never checks whether the\n * new parent lives inside the node's own subtree, so it will happily build a\n * self-referential tree. The native layout pass would then walk child→child\n * forever, hanging the main thread until the OS watchdog SIGKILLs the app.\n *\n * Kept purely as defensive coding: a same-tick Angular reorder or re-projection\n * can ask to re-insert an element underneath one of its own former descendants\n * (e.g. two siblings swap and one lands inside the other), and appendChild/\n * insertBefore skip that attach rather than corrupt the tree. NOTE: the\n * `LynxTransition` panel freeze that first surfaced this guard was NOT actually a\n * cycle — it was the old child-\"parking\" mechanism livelocking layout, and that\n * mechanism has since been removed entirely (see #doRemove). The guard stays\n * because the cyclic-attach hazard is genuinely possible and the check is cheap.\n *\n * This is the same ancestor check a browser performs in `insertBefore` (it\n * throws HierarchyRequestError); we return the answer so callers can skip the\n * attach instead of throwing. The walk is bounded by the depth of `parent`, and\n * each step is two cheap native reads — comparable to the tree bookkeeping the\n * attach itself does.\n *\n * Compares by unique ID rather than ref identity: native refs must not be used\n * as map/Set keys (hashing one crashes the Lepus engine — see\n * LynxDocument.createComment), and `__GetParent` is not guaranteed to return the\n * same JS handle across calls.\n */\nconst wouldFormCycle = (parent: ElementRef, candidate: ElementRef): boolean => {\n const candidateId = __GetElementUniqueID(candidate);\n for (let cur: ElementRef | null = parent; cur; cur = __GetParent(cur)) {\n if (__GetElementUniqueID(cur) === candidateId) return true;\n }\n return false;\n};\n\n/**\n * A raw-text leaf or a <text> container — the only elements that carry trimmable\n * inline text. Used to decide when a mutation should queue text normalization.\n */\nconst isTextish = (el: LynxElement): boolean =>\n el.tagName === 'text' || el.tagName === 'raw-text';\n\nexport class LynxElement implements BaseLynxElement {\n /**\n * The native element ref this wrapper currently drives.\n *\n * Exposed through a getter (rather than a public `readonly` field) because\n * `#recreateSubtree()` swaps in a FRESH native ref when this element is\n * remounted after its painting node was destroyed by a cross-flush removal.\n * Everything reads `this.element` through the getter, so it always sees the\n * current ref. Angular, `viewChild`, and `ElementRef.nativeElement` hold the\n * stable WRAPPER (this object), never the raw ref, so the swap is invisible to\n * them. The one snapshot risk — `LynxAnimation`, which copies the ref — is\n * safe because `#doRemove()` cancels animations before a removal, so none\n * survive into a remount.\n */\n #nativeRef: ElementRef;\n get element(): ElementRef {\n return this.#nativeRef;\n }\n tagName = '';\n\n /**\n * When true, this element is the root page element and must not be\n * re-parented (appendChild/insertBefore) or removed from the tree.\n * Angular calls appendChild/remove as part of normal component lifecycle,\n * but the page element is the immutable root — moving or removing it\n * would corrupt the native element tree.\n */\n isRootPageElement = false;\n\n /**\n * Virtual tree tracking — used when parent manages children outside the\n * native element tree (e.g., list manages children via componentAtIndex\n * callbacks rather than __AppendElement)\n */\n _virtualParent: LynxElement | null = null;\n _virtualPrev: LynxElement | null = null;\n _virtualNext: LynxElement | null = null;\n\n // Tracks IDs of animations started on this element via animate().\n // Canceled when the element is destroyed (see #doRemove) to clear stale\n // animation state from Lynx's native element pool — without this, pooled\n // elements retain animation values (e.g. opacity: 0) that poison\n // newly-created elements reusing the slot.\n #activeAnimationIds: string[] = [];\n\n // --- Recreation cache -------------------------------------------------------\n // Lynx destroys an element's native painting node when it is removed in one\n // flush and NOT re-inserted in that same flush (is_move=false in the core),\n // and there is no API to re-create a painting node on a later re-insert. So a\n // remounted element — e.g. content projected through <ng-content> inside an\n // @if that toggles off then on again — would re-attach an empty native view.\n // We fix it the way React Lynx does: recreate a fresh native element on\n // remount. That requires replaying the element's state onto the new ref, so\n // every state-mutating call below MIRRORS into these caches for\n // #recreateSubtree() to replay. Caching is eager (every element, every write)\n // because by the time a removal happens the setter calls are long gone — and\n // event listeners in particular cannot be read back from the native side.\n #attrs = new Map<string, unknown>();\n #id: string | null = null;\n #dataset: Record<string, unknown> = {};\n /** Full space-separated class string, mirroring __SetClasses semantics. */\n #classes = '';\n /** Whole-string inline style set via setInlineStyles (style=\"...\"). */\n #inlineStyleWhole: string | null = null;\n /** Per-key inline styles set via setStyle ([style.x] bindings). */\n #inlineStyleKeys = new Map<string, unknown>();\n #listeners: {\n eventType: LynxEventType;\n eventName: string;\n listener: (event: any) => any;\n }[] = [];\n /**\n * DISPLAYED text of a raw-text element — the positionally edge-trimmed value\n * that is actually painted, and what #recreateSubtree bakes into a rebuilt\n * raw-text (see setInitialText / #setDisplayedText).\n */\n #text: string | undefined;\n /**\n * Collapsed-but-UNTRIMMED text of a raw-text element (the value the renderer\n * produced via collapseWhitespace, before any positional edge-trim). The\n * flush-time normalization pass re-derives #text from this — it must keep the\n * edge spaces #text drops, so a leaf whose position changes (e.g. it stops\n * being the last run in its text) can have a trimmed edge restored. See\n * #normalizeTextRoot / processPendingTextNormalization.\n */\n #rawText: string | undefined;\n /**\n * Ordered child wrappers, kept in lock-step with the native child order by\n * appendChild/insertBefore/#doRemove. This is the CANONICAL wrapper list — the\n * wrappers Angular stores in its LView — which is what recreation must rebuild;\n * never the throwaway wrappers parentNode()/nextSibling()/querySelector mint.\n */\n #children: LynxElement[] = [];\n /** Back-pointer to the JS parent, for O(1) detach from its #children. */\n #jsParent: LynxElement | null = null;\n /**\n * True once this element's native painting node has been destroyed by a\n * genuine (non-move) removal. The next appendChild/insertBefore rebuilds it.\n */\n #paintingDead = false;\n\n /**\n * Elements whose removal has been requested but not yet committed to the\n * native tree. Angular performs a MOVE as detach-then-reinsert: it calls\n * renderer.removeChild(el) immediately followed — in the SAME synchronous\n * change-detection tick — by renderer.insertBefore(el, ...). If remove() tore\n * the element out synchronously, the intermediate detached state could be\n * committed between the two calls; queuing lets a same-tick re-insert cancel\n * the removal so a move is a no-op at the native level.\n *\n * So remove() only QUEUES the element here; `processPendingRemovals()` commits\n * the survivors from `LynxRendererFactory2.end()`, right before\n * `__FlushElementTree()`, so a genuine removal lands in the SAME flush as the\n * rest of the cycle's mutations. (It used to drain in a `queueMicrotask`, which\n * fired AFTER that flush — so a removed subtree lingered in native layout,\n * occupying space until some later cycle happened to flush. That was the\n * \"hidden element leaves a gap\" bug.) A re-insert (appendChild/insertBefore)\n * cancels the queued removal: the element is still natively attached, so\n * __InsertElementBefore/__AppendElement auto-reparents it with its whole\n * subtree intact — matching how React Lynx and the Lynx fiber core\n * (InsertNodeBeforeInternal) handle moves.\n *\n * Keyed by the LynxElement wrapper, not the native ElementRef: Angular hands\n * the SAME wrapper instance (the one stored in its LView) to both removeChild\n * and insertBefore, so wrapper identity is stable across a move — and native\n * refs can't be hashed anyway (doing so crashes the Lepus engine; see\n * LynxDocument.createComment).\n */\n static #pendingRemovals = new Set<LynxElement>();\n\n /**\n * Text-carrying elements whose inline content changed this cycle and need\n * positional whitespace re-derivation. The renderer collapses whitespace but\n * cannot trim edges — whether a run's leading/trailing space is trimmable\n * depends on its POSITION among siblings (see collapseWhitespace in\n * renderer.ts) — so trimming is deferred to a flush-time pass that walks each\n * dirty text's inline-formatting context. Drained by\n * `processPendingTextNormalization()` from `LynxRendererFactory2.end()`, right\n * after removals and before `__FlushElementTree()`, so corrected text lands in\n * the same flush. Keyed by the wrapper, never a native ref (hashing one crashes\n * the Lepus engine — see #pendingRemovals / #byNativeId).\n */\n static #pendingTextNormalization = new Set<LynxElement>();\n\n /**\n * Native-ref → canonical wrapper registry, keyed by the native unique ID.\n *\n * Angular locates an insertion parent for embedded views (@if/@for content)\n * via `renderer.parentNode(anchorComment)`, and Lynx exposes only the raw\n * native parent ref — with no way to map it back to the CANONICAL LynxElement\n * wrapper (the one Angular stores in its LView, whose `#children` recreation\n * walks). parentNode()/nextSibling()/querySelector() therefore used to MINT a\n * fresh throwaway wrapper (empty `#children`); when Angular then inserted the\n * embedded content into that throwaway, the content was adopted into the\n * throwaway's `#children` and was ABSENT from the canonical parent's. It still\n * rendered on first paint (the throwaway drives the same native ref), but\n * `#recreateSubtree()` — which rebuilds a remounted subtree from the canonical\n * `#children` — could never find it, so it vanished on route re-entry (the\n * reuse-strategy remount). This registry lets those methods return the\n * CANONICAL wrapper instead, so every adoption lands in the canonical tree.\n *\n * Keyed by `__GetElementUniqueID` (a number), never the ref itself — hashing a\n * native ref crashes the Lepus engine (see LynxDocument.createComment).\n */\n static #byNativeId = new Map<number, LynxElement>();\n\n /**\n * Returns the canonical wrapper driving `ref`, or a fresh wrapper if none is\n * registered (an element never created through LynxDocument, e.g. a raw query\n * hit). Read-only callers (parentNode/nextSibling/querySelector) use this so\n * they never mint a competing throwaway for an element that already has a\n * canonical wrapper.\n */\n static #canonicalFor(ref: ElementRef): LynxElement {\n const existing = LynxElement.#byNativeId.get(__GetElementUniqueID(ref));\n return existing ?? new LynxElement(ref);\n }\n\n constructor(element: ElementRef) {\n this.#nativeRef = element;\n // Register as the canonical wrapper for this native ref. #canonicalFor()\n // checks the map before constructing, so this never overwrites an existing\n // canonical wrapper with a throwaway.\n LynxElement.#byNativeId.set(__GetElementUniqueID(element), this);\n }\n\n /**\n * Drops this wrapper's current native id from the registry. Called when the\n * native ref is swapped (recreate-on-remount) for the STALE id, and by the\n * renderer's destroyNode when Angular tears the element down, so the registry\n * doesn't retain wrappers for dead native refs.\n */\n deregisterNative(): void {\n const id = __GetElementUniqueID(this.#nativeRef);\n // Only clear if WE are the registered wrapper — a later element that reused\n // this id (native id reuse) must keep its entry.\n if (LynxElement.#byNativeId.get(id) === this) {\n LynxElement.#byNativeId.delete(id);\n }\n }\n\n setProperty(name: string, value: any): void {\n this.setAttribute(name, value);\n }\n\n /**\n * Seeds the cached text for a raw-text element so #recreateSubtree() can\n * rebuild it via __CreateRawText. Called by LynxDocument right after\n * construction — raw-text bakes its text in at creation, so it never flows\n * through a cached setter.\n */\n setInitialText(text: string): void {\n this.#text = text;\n this.#rawText = text;\n }\n\n /**\n * Writes the positionally edge-trimmed DISPLAY text onto the live raw-text\n * element, bypassing setAttribute so it does NOT overwrite #rawText or re-queue\n * this node for normalization. Called only by the flush-time normalization\n * pass. Keeps #text and the recreation attr cache (#attrs['text']) in sync with\n * the displayed value so a remounted raw-text rebuilds with the correct text.\n */\n #setDisplayedText(displayed: string): void {\n if (this.#text === displayed) return;\n __SetAttribute(this.element, 'text', displayed);\n this.#text = displayed;\n this.#attrs.set('text', displayed);\n }\n setAttribute(name: string, value: any): void {\n if (name === 'class') {\n // Use __SetClasses (not __AddClass) because setAttribute replaces the\n // entire class attribute with a space-separated list. __AddClass treats\n // its argument as a single class name — passing 'foo bar baz' would set\n // the literal class 'foo bar baz' rather than three separate classes,\n // so no CSS rule would ever match. __SetClasses correctly parses the\n // space-separated list. This matches how React Lynx handles className.\n __SetClasses(this.element, value ?? '');\n this.#classes = value ?? '';\n } else if (name === 'style') {\n this.setInlineStyles(value);\n } else if (name === 'id') {\n __SetID(this.element, value);\n this.#id = value ?? null;\n } else if (name.startsWith('data-')) {\n const data: Record<string, any> = {};\n const key = name.slice(5);\n data[key] = value;\n __SetDataset(this.element, data);\n this.#dataset[key] = value;\n } else {\n __SetAttribute(this.element, name, value);\n // Mirror for recreation. removeAttribute() funnels here with value=null,\n // so drop the key then rather than replaying a cleared attribute. raw-text\n // carries its text via the 'text' attribute (renderer.setValue) — keep\n // #text in sync so a rebuilt raw-text bakes the current text in.\n if (value == null) {\n this.#attrs.delete(name);\n } else {\n this.#attrs.set(name, value);\n }\n if (this.tagName === 'raw-text' && name === 'text') {\n // The renderer feeds this the COLLAPSED-but-untrimmed value (see\n // renderer.setValue → collapseWhitespace). Stash it as the raw source and\n // queue the enclosing text for the positional edge-trim pass; #text is\n // the provisional display until that pass corrects it (#setDisplayedText).\n const text = value == null ? undefined : String(value);\n this.#text = text;\n this.#rawText = text;\n LynxElement.#enqueueTextNormalization(this);\n }\n }\n }\n\n getAttribute(name: string) {\n return __GetAttributeByName(this.element, name) as string;\n }\n\n removeAttribute(name: string): void {\n this.setAttribute(name, null);\n }\n\n setStyle(key: string, value: unknown): void {\n __AddInlineStyle(this.element, key, value);\n this.#inlineStyleKeys.set(key, value);\n }\n removeStyle(key: string): void {\n __AddInlineStyle(this.element, key, null);\n this.#inlineStyleKeys.delete(key);\n }\n setInlineStyles(inlineStyle: string): void {\n __SetInlineStyles(this.element, inlineStyle);\n this.#inlineStyleWhole = inlineStyle;\n }\n\n insertBefore(newChild: LynxElement, refChild: LynxElement | null): void {\n if (newChild.isRootPageElement) return;\n // A queued removal immediately followed by a re-insert is an Angular MOVE —\n // cancel the removal so the element keeps its children. It is still natively\n // attached to its old parent, so __InsertElementBefore auto-reparents the\n // whole subtree (see #pendingRemovals).\n newChild.#cancelPendingRemoval();\n // If the child was genuinely removed in a PREVIOUS cycle its native painting\n // node is gone — rebuild a fresh native element + subtree before re-attaching\n // (see #recreateSubtree). A same-tick move was canceled just above and is\n // never painting-dead, so the fast move path pays only a boolean check.\n newChild.#recreateIfDead();\n if (refChild == null) {\n this.appendChild(newChild);\n } else {\n // Never insert an element into its own subtree — Lynx would build a cyclic\n // native tree and hang the layout pass (see wouldFormCycle). Skipping is\n // safe: a cyclic insert is a corrupt request, and leaving newChild where it\n // is beats freezing the app.\n if (wouldFormCycle(this.element, newChild.element)) return;\n __InsertElementBefore(this.element, newChild.element, refChild.element);\n this.#adoptChild(newChild, refChild);\n if (isTextish(this) || isTextish(newChild)) {\n LynxElement.#enqueueTextNormalization(newChild);\n }\n }\n }\n\n appendChild(newChild: LynxElement): void {\n if (newChild.isRootPageElement) return;\n // See insertBefore: cancel a pending removal so a move keeps its subtree,\n // then rebuild the child if its painting node was destroyed in a prior cycle.\n newChild.#cancelPendingRemoval();\n newChild.#recreateIfDead();\n // Guard against a cycle-forming attach (see wouldFormCycle) — the same hang\n // insertBefore protects against.\n if (wouldFormCycle(this.element, newChild.element)) return;\n __AppendElement(this.element, newChild.element);\n this.#adoptChild(newChild);\n // Attaching a run to (or as) a text shifts inline layout — re-derive the\n // enclosing context's edge whitespace at the next flush (see\n // #pendingTextNormalization). Enqueue newChild; the pass resolves it to the\n // outermost text root, so this covers both a run joining a text and a text\n // root being attached elsewhere.\n if (isTextish(this) || isTextish(newChild)) {\n LynxElement.#enqueueTextNormalization(newChild);\n }\n }\n\n /**\n * Records `newChild` in this element's ordered `#children`, first unlinking it\n * from its previous JS parent (mirroring the native auto-reparent that\n * __AppendElement/__InsertElementBefore perform). Keeping `#children` in\n * lock-step with the native child order is what lets #recreateSubtree() rebuild\n * a remounted subtree in the correct order. `refChild` positions the insert;\n * when omitted the child is appended.\n */\n #adoptChild(newChild: LynxElement, refChild?: LynxElement): void {\n const prev = newChild.#jsParent;\n if (prev) {\n const i = prev.#children.indexOf(newChild);\n // Defensive: if newChild is tracked as a child of `prev`, indexOf always\n // finds it. The i < 0 branch would only fire on a bookkeeping mismatch\n // that shouldn't happen through the public API.\n /* v8 ignore next */\n if (i >= 0) prev.#children.splice(i, 1);\n }\n newChild.#jsParent = this;\n if (refChild) {\n const idx = this.#children.indexOf(refChild);\n // Defensive: refChild always sits in #children when it's used as an\n // anchor for insertBefore. If a caller passes a foreign refChild, fall\n // back to appending at the tail rather than throwing.\n /* v8 ignore next */\n this.#children.splice(idx < 0 ? this.#children.length : idx, 0, newChild);\n } else {\n this.#children.push(newChild);\n }\n }\n\n addClass(name: string): void {\n __AddClass(this.element, name);\n // Keep the cached class string in sync (deduped) so recreation replays the\n // full class list in one __SetClasses.\n const set = new Set(this.#classes.split(/\\s+/).filter(Boolean));\n set.add(name);\n this.#classes = [...set].join(' ');\n }\n\n /**\n * Lynx has no __RemoveClass PAPI — we must get current classes, filter,\n * and set back. This is O(n) per class removal but class lists on Lynx\n * elements are typically small (1-5 classes for scope/component styling).\n */\n removeClass(name: string): void {\n const classes = __GetClasses(this.element).filter((c) => c !== name);\n const joined = classes.join(' ');\n __SetClasses(this.element, joined);\n this.#classes = joined;\n }\n\n /**\n * Requests removal of this element. Two removal paths:\n * 1. Virtual parent (list) → delegate to removeVirtualChild() SYNCHRONOUSLY,\n * which updates the JS linked list and schedules an update-list-info diff.\n * Does NOT call __RemoveElement — list item removal is managed exclusively\n * through update-list-info's removeAction (calling both would double-remove\n * and crash). This is never part of an Angular move, so it is not deferred.\n * 2. Normal parent → QUEUED and committed at the end of the change-detection\n * cycle (see #pendingRemovals / commitPendingRemovals). If a re-insert\n * follows in the same cycle it is a move and gets canceled; otherwise\n * #doRemove() detaches from the native tree.\n */\n remove() {\n if (this.isRootPageElement) return;\n // Count the removal request on the synchronous path. `__PROFILE__` is a\n // build-time `define` — read it here rather than from the deferred drain (in\n // tests a leaked drain can run after the module's defines are gone, throwing\n // \"__PROFILE__ is not defined\"). Vitest's config sets it to `false`, so\n // the increment is dead code from the test bundle's point of view.\n /* v8 ignore next */\n if (__PROFILE__) devStats.elementRemoved++;\n if (this._virtualParent) {\n const vp = this._virtualParent as any;\n if (typeof vp.removeVirtualChild === 'function') {\n vp.removeVirtualChild(this);\n }\n return;\n }\n LynxElement.#pendingRemovals.add(this);\n }\n\n /**\n * Commits every queued genuine removal. Called by `LynxRendererFactory2.end()`\n * once per change-detection cycle, BEFORE `__FlushElementTree()`, so the\n * `__RemoveElement` calls are committed to the main thread in the same flush as\n * the cycle's other mutations (see #pendingRemovals for why the timing\n * matters). Any element that was re-inserted (a move) has already removed\n * itself from the set via #cancelPendingRemoval, so only genuine destroys\n * remain.\n */\n static commitPendingRemovals(): void {\n if (LynxElement.#pendingRemovals.size === 0) return;\n const items = [...LynxElement.#pendingRemovals];\n LynxElement.#pendingRemovals.clear();\n for (const el of items) {\n el.#doRemove();\n }\n }\n\n /**\n * Queues `el` for flush-time whitespace normalization (see\n * #pendingTextNormalization). Deduped, so a node touched by both a text update\n * and an attach in the same cycle is processed once, against the final tree.\n */\n static #enqueueTextNormalization(el: LynxElement): void {\n LynxElement.#pendingTextNormalization.add(el);\n }\n\n /**\n * Re-derives displayed whitespace for every text touched this cycle. Each dirty\n * node is resolved to the OUTERMOST enclosing <text>: a nested <text> is inline\n * — it shares one inline-formatting-context with the surrounding raw-text, like\n * an HTML <span> — so the whole subtree is trimmed as a single run of text.\n * Called by `processPendingTextNormalization()` from `end()` /\n * `scheduleSettleFlush`, after removals and before the flush.\n */\n static commitPendingTextNormalization(): void {\n if (LynxElement.#pendingTextNormalization.size === 0) return;\n const dirty = [...LynxElement.#pendingTextNormalization];\n LynxElement.#pendingTextNormalization.clear();\n const roots = new Set<LynxElement>();\n for (const node of dirty) {\n let root = node;\n while (root.#jsParent && root.#jsParent.tagName === 'text') {\n root = root.#jsParent;\n }\n // Skip stray enqueues (not inside a text) and subtrees torn down this\n // cycle — their native refs are gone (see #doRemove / #paintingDead).\n if (!isTextish(root) || root.#paintingDead) continue;\n roots.add(root);\n }\n for (const root of roots) {\n LynxElement.#normalizeTextRoot(root);\n }\n }\n\n /**\n * Trims the edges of one text inline-formatting context. Collects its raw-text\n * leaves in document order, strips the leading space of the first NON-EMPTY\n * leaf and the trailing space of the last NON-EMPTY leaf, and collapses a space\n * shared across an inter-run boundary to a single space — matching how a\n * browser lays out `white-space: normal` text. A single-leaf context (ordinary\n * prose) reduces to trim-both.\n *\n * \"Non-empty\" matters because a leaf can legitimately collapse to '' (a\n * whitespace-only interpolated or `@for` run — collapseWhitespace shrinks it to\n * a single space, which the inter-run branch below can then consume entirely).\n * Such a leaf contributes no inline box, so it must be transparent: it cannot\n * claim an edge trim in place of the real first/last run, and it must not\n * erase `pendingSpace` — the earlier run's trailing space is still \"pending\"\n * across it, or the run after would keep its own leading space too and produce\n * a double space (this was a real bug: `['A ', ' ', ' B']` rendered \"A B\").\n */\n static #normalizeTextRoot(root: LynxElement): void {\n // A raw-text is itself a leaf. Its parent is not always a <text> (a raw-text\n // painted outside a <text> is unsupported by Lynx and never renders, but\n // this keeps the pass's own contract — \"a single-leaf context reduces to\n // trim-both\" — true for every root it is handed).\n // The caller (commitPendingTextNormalization) resolves to the outermost\n // text root before enqueuing, so in practice `root` is always a <text>\n // (raw-text under a text becomes the parent). The raw-text and\n // empty-leaves branches are defensive; kept to preserve the pass's\n // single-context contract if a future call path enqueues a bare leaf.\n /* v8 ignore start */\n const leaves: LynxElement[] = root.tagName === 'raw-text' ? [root] : [];\n if (root.tagName === 'text') {\n LynxElement.#collectRawTextLeaves(root, leaves);\n }\n if (leaves.length === 0) return;\n /* v8 ignore stop */\n\n const displayed: string[] = [];\n let pendingSpace = false;\n let seenNonEmpty = false;\n for (const leaf of leaves) {\n // #rawText is seeded on every raw-text via setInitialText or the 'text'\n // attribute path; the `?? ''` fallback covers a synthesized leaf without\n // a raw source, which never happens in practice.\n /* v8 ignore next */\n let text = leaf.#rawText ?? '';\n if (!seenNonEmpty) {\n // Still at the leading edge of the whole context — every leaf up to and\n // including the first non-empty one is eligible for the leading trim.\n text = text.replace(/^ /, '');\n } else if (pendingSpace && text.startsWith(' ')) {\n // A space on both sides of an inter-run boundary collapses to one (kept\n // on the earlier run), as a browser would across adjacent inline boxes.\n text = text.slice(1);\n }\n displayed.push(text);\n if (text.length > 0) {\n seenNonEmpty = true;\n pendingSpace = text.endsWith(' ');\n }\n // An empty leaf carries `pendingSpace`/`seenNonEmpty` forward unchanged —\n // it is not the edge and not a boundary in its own right.\n }\n // Trailing edge: strip one trailing space from the LAST non-empty leaf. Done\n // as a second pass (not inline above) because which leaf is \"last\" can only\n // be known once an empty tail has been ruled out.\n for (let i = displayed.length - 1; i >= 0; i--) {\n if (displayed[i].length === 0) continue;\n displayed[i] = displayed[i].replace(/ $/, '');\n break;\n }\n for (let i = 0; i < leaves.length; i++) {\n leaves[i].#setDisplayedText(displayed[i]);\n }\n }\n\n /**\n * Collects the raw-text leaves under `el` in document order, descending through\n * nested <text> (inline) and treating any other element as opaque. Walks the\n * canonical #children — never __GetChildren, whose throwaway wrappers would\n * break the recreation registry and background/testing.\n */\n static #collectRawTextLeaves(el: LynxElement, out: LynxElement[]): void {\n for (const child of el.#children) {\n if (child.tagName === 'raw-text') {\n out.push(child);\n } else if (child.tagName === 'text') {\n LynxElement.#collectRawTextLeaves(child, out);\n }\n }\n }\n\n /**\n * Cancels a queued removal because the element is being re-inserted (a move).\n * A no-op if the element was not pending (a plain append/insert of a fresh\n * element).\n */\n #cancelPendingRemoval(): void {\n LynxElement.#pendingRemovals.delete(this);\n }\n\n /**\n * Commits a genuine removal (no re-insert canceled it):\n * __RemoveElement detaches from the native element tree. Note: __RemoveElement\n * does NOT free the element's native pool slot — there is no __ReleaseElement\n * in Lynx's PAPI.\n */\n #doRemove(): void {\n const parent = this.parentNode();\n if (!parent) {\n return;\n }\n // Cancel all active animations and reset animated properties before removal.\n // Lynx's native element pool reuses elements — if an animation is still\n // running (or fill:'forwards' persists the final frame), the stale animation\n // state transfers to whatever new element reuses this pool slot.\n // Canceling + resetting inline styles ensures the pooled element returns clean.\n // Wire protocol constant 3 = ANIMATION_CANCEL (from animation.ts).\n // Canceling a completed animation is harmless — a no-op at the native level.\n for (const id of this.#activeAnimationIds) {\n __ElementAnimate(this.element, [3, id]);\n }\n if (this.#activeAnimationIds.length > 0) {\n // Cancel clears the animation's active effect, but Lynx may leave\n // residual computed values on the element (observed: opacity stays at\n // the initial keyframe value 0 after cancel). Nulling the inline styles\n // forces a full reset so the pooled element has no lingering overrides.\n __AddInlineStyle(this.element, 'opacity', null);\n __AddInlineStyle(this.element, 'transform', null);\n this.#activeAnimationIds.length = 0;\n }\n // Remove the whole subtree in one shot — no \"parking\" of children elsewhere.\n // This runs ONLY for a genuine destroy: a move (remove-then-reinsert in the\n // same tick) is canceled before it reaches here (see #pendingRemovals), so a\n // moved element keeps its children and is reparented intact.\n //\n // Earlier revisions detached this element's children first and stashed them\n // somewhere safe (the page root, then a `display:none` holder) so that\n // projected content owned by a SURVIVING component could be re-projected after\n // an ancestor `@if` toggled off. That machinery caused two on-device watchdog\n // SIGKILLs: moving a parked child out of the laid-out page root into a deep\n // descendant on re-show livelocked the layout pass, and children of a\n // permanently-destroyed element leaked into the holder forever until tearing\n // that tree down at shell-destroy blew the 5s watchdog. Removing the subtree\n // as a unit sidesteps both — nothing is ever stranded or accumulated.\n //\n // Component-wrapped projection (e.g. `@if(open){ <view><ng-content/></view> }`,\n // the accordion/collapsible shape) survives a re-show via recreate-on-remount:\n // the consumer's projected content is recycled with this wrapper here, its\n // painting node dies, and the next re-insert rebuilds it from cache (see\n // #recreateSubtree). That is why we mark the whole subtree painting-dead just\n // below rather than \"parking\" the children somewhere to keep them alive.\n __RemoveElement((parent as LynxElement).element, this.element);\n // The native painting nodes of this element and its entire subtree are now\n // gone (Lynx tears them down for a non-move removal — is_move=false). Unlink\n // from the JS parent and mark the subtree painting-dead so the next re-insert\n // rebuilds fresh native elements instead of re-attaching empty ones.\n const jsParent = this.#jsParent;\n if (jsParent) {\n const i = jsParent.#children.indexOf(this);\n // Defensive: jsParent's #children was kept in lock-step with the native\n // tree via #adoptChild, so indexOf always finds `this` here.\n /* v8 ignore next */\n if (i >= 0) jsParent.#children.splice(i, 1);\n this.#jsParent = null;\n }\n this.#markPaintingDead();\n // Removing a run from a surviving text shifts its edges (a middle run can\n // become the new last run), so re-derive the former parent's context. Uses\n // jsParent captured above, before #jsParent was nulled.\n if (jsParent && isTextish(this)) {\n LynxElement.#enqueueTextNormalization(jsParent);\n }\n }\n\n /**\n * Recursively flags this element and every cached descendant painting-dead,\n * mirroring the native painting-node cascade when a subtree is removed. The\n * caches themselves are kept intact — they are exactly what #recreateSubtree\n * replays onto fresh refs.\n */\n #markPaintingDead(): void {\n this.#paintingDead = true;\n for (const child of this.#children) {\n child.#markPaintingDead();\n }\n }\n\n /**\n * Rebuilds this element from its caches if its painting node was destroyed by\n * a genuine removal. A no-op otherwise, so the common append/move path pays\n * only a single boolean check.\n */\n #recreateIfDead(): void {\n if (!this.#paintingDead) return;\n this.#recreateSubtree();\n // Recreation is the one native-mutating path that bypasses\n // LynxDocument.createElement (it calls createNativeRefByTag directly), so it\n // is also the one place that builds fresh native refs WITHOUT arming the\n // out-of-cycle safety-net flush. A route re-attach (RouterOutlet re-insert)\n // runs OUTSIDE a begin()/end() cycle, so without this the rebuilt subtree\n // would sit unflushed until some unrelated later CD. scheduleSettleFlush is\n // self-guarding (a no-op inside a CD cycle — the @if-toggle path — and during\n // first render) and coalesced, so nested remounts still cost one flush.\n scheduleSettleFlush();\n }\n\n /**\n * * Re-creates a fresh native element for this wrapper and its whole subtree,\n * * replaying the cached state onto the new refs. This mirrors React Lynx's\n * * \"recreate on remount\": Lynx cannot resurrect a painting node torn down by a\n * * cross-flush removal, so re-attaching the stale ref would render empty. Runs\n * * depth-first, bottom-up — children are rebuilt first and re-appended, so the\n * * new parent ref owns fresh, live child refs.\n * *\n * * 'list' and 'page' are never rebuilt: a list is a LynxListElement whose\n * * children are driven by update-list-info (not __AppendElement), and the page\n * * is the immutable singleton root. Both just clear the flag. (A consequence:\n * * a <list> nested directly inside a toggling @if remounts empty — a pre-existing\n * * limitation, not a regression, since its ref cannot be rebuilt from a raw tag.)\n * v8 ignore start -- reached only when a same-flush move is later expanded into a real removal + reinsertion; the on-device flow is exercised by teardown.test.ts's higher-level appendChild/remove regressions and by the route-reuse detach/reattach cycle. The individual attribute/style/class replay branches inside require reproducing every combination of a live element's cached state, which the unit-test fake-native tree doesn't drive end-to-end.\n */\n #recreateSubtree(): void {\n if (!this.#paintingDead) return;\n this.#paintingDead = false;\n if (this.isRootPageElement || this.tagName === 'list') return;\n\n // Swapping the native ref changes this wrapper's unique id — move its\n // registry entry from the stale (destroyed) ref's id to the fresh one so\n // parentNode()/#canonicalFor keep resolving to this canonical wrapper.\n this.deregisterNative();\n const fresh = createNativeRefByTag(this.tagName, getPageId(), this.#text);\n this.#nativeRef = fresh;\n LynxElement.#byNativeId.set(__GetElementUniqueID(fresh), this);\n\n if (this.tagName === 'raw-text') {\n // #text may be stale: normalization is SKIPPED for a subtree while it is\n // #paintingDead (see commitPendingTextNormalization), so a multi-run text\n // removed and re-shown in the same cycle can still be carrying its\n // pre-removal (or even never-yet-trimmed) displayed value here. Queue this\n // leaf so the next drain re-derives the correct positional trim from\n // #rawText — cheap even when unchanged, since #setDisplayedText no-ops.\n // #jsParent is untouched by removal/recreate (only the actually-removed\n // node's own link is cleared — see #doRemove), so root-resolution still\n // finds the right enclosing <text>, whose #paintingDead was already\n // cleared above by the time this leaf's own recreate runs (recreate flips\n // the flag before recursing into children).\n LynxElement.#enqueueTextNormalization(this);\n }\n\n if (this.#id != null) __SetID(fresh, this.#id);\n // Apply the dataset in one call so recreation is order- and merge-agnostic.\n if (Object.keys(this.#dataset).length > 0) {\n __SetDataset(fresh, this.#dataset);\n }\n for (const [name, value] of this.#attrs) {\n __SetAttribute(fresh, name, value);\n }\n if (this.#classes) __SetClasses(fresh, this.#classes);\n // Whole-string styles first, then per-key overrides — same order as the\n // original setAttribute('style') vs [style.x] application.\n if (this.#inlineStyleWhole != null) {\n __SetInlineStyles(fresh, this.#inlineStyleWhole);\n }\n for (const [key, value] of this.#inlineStyleKeys) {\n __AddInlineStyle(fresh, key, value);\n }\n for (const { eventType, eventName, listener } of this.#listeners) {\n __AddEvent(fresh, eventType, eventName, {\n type: 'worklet',\n value: listener,\n });\n }\n for (const child of this.#children) {\n child.#recreateSubtree();\n __AppendElement(fresh, child.element);\n }\n }\n /* v8 ignore stop */\n\n /**\n * Returns the parent element. For list children, the virtual parent (the JS\n * LynxListElement) is returned instead of the native parent — this maintains\n * the illusion that list children are parented by the list even though they\n * may not be __AppendElement'd to the native list yet (lazy append in\n * componentAtIndex).\n */\n parentNode(): LynxElement | null {\n if (this._virtualParent) return this._virtualParent;\n const parent = __GetParent(this.element);\n if (!parent) return null;\n // Return the CANONICAL wrapper, not a throwaway: Angular uses this as the\n // insertion parent for embedded-view (@if/@for) content, and adopting that\n // content into a throwaway's #children (instead of the canonical parent's)\n // is exactly what made it vanish on route re-entry (see #byNativeId).\n return LynxElement.#canonicalFor(parent);\n }\n\n nextSibling(): LynxElement | null {\n // If in a virtual tree, use virtual sibling tracking\n if (this._virtualParent) return this._virtualNext;\n const nextSibling = __NextElement(this.element);\n if (!nextSibling) return null;\n // Return the canonical wrapper (see #canonicalFor / parentNode). Angular can\n // hand a nextSibling() result back as a refChild to insertBefore, so it must\n // be the same wrapper whose #children recreation walks — never a throwaway.\n return LynxElement.#canonicalFor(nextSibling);\n }\n\n querySelector(selector: string): LynxElement | null {\n const element = __QuerySelector(this.element, selector, {});\n if (!element) return null;\n // Canonical wrapper, not a throwaway: a caller that mutates the query result\n // (appendChild, setAttribute) must drive the SAME wrapper the rest of the\n // tree references, or those mutations are lost on the next remount.\n return LynxElement.#canonicalFor(element);\n }\n querySelectorAll(selector: string): LynxElement[] {\n // Same canonical-wrapper requirement as querySelector, per hit.\n return __QuerySelectorAll(this.element, selector, {}).map((e) =>\n LynxElement.#canonicalFor(e),\n );\n }\n /**\n * Invokes a native UI method on this element by name.\n *\n * This is needed because some Lynx native elements expose behavior only\n * through UIMethod calls and have no corresponding @LynxProp handler. The\n * most common case is input/textarea text updates: the native\n * LynxUIBaseInput class has no @LynxProp for \"value\", so __SetAttribute\n * is a no-op for changing the displayed text after user interaction. The\n * setValue UIMethod is the only way to programmatically update the live\n * text.\n *\n * The result callback is intentionally empty. Callers that need a result\n * (e.g. getValue, boundingClientRect) should use MainThreadElement.invoke(),\n * which returns a Promise. This method covers fire-and-forget cases like\n * setValue where only the side-effect matters.\n */\n invoke(methodName: string, params?: Record<string, unknown>): void {\n __InvokeUIMethod(this.element, methodName, params ?? {}, () => {});\n }\n\n animate(\n keyframes: Record<string, string | number>[],\n options?: number | LynxAnimationOptions,\n ): LynxAnimation {\n const normalizedOptions =\n typeof options === 'number' ? { duration: options } : (options ?? {});\n const anim = new LynxAnimation(this.element, keyframes, normalizedOptions);\n // Track the animation so remove() can cancel it before the element\n // returns to the native pool. Without this, the pool slot retains\n // stale animation state (e.g. opacity stuck at the FROM keyframe).\n this.#activeAnimationIds.push(anim.id);\n return anim;\n }\n\n /**\n * Angular's renderer.listen() calls this with event names like 'bindtap',\n * 'catchtouchstart', 'bindscroll', etc. We strip the Lynx event prefix\n * (bind/catch/capture-bind/capture-catch) to extract the native event name\n * and determine the event type for __AddEvent.\n * Events that don't match any prefix (e.g. DOM-style 'click') are silently\n * ignored — Lynx has no equivalent event system for arbitrary names.\n */\n addEventListener(name: string, cb: (event: any) => any) {\n let eventName = '';\n let eventType: LynxEventType | undefined;\n\n for (const [prefix, type] of EVENT_PREFIXES) {\n if (name.startsWith(prefix)) {\n eventName = name.slice(prefix.length);\n eventType = type;\n break;\n }\n }\n\n if (!eventType) {\n return () => {};\n }\n\n /**\n * Lynx's background-thread event objects don't implement the DOM-style\n * stopPropagation()/preventDefault() methods. Lynx only exposes them in\n * main-thread scripts, yet its own .d.ts declares them on every event — so\n * TypeScript never catches the gap. Angular templates (and Angular's own\n * listener wrapper, which calls preventDefault() whenever a handler returns\n * false) assume every event has them, so a handler like\n * `$event.stopPropagation()` throws \"not a function\" at runtime.\n *\n * Propagation in Lynx is controlled statically by the bind/catch event\n * prefix, and there is no runtime default to prevent, so we inject no-op\n * shims — only when missing, to avoid clobbering the real methods that DO\n * exist in main-thread-script contexts. This gives Angular DOM parity:\n * handlers that call these methods run without crashing. We augment the\n * event before invoking cb (Angular's wrapper may call preventDefault()\n * during that call) and return cb's result (the return-false path relies\n * on it). Mirrors React Lynx's addEventMethodsIfNeeded.\n */\n const listener = (event: any) => {\n if (event && typeof event === 'object') {\n if (typeof event.stopPropagation !== 'function') {\n event.stopPropagation = () => {};\n }\n if (typeof event.preventDefault !== 'function') {\n event.preventDefault = () => {};\n }\n if (typeof event.stopImmediatePropagation !== 'function') {\n event.stopImmediatePropagation = () => {};\n }\n }\n const result = cb(event);\n // Native events are delivered straight to this callback by the Lynx SDK —\n // OUTSIDE Angular's begin()/end() change-detection cycle. So a handler that\n // imperatively mutates the native tree (e.g. `el.setStyle(...)` for a press\n // animation) but changes NO signal schedules no CD, and LynxRendererFactory2\n // .end() therefore never flushes those mutations. On native the effect is a\n // delayed paint; on web (@lynx-js/web-core's offscreen document) the mutation\n // never reaches the real DOM at all, so imperative animations silently do\n // nothing (verified in a headless browser). Schedule the same coalesced\n // safety-net flush used for content built outside a cycle so these mutations\n // commit. It's a near-no-op when nothing is layout-dirty, and if the handler\n // DID change a signal the resulting CD flush runs and this stays a guarded\n // no-op — so there's no double-flush cost.\n scheduleSettleFlush();\n return result;\n };\n\n // Cache the resolved handler so #recreateSubtree() can re-register it on a\n // rebuilt native ref — native events don't survive a painting-node teardown\n // and can't be read back from the native side, so template `(bind…)` handlers\n // on projected content would go dead after a remount without this.\n const entry = { eventType, eventName, listener };\n this.#listeners.push(entry);\n\n // type: 'worklet' routes the callback through Lynx's worklet system\n // (runWorklet), which is the only way to receive events in the JS thread.\n // Direct function callbacks also work here (not just worklet handles) —\n // the native engine checks the value type at runtime.\n __AddEvent(this.element, eventType, eventName, {\n type: 'worklet',\n value: listener,\n });\n\n return () => {\n const i = this.#listeners.indexOf(entry);\n // Defensive: the entry was pushed above and cleanup runs at most once\n // per registration; indexOf always finds it.\n /* v8 ignore next */\n if (i >= 0) this.#listeners.splice(i, 1);\n // Passing undefined as the listener tells the Lynx SDK to remove the\n // corresponding event listener for this type+name combination.\n __AddEvent(this.element, eventType, eventName, undefined);\n };\n }\n}\n\n/**\n * Commits all queued genuine element removals — a free-function wrapper over\n * `LynxElement.commitPendingRemovals()` so `LynxRendererFactory2.end()` can\n * drain them (via the lynx-element barrel) right before `__FlushElementTree()`,\n * keeping removals in the same flush as the cycle's other mutations.\n */\nexport const processPendingRemovals = (): void => {\n LynxElement.commitPendingRemovals();\n};\n\n/**\n * Re-derives positional edge whitespace for every text touched this cycle — a\n * free-function wrapper over `LynxElement.commitPendingTextNormalization()` so\n * `LynxRendererFactory2.end()` can drain it (via the lynx-element barrel) right\n * after removals and before `__FlushElementTree()`, keeping the corrected text in\n * the same flush as the cycle's other mutations. See #pendingTextNormalization.\n */\nexport const processPendingTextNormalization = (): void => {\n LynxElement.commitPendingTextNormalization();\n};\n\nlet settleFlushScheduled = false;\n\n/**\n * Safety-net flush for native mutations made OUTSIDE a begin()/end() change-\n * detection cycle. `LynxRendererFactory2.end()` calls `__FlushElementTree()`\n * once per CD tick, which is what commits (lays out + paints) the cycle's\n * element mutations. But a lazy-loaded route component is instantiated by\n * `RouterOutlet` DURING navigation — outside any such cycle — so its freshly\n * created elements land in the fiber tree yet are never flushed. On-device\n * symptom: the route's static shell renders, but its `@if`/`@for`/interpolation\n * content stays invisible until an unrelated CD (e.g. a tap) triggers the next\n * end() flush. (Bootstrap sidesteps this via native's implicit post-renderPage\n * flush.) This mirrors the `<list>` path's own guard for the exact same case —\n * see `LynxListElement.#scheduleUpdate`.\n *\n * Called from `LynxDocument`'s element creators — which only ever run on the\n * main thread (the background thread uses LynxBackgroundDocument, which does not\n * touch the native tree), so no thread guard is needed here. It schedules ONE\n * coalesced microtask (matching the list guard's `queueMicrotask`, not\n * `setTimeout` — flushing from a macrotask crashes the native engine), and is a\n * no-op while:\n * - inside a CD cycle — end() will flush;\n * - the first render is pending — native flushes after renderPage, and any\n * `<list>` defers its own first flush (see isFirstRenderPending()).\n * The near-no-op cost when nothing is layout-dirty (the core's `need_layout_`\n * gate) keeps the steady-state overhead negligible.\n */\nexport const scheduleSettleFlush = (): void => {\n if (\n settleFlushScheduled ||\n isInsideChangeDetection() ||\n isFirstRenderPending()\n ) {\n return;\n }\n settleFlushScheduled = true;\n queueMicrotask(() => {\n settleFlushScheduled = false;\n // A CD cycle began in the meantime — its end() will flush; don't double up\n // (and avoid a re-entrant flush).\n if (isInsideChangeDetection()) return;\n // Mirror end()'s ordering: commit any queued removals, then re-derive text\n // whitespace, so both land in the same flush as the new content (see\n // #pendingRemovals / #pendingTextNormalization). List children are driven by\n // their own update-list-info path, so no list handling here.\n LynxElement.commitPendingRemovals();\n LynxElement.commitPendingTextNormalization();\n __FlushElementTree();\n });\n};\n","import {\n isFirstRenderPending,\n runAfterFirstRender,\n} from '../lynx-render-lifecycle';\nimport type { ElementRef, ListElementRef } from '../types/lynx';\nimport { LynxElement } from './lynx-element';\n\n/**\n * Manages list children in a virtual tree instead of the native element tree.\n *\n * Lynx's native list is a virtualized list driven by engine callbacks\n * (componentAtIndex / enqueueComponent). Children must NOT be appended via\n * __AppendElement at render time — the list calls componentAtIndex to request\n * items by index on demand, and update-list-info tells it which indices exist.\n *\n * Angular's rendering model appends children directly, so this class intercepts\n * appendChild/insertBefore and stores children in a JS-level linked list.\n * The actual __AppendElement call happens lazily inside componentAtIndex\n * (create-list-element.ts) when the native engine requests the item.\n */\n\n/**\n * Module-level set of LynxListElements that need their native list updated.\n * Drained by processPendingListUpdates() which is called from\n * LynxRendererFactory2.end() — right before __FlushElementTree().\n */\nconst pendingListUpdates = new Set<LynxListElement>();\n\n/**\n * Process all pending list updates. Called from LynxRendererFactory2.end()\n * before __FlushElementTree() so list updates are flushed as part of the\n * normal Angular CD cycle — never from setTimeout (which crashes native).\n */\nexport const processPendingListUpdates = (): void => {\n if (pendingListUpdates.size === 0) return;\n // Copy & clear before iterating — a processUpdate could theoretically\n // trigger further mutations, though unlikely.\n const lists = [...pendingListUpdates];\n pendingListUpdates.clear();\n for (const list of lists) {\n list._processUpdate();\n }\n};\n\nexport class LynxListElement extends LynxElement {\n #firstVirtualChild: LynxElement | null = null;\n #lastVirtualChild: LynxElement | null = null;\n #destroyed = false;\n /**\n * Tracks what was last committed to native via update-list-info so we can\n * compute a diff (insertAction / removeAction) on the next update. This is\n * ALSO what componentAtIndex/componentAtIndexes (create-list-element.ts)\n * read via getCommittedUIChildren() — see that method's doc comment for\n * why they must never call getUIChildren() themselves.\n */\n #committedUIChildren: ElementRef[] = [];\n /**\n * The native unique-ID (a plain number) of each element in\n * #committedUIChildren, in the same order. Stored so _processUpdate() can\n * diff on primitive keys instead of element-object identity — see that\n * method's diff block for why hashing an element ref in a Set/Map aborts the\n * Lepus context. Kept strictly in lock-step with #committedUIChildren.\n */\n #committedIds: number[] = [];\n #componentAtIndex: ((...args: any[]) => number | undefined) | null = null;\n #enqueueComponent: ((...args: any[]) => void) | null = null;\n #componentAtIndexes: ((...args: any[]) => void) | null = null;\n\n /**\n * Store the list callbacks so _processUpdate() can re-register them via\n * __UpdateListCallbacks on every update. React Lynx does this on every\n * flush (see listUpdateInfo.ts) — the native engine (unlike the web\n * polyfill) does not invoke componentAtIndex for a fresh update-list-info\n * unless the callbacks are re-registered alongside it. Without this,\n * update-list-info is accepted with no crash but componentAtIndex is\n * silently never called and the list stays blank.\n */\n setCallbacks(\n componentAtIndex: (...args: any[]) => number | undefined,\n enqueueComponent: (...args: any[]) => void,\n componentAtIndexes: (...args: any[]) => void,\n ): void {\n this.#componentAtIndex = componentAtIndex;\n this.#enqueueComponent = enqueueComponent;\n this.#componentAtIndexes = componentAtIndexes;\n }\n\n override remove(): void {\n this.#destroyed = true;\n pendingListUpdates.delete(this);\n super.remove();\n }\n\n override appendChild(newChild: LynxElement): void {\n if (newChild.isRootPageElement) return;\n newChild._virtualParent = this;\n newChild._virtualPrev = this.#lastVirtualChild;\n newChild._virtualNext = null;\n\n if (this.#lastVirtualChild) {\n this.#lastVirtualChild._virtualNext = newChild;\n }\n if (!this.#firstVirtualChild) {\n this.#firstVirtualChild = newChild;\n }\n this.#lastVirtualChild = newChild;\n\n this.#scheduleUpdate();\n }\n\n override insertBefore(\n newChild: LynxElement,\n refChild: LynxElement | null,\n ): void {\n if (newChild.isRootPageElement) return;\n if (refChild == null) {\n this.appendChild(newChild);\n return;\n }\n\n newChild._virtualParent = this;\n newChild._virtualNext = refChild;\n newChild._virtualPrev = refChild._virtualPrev;\n\n if (refChild._virtualPrev) {\n refChild._virtualPrev._virtualNext = newChild;\n } else {\n this.#firstVirtualChild = newChild;\n }\n refChild._virtualPrev = newChild;\n\n this.#scheduleUpdate();\n }\n\n removeVirtualChild(child: LynxElement): void {\n if (child._virtualPrev) {\n child._virtualPrev._virtualNext = child._virtualNext;\n } else {\n this.#firstVirtualChild = child._virtualNext;\n }\n if (child._virtualNext) {\n child._virtualNext._virtualPrev = child._virtualPrev;\n } else {\n this.#lastVirtualChild = child._virtualPrev;\n }\n\n child._virtualParent = null;\n child._virtualPrev = null;\n child._virtualNext = null;\n\n // Do NOT call __RemoveElement here. List item removal is managed\n // exclusively through update-list-info's removeAction (sent in\n // _processUpdate). Direct __RemoveElement on list children is invalid —\n // same as direct __AppendElement outside componentAtIndex crashes.\n // Calling both __RemoveElement AND removeAction double-removes and crashes.\n\n this.#scheduleUpdate();\n }\n\n /**\n * Returns ElementRefs of real UI children, excluding NoneElement comment\n * markers — the invisible <view>s LynxDocument.createComment() creates as\n * Angular's @for/@if insertion anchors, each tagged tagName === 'comment'.\n *\n * Filters on the wrapper's `tagName` (a plain JS string on the LynxElement\n * object), NOT a WeakSet keyed by the native ElementRef. This is the fix for\n * the crash-to-home-screen on every list add/remove. The previous\n * implementation did `#nonElements.has(child.element)`, and hashing a\n * native-backed element ref in a WeakSet/Map/Set on the main-thread Lepus\n * context aborts the process — js_map_has → map_find_record → js_strict_eq2\n * → __JS_FreeValueRT (a QuickJS refcount assertion). _processUpdate() calls\n * this on every list update, so it detonated as soon as items changed.\n * (The initial render happened to survive it — the abort is refcount-timing\n * sensitive — which is why it looked fine until the first mutation.) Reading\n * a string property off the JS wrapper touches no FFI object and no Map/Set,\n * so it can never trip it. See create-list-element.ts's componentAtIndex doc\n * for the general \"never key a Set/Map on an element ref\" constraint.\n */\n getUIChildren(): ElementRef[] {\n const children: ElementRef[] = [];\n let child = this.#firstVirtualChild;\n while (child) {\n if (child.tagName !== 'comment') {\n children.push(child.element);\n }\n child = child._virtualNext;\n }\n return children;\n }\n\n /**\n * The UI children list as of the last _processUpdate() call, pre-filtered\n * and cached — for componentAtIndex/componentAtIndexes (create-list-element.ts)\n * to read via plain array indexing. See their call sites' doc comments:\n * native invokes them synchronously, reentrantly, from deep inside its own\n * list layout pass, and calling ANY WeakSet/Map method (even a single\n * `.has()`) from within that reentrant call was observed to crash the\n * Lepus QuickJS context with a refcounting assertion inside\n * __JS_FreeValueRT, every time, regardless of how shallow the surrounding\n * call stack is (confirmed via a genuinely fresh setTimeout-scheduled\n * invocation that still crashed identically) — so getUIChildren() (which\n * calls WeakSet.has() per child) must never run from that call path.\n */\n getCommittedUIChildren(): ElementRef[] {\n return this.#committedUIChildren;\n }\n\n /**\n * Appended-state is tracked as a plain property directly on the ElementRef\n * rather than a WeakSet, for the same reason as getCommittedUIChildren():\n * these are called from componentAtIndex, where WeakSet/Map methods crash.\n * A plain property get/set compiles to ordinary field access, not a call\n * into QuickJS's Map/Set native implementation.\n */\n isAppendedToNativeList(child: ElementRef): boolean {\n return (child as { __appended?: boolean }).__appended === true;\n }\n\n markAppendedToNativeList(child: ElementRef): void {\n (child as { __appended?: boolean }).__appended = true;\n }\n\n /**\n * Mark this list for update. The actual processing happens in\n * processPendingListUpdates(), called from LynxRendererFactory2.end()\n * right before __FlushElementTree(). This ensures list updates are\n * flushed as part of the normal Angular CD cycle — calling\n * __FlushElementTree from setTimeout crashes the native engine.\n */\n #scheduleUpdate(): void {\n if (this.#destroyed) return;\n const wasEmpty = pendingListUpdates.size === 0;\n pendingListUpdates.add(this);\n if (wasEmpty) {\n // Safety net for cases where list items are created outside a begin/end\n // CD cycle (e.g. lazy-loaded route components on first navigation).\n // If end() drains the set first, this microtask is a no-op.\n // IMPORTANT: Only call processPendingListUpdates() here — NOT\n // __FlushElementTree() directly. _processUpdate() does its own flush\n // per list once update-list-info/callbacks are set; flushing before\n // that setup runs processes stale list state.\n queueMicrotask(() => {\n if (pendingListUpdates.size > 0) {\n processPendingListUpdates();\n }\n });\n }\n }\n\n /**\n * Compute a diff against the last committed children and send update-list-info.\n * Called from processPendingListUpdates() — NOT directly.\n * __FlushElementTree() is called afterwards by the renderer factory.\n *\n * Positions in insertAction are indices in the NEW child array.\n * Positions in removeAction are indices in the OLD (committed) child array.\n * This matches the React Lynx ListUpdateInfoRecording format.\n */\n _processUpdate(): void {\n if (this.#destroyed) return;\n\n // Defer the ENTIRE update — not just the flush — until the first render\n // has fully completed. See isFirstRenderPending()'s doc comment: driving\n // the list's update-list-info + layout flush now would run it while still\n // nested inside native's initial renderPage() call, re-entering our\n // componentAtIndex callback from a call frame native hasn't finished\n // unwinding. Re-running this method from the setTimeout macrotask scheduled\n // by markFirstRenderComplete() lets it run on a clean top-level task\n // instead, after renderPage() has returned.\n if (isFirstRenderPending()) {\n runAfterFirstRender(() => this._processUpdate());\n return;\n }\n\n const newChildren = this.getUIChildren();\n const oldChildren = this.#committedUIChildren;\n const oldIds = this.#committedIds;\n\n // Diff by native unique-ID (a plain number), NOT by element-object identity.\n // This is the fix for the SIGABRT on item removal. The diff below looks\n // items up in a Set; hashing a native-backed element ref as a Set/Map key\n // routes through Lepus's LepusConvertToObjectCallBack → CheckObjectCtx,\n // which aborts the entire main-thread QuickJS context the instant the ref\n // is stale or from another context — precisely the case on removal, where\n // the diff must test the just-removed element (whose native backing is now\n // detached) against the surviving set. Crucially this crash did NOT surface\n // on the initial render or on pure appends: those only ever call .has()\n // against an EMPTY Set, and QuickJS short-circuits an empty-set lookup\n // without converting the key. Numbers hash directly with no conversion\n // callback, so an ID-keyed Set is safe on every path (insert, remove,\n // reorder). newIds is read from the live new children (all valid here);\n // oldIds is the array captured on the previous update, so we never invoke a\n // native accessor on an already-removed element while diffing.\n const newIds = newChildren.map((child) => __GetElementUniqueID(child));\n\n // Commit NOW, before update-list-info/flush below — not at the end of\n // this method. componentAtIndex reads via getCommittedUIChildren(), and\n // it can run reentrantly from inside the __FlushElementTree() call\n // further down (native invokes it synchronously as part of the list's\n // own layout pass); by then this must already reflect the new list.\n // #committedIds is committed in lock-step so the NEXT update's oldIds line\n // up positionally with the array componentAtIndex indexes into.\n this.#committedUIChildren = newChildren;\n this.#committedIds = newIds;\n\n const oldIdSet = new Set(oldIds);\n const newIdSet = new Set(newIds);\n\n // Items present in old but absent from new → tell native to remove them.\n // Positions are indices into the OLD committed array (oldIds is parallel).\n const removeAction: number[] = [];\n for (let i = 0; i < oldIds.length; i++) {\n if (!newIdSet.has(oldIds[i]!)) {\n removeAction.push(i);\n }\n }\n\n // Items present in new but absent from old → tell native to insert them.\n // Minimal insertAction format matching Vue Lynx: only position, type, item-key.\n // Positions are indices into the NEW child array.\n const insertAction = newChildren\n .map((child, i) => ({ child, i }))\n .filter(({ i }) => !oldIdSet.has(newIds[i]!))\n .map(({ child, i }) => ({\n position: i,\n type: 'list-item',\n 'item-key':\n __GetAttributeByName(child, 'item-key') ?? String(newIds[i]),\n }));\n\n // CRITICAL: Never send empty update-list-info. Vue Lynx skips updates\n // when there's nothing new (flushListUpdates checks items.length <= reported).\n // Sending an empty update puts the native list in a bad state that causes\n // subsequent updates with items to crash intermittently.\n if (insertAction.length === 0 && removeAction.length === 0) {\n return;\n }\n\n // Clean up the appended-to-native-list marker for removed items so they\n // can be re-appended fresh if re-added to the list later.\n for (const idx of removeAction) {\n const removed = oldChildren[idx];\n // Defensive: removeAction is built from oldIds → oldChildren indices, so\n // every idx maps to a live child. The undefined-guard is unreachable but\n // stays as safety against index drift from a future refactor.\n /* v8 ignore next */\n if (removed) (removed as { __appended?: boolean }).__appended = false;\n }\n\n __SetAttribute(this.element, 'update-list-info', {\n insertAction,\n removeAction,\n updateAction: [],\n });\n\n // Re-register callbacks alongside the fresh update-list-info — matches\n // React Lynx's flush() (listUpdateInfo.ts), which calls this on every\n // update, not just once at creation, rather than only once at __CreateList\n // time as we did before.\n if (this.#componentAtIndex && this.#enqueueComponent) {\n __UpdateListCallbacks(\n this.element as ListElementRef,\n this.#componentAtIndex,\n this.#enqueueComponent,\n // componentAtIndexes is optional in the setCallbacks signature — the\n // batch path is a Lynx optimization the runtime uses only when native\n // asks for it. Every real caller supplies it, so the nullish fallback\n // is defensive.\n /* v8 ignore next */\n this.#componentAtIndexes ?? undefined,\n );\n }\n\n // Flush from the tree ROOT, not the list element. FiberElement's layout\n // traversal (UpdateLayoutInfoRecursively) walks down from root and\n // early-returns the instant it hits a non-dirty ancestor — it does NOT\n // recurse into children past that point. The list's surrounding\n // <view>/<scroll-view> wrapper was already flushed clean by the earlier\n // bare flush in end(), so a flush scoped to just the list element (via\n // an `element` arg + listID) never reaches the list: the traversal\n // prunes one level above it and the native list's own layout pass\n // (which calls componentAtIndex) never runs. A root-scoped flush walks\n // the whole tree, and marking the list dirty (done above via\n // update-list-info's ResolveAttribute) bubbles dirtiness up through its\n // ancestors, so the traversal isn't pruned before reaching it.\n __FlushElementTree(undefined, { triggerLayout: true });\n\n // Do NOT clear update-list-info to an empty {insertAction:[],...} here.\n // Native consumes update-list-info once during the flush above (the list\n // element is no longer dirty for that attribute afterward), so a later\n // bare __FlushElementTree() in end() won't re-apply it. React Lynx never\n // clears it either — it just sets a fresh diff on the next real update\n // (see listUpdateInfo.ts, which only ever __SetAttribute's a computed\n // diff, never an empty one). Sending an empty update-list-info actively\n // corrupts the native list's state (see this file's earlier note): it\n // leaves every cell perpetually \"binding\" and the engine re-runs its\n // layout pass forever with visibleItem stuck empty.\n }\n}\n","import { LynxBackgroundElement } from '../lynx-element';\nimport type { LynxDocumentBase } from './types';\n\nexport class LynxBackgroundDocument implements LynxDocumentBase {\n #page: LynxBackgroundElement | null = null;\n\n constructor() {}\n createRootElement(): LynxBackgroundElement {\n const page = new LynxBackgroundElement();\n page.tagName = 'page';\n page.setAttribute('tagName', 'page');\n page.isRootPageElement = true;\n this.#page = page;\n return this.#page;\n }\n createElement(tag: string, value?: string): LynxBackgroundElement {\n // Returns the existing root page element — same singleton semantics as main thread.\n if (tag === 'page') {\n return this.#page!;\n }\n\n // In the background thread, we create virtual elements but store their tag name\n // to help with debugging and potential future synchronization\n const element = new LynxBackgroundElement();\n element.tagName = tag;\n element.setAttribute('tagName', tag);\n\n // For debugging purposes, store text content if provided\n if (value) {\n element.setAttribute('textContent', value);\n }\n\n return element;\n }\n createText(value: string): LynxBackgroundElement {\n const element = new LynxBackgroundElement();\n element.tagName = 'text';\n element.setAttribute('tagName', 'text');\n element.setAttribute('textContent', value);\n return element;\n }\n createComment(): LynxBackgroundElement {\n const element = new LynxBackgroundElement();\n element.tagName = 'comment';\n element.setAttribute('tagName', 'comment');\n return element;\n }\n appendChild(newChild: LynxBackgroundElement): void {\n this.#page?.appendChild(newChild);\n }\n}\n","import { LynxListElement } from '../../lynx-element';\nimport type { ListElementRef } from '../../types/lynx';\n\n/**\n * Factory for the list native element.\n *\n * list in Lynx is a virtualized list driven by engine callbacks.\n * Angular's rendering builds children into a virtual JS-level linked list\n * (LynxListElement). The native engine calls componentAtIndex for each\n * visible index, synchronously, during the list's own layout pass; we\n * append the pre-built element and ack it with { asyncFlush: true } (see\n * componentAtIndex's own doc comment for why, and for the hard constraint\n * that nothing reachable from these callbacks may call a WeakSet/Map method).\n */\nexport const createListElement = (pageId: number): LynxListElement => {\n // Forward-declared so callbacks can close over the fully-initialized instance.\n let listEl: LynxListElement;\n\n /**\n * * componentAtIndex is called by the native engine synchronously, from\n * * DEEP inside the list's own layout pass (LinearLayoutManager::Fill ->\n * * LayoutChunk -> BindItemHolder -> ComponentAtIndex -> into JS). We append\n * * the pre-built element (its own inner subtree was already committed by\n * * the normal, non-list __AppendElement calls during rendering) and ack it.\n * *\n * * The ack MUST be a synchronous flush tagged with the operationID native\n * * passed us: { triggerLayout: true, operationID, elementID: sign, listID }.\n * * This mirrors React Lynx's single-item componentAtIndex exactly (see\n * * references/.../snapshot/list/list.ts, componentAtChildCtx's\n * * `!enableBatchRender` branch). The operationID is the acknowledgment the\n * * native list waits for to mark this cell's binding COMPLETE — it is the\n * * whole point of the callback. { asyncFlush: true } (untagged) is only for\n * * the batch componentAtIndexes path where the engine itself opts in; using\n * * it here leaves every cell perpetually \"binding\" (native never matches an\n * * operationID), so it re-runs its layout pass forever without ever showing\n * * an item — an infinite layoutComplete loop with visibleItem stuck empty.\n * * Despite running from inside the layout pass, the operationID flush is not\n * * dangerously re-entrant: native defers the operation's completion via the\n * * operationID queue rather than recursing into TickLayout here.\n * *\n * * CRITICAL: this function (and anything it calls, e.g. listEl's helper\n * * methods) must NEVER key a WeakSet/Map/Set on an element ref — not even a\n * * single .has(). Hashing a native-backed element ref on the main-thread\n * * Lepus context aborts the whole process inside QuickJS's Map/Set\n * * implementation: js_map_has → map_find_record → js_strict_eq2 →\n * * __JS_FreeValueRT (a refcount assertion), or a CheckObjectCtx cross-context\n * * abort. This is NOT about reentrancy or call-stack depth — it reproduced\n * * from a freshly-scheduled setTimeout task with no accumulated depth, and it\n * * ALSO fires from LynxListElement._processUpdate() during an ordinary\n * * change-detection cycle (it crashed to the home screen on every list\n * * add/remove until getUIChildren() stopped keying a WeakSet on element refs).\n * * The helpers below sidestep it structurally: getCommittedUIChildren()\n * * indexes a pre-computed array, isAppendedToNativeList() reads a plain\n * * property tag, _processUpdate() diffs Sets of numeric unique-IDs, and\n * * getUIChildren() filters on the wrapper's tagName — all ordinary field\n * * access / primitive hashing, never an element-ref Map/Set lookup.\n * v8 ignore start -- callback invoked synchronously by the native list layout pass (LinearLayoutManager::Fill → BindItemHolder → ComponentAtIndex → into JS). It is not reachable from unit tests without recreating the native call frame; the behavior is covered by the on-device integration checks documented in investigations/list.md.\n */\n const componentAtIndex = (\n listRef: ListElementRef,\n listId: number,\n cellIndex: number,\n opId: number,\n ): number | undefined => {\n const uiChildren = listEl.getCommittedUIChildren();\n if (cellIndex >= uiChildren.length) return undefined;\n const child = uiChildren[cellIndex]!;\n if (!listEl.isAppendedToNativeList(child)) {\n __AppendElement(listRef, child);\n listEl.markAppendedToNativeList(child);\n }\n const sign = __GetElementUniqueID(child);\n __FlushElementTree(child, {\n triggerLayout: true,\n operationID: opId,\n elementID: sign,\n listID: listId,\n });\n return sign;\n };\n /**\n * v8 ignore stop\n */\n\n const enqueueComponent = (\n _listRef: ListElementRef,\n _listId: number,\n _eleId: number,\n ) => {\n // enqueueComponent signals that an item scrolled offscreen and can be\n // recycled. We don't implement a recycle pool — items stay in the native\n // list tree permanently.\n };\n\n /**\n * * Batch version called by the native engine when it needs multiple items.\n * * Same no-flush approach as componentAtIndex — items are already committed.\n * * If the engine passes asyncFlush: true, we use it since that path delegates\n * * scheduling to native (no re-entrancy). The !asyncFlush batch path collects\n * * all elementIDs and does a single non-re-entrant flush at the end.\n * v8 ignore start -- batch callback invoked by the native list layout pass; same rationale as componentAtIndex above — not reachable from unit tests without simulating the native call frame.\n */\n const componentAtIndexes = (\n listRef: ListElementRef,\n listId: number,\n cellIndexes: number[],\n opIds: number[],\n _enableReuseNotification: boolean,\n asyncFlush: boolean,\n ) => {\n const uiChildren = listEl.getCommittedUIChildren();\n const elementIDs: number[] = [];\n for (let i = 0; i < cellIndexes.length; i++) {\n const child = uiChildren[cellIndexes[i]!];\n if (!child) continue;\n if (!listEl.isAppendedToNativeList(child)) {\n __AppendElement(listRef, child);\n listEl.markAppendedToNativeList(child);\n }\n const elementID = __GetElementUniqueID(child);\n elementIDs.push(elementID);\n if (asyncFlush) {\n // Native engine owns the async schedule — safe, no re-entrancy.\n __FlushElementTree(child, { asyncFlush: true });\n }\n }\n if (!asyncFlush) {\n __FlushElementTree(listRef, {\n triggerLayout: true,\n operationIDs: opIds,\n elementIDs,\n listID: listId,\n });\n }\n };\n /* v8 ignore stop */\n\n const nativeList = __CreateList(\n pageId,\n componentAtIndex,\n enqueueComponent,\n {},\n componentAtIndexes,\n );\n\n // list-type, span-count, and scroll-orientation should be set via template\n // bindings (e.g. <list list-type=\"single\" span-count=\"1\" ...>), NOT\n // programmatically here. Vue Lynx does not set any attributes after\n // __CreateList — they flow through the normal attribute-setting path.\n //\n // enable-async-list is the one exception: it's not a per-list layout\n // choice, it's a hard requirement of Lynx's native list UI (see\n // LynxUICollection.isNeedRenderComponents in the iOS engine — error\n // E_COMPONENT_LIST_UNSUPPORTED_THREAD_STRATEGY, code 220207). Every\n // AngularLynx app runs the dual-thread (async) engine strategy with\n // fiber-style elements, and without this flag the native list silently\n // skips applying its data source — componentAtIndex is simply never\n // called, no crash, nothing renders. Setting it here means every <list>\n // works out of the box; a template binding can still override it if a\n // future use case genuinely needs the sync (all-on-UI) engine strategy.\n __SetAttribute(nativeList, 'enable-async-list', true);\n\n listEl = new LynxListElement(nativeList);\n listEl.tagName = 'list';\n listEl.setCallbacks(componentAtIndex, enqueueComponent, componentAtIndexes);\n return listEl;\n};\n","import type { LynxElement } from '../../lynx-element';\n\n/**\n * Returns the existing root page element — does NOT create a new one.\n * Only one <page> element is allowed per application. The page element's\n * isRootPageElement guard prevents Angular from reparenting or removing it.\n */\nexport const createPageElement = (\n page: LynxElement,\n pageElementRequested: boolean,\n): { element: LynxElement; pageElementRequested: boolean } => {\n if (pageElementRequested) {\n console.warn(\n 'Multiple <page> elements detected. Only one <page> is allowed per application.',\n );\n }\n return { element: page, pageElementRequested: true };\n};\n","import { devStats } from '../devtools/stats';\nimport {\n LynxElement,\n type LynxListElement,\n scheduleSettleFlush,\n} from '../lynx-element';\nimport { setPageElementRef } from './page-ref';\n\nimport { createNativeRefByTag } from './create-native-ref';\nimport {\n createCommentElement,\n createListElement,\n createPageElement,\n} from './element-creators';\nimport type { LynxDocumentBase } from './types';\n\n/**\n * Main-thread document that creates native Lynx elements via PAPI functions.\n * Each createElement call wraps a PAPI call (__CreateView, __CreateText, etc.)\n * and returns a LynxElement wrapping the native ElementRef. The document owns\n * the root page element and tracks its unique ID for child element creation.\n */\nexport class LynxDocument implements LynxDocumentBase {\n page!: LynxElement;\n #pageId = 0;\n #pageElementRequested = false;\n\n constructor() {}\n createRootElement(): LynxElement {\n const pageElement = __CreatePage('0', 0);\n this.page = new LynxElement(pageElement);\n this.page.tagName = 'page';\n // Prevent Angular from reparenting or removing the root page element\n // during normal component lifecycle (appendChild/remove calls).\n this.page.isRootPageElement = true;\n this.#pageId = __GetElementUniqueID(pageElement);\n setPageElementRef(pageElement);\n return this.page;\n }\n createElement(tag: string, value?: string): LynxElement | LynxListElement {\n // `__PROFILE__` is a build-time `define`. In the test config it's `false`\n // (dead-code-eliminated), so the increment is unreachable from Vitest.\n /* v8 ignore next */\n if (__PROFILE__) devStats.elementCreated++;\n // Ensure content created outside a CD cycle (e.g. a lazy route component\n // built by RouterOutlet during navigation) still gets flushed — see\n // scheduleSettleFlush(). A no-op during normal in-cycle rendering.\n scheduleSettleFlush();\n // 'list' returns a LynxListElement (a virtual-tree wrapper, not a raw ref)\n // and 'page' returns the singleton root — both are special and are never\n // recreated, so they are handled here rather than via the shared raw-ref\n // dispatch (createNativeRefByTag), which the recreation path also uses.\n if (tag === 'list') {\n return createListElement(this.#pageId);\n }\n if (tag === 'page') {\n const result = createPageElement(this.page, this.#pageElementRequested);\n this.#pageElementRequested = result.pageElementRequested;\n return result.element;\n }\n const element = createNativeRefByTag(tag, this.#pageId, value);\n const el = new LynxElement(element);\n el.tagName = tag;\n // raw-text bakes its text into the native element at creation, bypassing the\n // cached setter path — seed the recreation cache so a remounted raw-text can\n // be rebuilt via __CreateRawText with the same text.\n if (tag === 'raw-text') {\n el.setInitialText(value ?? '');\n }\n return el;\n }\n createText(value: string): LynxElement {\n scheduleSettleFlush();\n const text = __CreateRawText(value);\n const lynxElement = new LynxElement(text);\n lynxElement.tagName = 'raw-text';\n // Seed the recreation cache: the text is baked into the native ref at\n // creation and never flows through a cached setter, so without this a\n // remounted raw-text would rebuild empty (see LynxElement.setInitialText /\n // #recreateSubtree).\n lynxElement.setInitialText(value);\n return lynxElement;\n }\n createComment(): LynxElement {\n scheduleSettleFlush();\n const element = createCommentElement(this.#pageId);\n const el = new LynxElement(element);\n // tagName 'comment' is the SOLE marker LynxListElement.getUIChildren() uses\n // to skip these @for/@if insertion anchors. It deliberately does not go in a\n // WeakSet of element refs — hashing a native ref crashes the Lepus engine\n // (see getUIChildren). Keep this tag and that filter in sync.\n el.tagName = 'comment';\n return el;\n }\n appendChild(newChild: LynxElement): void {\n this.page.appendChild(newChild);\n }\n}\n","import { LynxElement } from '../lynx-element';\nimport { LynxDocument, type LynxDocumentBase } from '../lynx-document';\nimport type { ElementRef } from '../types/lynx';\n\n/**\n * Hydration-aware document that reconnects Angular's element tree to\n * pre-existing native elements (created by the Lynx engine from a snapshot)\n * instead of creating new ones. Once the hydration queue is exhausted,\n * falls through to a normal LynxDocument for subsequent dynamic mutations.\n */\nexport class LynxHydrateDocument implements LynxDocumentBase {\n readonly #queue: ElementRef[];\n #cursor = 0;\n #fallback: LynxDocument | null = null;\n #page: LynxElement | null = null;\n readonly #pageElementRef: ElementRef;\n\n constructor(pageElementRef: ElementRef, elementQueue: ElementRef[]) {\n this.#pageElementRef = pageElementRef;\n this.#queue = elementQueue;\n }\n\n #isHydrating(): boolean {\n return this.#cursor < this.#queue.length;\n }\n\n /**\n * Lazily create the fallback document for post-hydration mutations.\n * Reuses the same page element so Angular's root stays consistent.\n */\n #getFallback(): LynxDocument {\n if (!this.#fallback) {\n this.#fallback = new LynxDocument();\n // Backfill the fallback's page reference without calling __CreatePage\n // again — the page already exists from the snapshot.\n this.#fallback.page = this.#page!;\n }\n return this.#fallback;\n }\n\n #nextElement(): LynxElement {\n // Callers (createElement/createText/createComment) already gate on\n // #isHydrating() before reaching here, so the queue is guaranteed to have\n // an entry. The defensive re-check has been folded into a single throw\n // path (ignored) rather than a two-branch if to keep the coverage report\n // clean while still failing loudly on a future caller that forgets the\n // guard.\n /* v8 ignore next 4 */\n if (this.#cursor >= this.#queue.length) {\n throw new Error(\n 'Hydration queue exhausted during initial render — snapshot/template mismatch',\n );\n }\n const ref = this.#queue[this.#cursor++]!;\n return new LynxElement(ref);\n }\n\n createRootElement(): LynxElement {\n // Reuse the page element the engine reconstructed from the snapshot\n // instead of calling __CreatePage which would create a duplicate.\n const page = new LynxElement(this.#pageElementRef);\n page.tagName = 'page';\n page.isRootPageElement = true;\n this.#page = page;\n return page;\n }\n\n createElement(tag: string, value?: string): LynxElement {\n if (!this.#isHydrating()) {\n return this.#getFallback().createElement(tag, value) as LynxElement;\n }\n\n // Return the next pre-existing element from the queue. Angular calls\n // createElement in the same deterministic order as the original render,\n // so the queue order matches.\n if (tag === 'page') {\n return this.#page!;\n }\n const el = this.#nextElement();\n el.tagName = tag;\n return el;\n }\n\n createText(value: string): LynxElement {\n if (!this.#isHydrating()) {\n return this.#getFallback().createText(value);\n }\n const el = this.#nextElement();\n el.tagName = 'raw-text';\n // Seed the same recreation/normalization cache a freshly-created raw-text\n // gets (see LynxDocument.createText). Without this, #rawText stays\n // undefined; if this element is later touched by the flush-time whitespace\n // pass (e.g. a sibling run inside the same <text> changes), it would read\n // back '' and blank this correctly-hydrated text.\n el.setInitialText(value);\n return el;\n }\n\n createComment(): LynxElement {\n if (!this.#isHydrating()) {\n return this.#getFallback().createComment();\n }\n const el = this.#nextElement();\n el.tagName = 'comment';\n return el;\n }\n\n appendChild(newChild: LynxElement): void {\n // During hydration: no-op — the tree structure is already correct\n // in the native layer from the snapshot reconstruction.\n if (this.#isHydrating()) return;\n // The optional-chaining transform generates a synthetic branch that v8's\n // provider counts inconsistently; the two-branch behavior (page set vs\n // not) is exercised by the \"delegates to page\" and \"before createRoot\"\n // tests. Ignore the synthetic branch here.\n /* v8 ignore next */\n this.#page?.appendChild(newChild);\n }\n}\n","import {\n type ListenerOptions,\n type Renderer2,\n RendererStyleFlags2,\n} from '@angular/core';\nimport type { LynxDocumentBase } from '../lynx-document';\nimport type { BaseLynxElement } from '../lynx-element';\n\n/**\n * Collapse every run of whitespace to a single space — WITHOUT trimming the ends.\n *\n * Angular's template compiler (`preserveWhitespaces: false`, the default)\n * already collapses interior whitespace but leaves the single leading/trailing\n * space that template indentation produces (e.g. `<text>\\n Hello\\n</text>`\n * reaches us as `\" Hello \"`). Native Lynx has no CSS white-space model, so that\n * edge space renders as a literal indent on-device.\n *\n * We must strip that edge space — but NOT here, because whether an edge space is\n * trimmable depends on POSITION within the text's inline-formatting context. The\n * leading space of the FIRST run and the trailing space of the LAST run are\n * trimmed, but the space between two adjacent runs — e.g. the projected\n * `<text>One </text><text>two</text><text> three</text>` — is meaningful and\n * must survive (otherwise \"One two three\" renders as \"Onetwothree\"). The\n * renderer sees one text node at a time with no sibling context, and projected\n * runs from separate templates only form one inline context at runtime, so the\n * positional edge-trim runs later — at flush time over the assembled tree (see\n * `processPendingTextNormalization` in lynx-element.ts). Here we only collapse,\n * so the element can stash the collapsed-but-untrimmed value that pass re-derives\n * the display from. React Lynx sidesteps all this at compile time, where its JSX\n * transform still has the newline info Angular has already discarded by now.\n *\n * ASCII whitespace only, so a deliberate non-breaking space (U+00A0) survives as\n * an escape hatch for a value that needs a literal edge space.\n */\nconst collapseWhitespace = (value: string): string =>\n value.replace(/[ \\t\\n\\r\\f\\v]+/g, ' ');\n\nexport class LynxRenderer implements Renderer2 {\n readonly #document: LynxDocumentBase;\n /**\n * Stable storage for Angular's per-renderer metadata (e.g. component styles).\n * Must be the same object reference across calls — Angular reads back what it writes.\n */\n readonly #data: { [key: string]: unknown } = {};\n\n constructor(document: LynxDocumentBase) {\n this.#document = document;\n }\n\n get data(): { [key: string]: any } {\n return this.#data;\n }\n\n destroy(): void {\n // No-op: this renderer does not own the document (it is injected via DI)\n // and holds no other resources that require explicit cleanup.\n }\n createElement(name: string, _namespace?: string | null): BaseLynxElement {\n return this.#document.createElement(name);\n }\n createComment(_value: string): BaseLynxElement {\n return this.#document.createComment();\n }\n createText(value: string): BaseLynxElement {\n return this.#document.createText(collapseWhitespace(value));\n }\n // Angular walks a destroyed view and calls destroyNode() per node ONLY when\n // this is non-null (see destroyLView in @angular/core). We use it to drop the\n // node from LynxElement's native-ref → canonical-wrapper registry, so the\n // registry doesn't retain wrappers for genuinely-destroyed elements. A no-op\n // for nodes without the method (background-thread / SSR elements).\n destroyNode: ((node: unknown) => void) | null = (node: unknown): void => {\n (node as { deregisterNative?: () => void }).deregisterNative?.();\n };\n\n appendChild(parent: BaseLynxElement, newChild: BaseLynxElement): void {\n parent.appendChild(newChild);\n }\n insertBefore(\n parent: BaseLynxElement,\n newChild: BaseLynxElement,\n refChild: BaseLynxElement | null,\n _isMove?: boolean,\n ): void {\n if (refChild == null) {\n parent.appendChild(newChild);\n } else {\n parent.insertBefore(newChild, refChild);\n }\n }\n removeChild(\n _parent: BaseLynxElement,\n oldChild: BaseLynxElement,\n _isHostElement?: boolean,\n ): void {\n oldChild.remove();\n }\n /**\n * Angular calls selectRootElement once during bootstrap to get the root\n * node where the app component will be rendered. In browser Angular this\n * finds an existing DOM element; here we create the Lynx page element.\n */\n selectRootElement(): BaseLynxElement {\n return this.#document.createRootElement();\n }\n parentNode(node: BaseLynxElement): BaseLynxElement | null {\n return node.parentNode();\n }\n nextSibling(node: BaseLynxElement): BaseLynxElement | null {\n return node.nextSibling();\n }\n setAttribute(\n el: BaseLynxElement,\n name: string,\n value: string,\n _namespace?: string | null,\n ): void {\n el.setAttribute(name, value);\n }\n removeAttribute(\n el: BaseLynxElement,\n name: string,\n _namespace?: string | null,\n ): void {\n el.removeAttribute(name);\n }\n addClass(el: BaseLynxElement, name: string): void {\n el.addClass(name);\n }\n removeClass(el: BaseLynxElement, name: string): void {\n el.removeClass(name);\n }\n setStyle(\n el: BaseLynxElement,\n style: string,\n value: any,\n flags?: RendererStyleFlags2,\n ): void {\n // Angular passes style names in camelCase unless DashCase flag is set.\n // Lynx expects CSS property names in dash-case (e.g. background-color).\n const cssKey =\n flags != null && flags & RendererStyleFlags2.DashCase\n ? style\n : style.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);\n // Important flag signals [style.foo.important] binding — append !important.\n const cssValue =\n flags != null && flags & RendererStyleFlags2.Important\n ? `${String(value)} !important`\n : value;\n el.setStyle(cssKey, cssValue);\n }\n removeStyle(\n el: BaseLynxElement,\n style: string,\n flags?: RendererStyleFlags2,\n ): void {\n const cssKey =\n flags != null && flags & RendererStyleFlags2.DashCase\n ? style\n : style.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);\n el.removeStyle(cssKey);\n }\n setProperty(el: BaseLynxElement, name: string, value: any): void {\n el.setProperty(name, value);\n }\n /**\n * Angular calls setValue for text nodes created via createText(). In the\n * browser DOM this sets node.nodeValue. In Lynx, raw-text elements store\n * their content in the 'text' attribute.\n */\n setValue(node: BaseLynxElement, value: string): void {\n node.setAttribute('text', collapseWhitespace(value));\n }\n listen(\n target: BaseLynxElement,\n eventName: string,\n callback: (event: boolean) => boolean | void,\n _options?: ListenerOptions,\n ): () => void {\n return target.addEventListener(eventName, callback);\n }\n}\n","import type { LynxDocumentBase } from '../lynx-document';\nimport { LynxRenderer } from './renderer';\n\n/**\n * Angular creates one EmulatedLynxRenderer per component type (keyed by\n * RendererType2.id). This renderer is used when ViewEncapsulation.Emulated\n * is active (the default) and handles adding scope classes for CSS isolation.\n *\n * In a browser, Angular's EmulatedEncapsulationDomRenderer2 adds _ngcontent-xxx\n * attributes to every element. In Lynx, the template plugin handles per-component\n * CSS scoping natively, so we only need the _nghost class on the host element\n * (for :host selectors). Child elements get no scope classes at all.\n */\nexport class EmulatedLynxRenderer extends LynxRenderer {\n #componentScopeId: string;\n\n constructor(document: LynxDocumentBase, componentId: string) {\n super(document);\n this.#componentScopeId = componentId;\n }\n\n /**\n * Note: we no longer add scope classes to child elements. The Lynx template\n * embeds the component scope ID separately from element class lists, so plain\n * class selectors in CSS are matched by the native CSS engine without needing\n * a conjunction scope class on every element.\n */\n override selectRootElement() {\n const el = super.selectRootElement();\n // Keep scope class on the host element for potential :host CSS rules.\n el.addClass(`_nghost-${this.#componentScopeId}`);\n return el;\n }\n}\n","import {\n Injectable,\n inject,\n type Renderer2,\n type RendererFactory2,\n type RendererType2,\n ViewEncapsulation,\n} from '@angular/core';\nimport { devStats } from '../devtools/stats';\nimport type { LynxDocumentBase } from '../lynx-document';\nimport {\n processPendingListUpdates,\n processPendingRemovals,\n processPendingTextNormalization,\n} from '../lynx-element';\nimport {\n isFirstRenderPending,\n setInsideChangeDetection,\n} from '../lynx-render-lifecycle';\nimport { EmulatedLynxRenderer } from './emulated-lynx-renderer';\nimport { LynxRenderer } from './renderer';\nimport { LYNX_DOCUMENT } from './token';\n\n@Injectable()\nexport class LynxRendererFactory2 implements RendererFactory2 {\n lynxDocument: LynxDocumentBase = inject(LYNX_DOCUMENT);\n #defaultRenderer: LynxRenderer | null = null;\n #emulatedRenderers = new Map<string, EmulatedLynxRenderer>();\n\n /**\n * Angular calls createRenderer once per component type. The renderer is\n * cached by encapsulation mode + component ID, so each component type gets\n * at most one renderer instance that's reused across all instances of that\n * component.\n */\n createRenderer(_hostElement: any, type: RendererType2 | null): Renderer2 {\n if (!type || type.encapsulation === ViewEncapsulation.None) {\n if (!this.#defaultRenderer) {\n this.#defaultRenderer = new LynxRenderer(this.lynxDocument);\n }\n return this.#defaultRenderer;\n }\n\n if (type.encapsulation === ViewEncapsulation.ShadowDom) {\n console.warn(\n 'ViewEncapsulation.ShadowDom is not supported in Lynx. Falling back to no encapsulation.',\n );\n if (!this.#defaultRenderer) {\n this.#defaultRenderer = new LynxRenderer(this.lynxDocument);\n }\n return this.#defaultRenderer;\n }\n\n // ViewEncapsulation.Emulated (default) — one EmulatedLynxRenderer per\n // component type, keyed by type.id (the ɵcmp.id we set in angular.ts).\n let renderer = this.#emulatedRenderers.get(type.id);\n if (!renderer) {\n renderer = new EmulatedLynxRenderer(this.lynxDocument, type.id);\n this.#emulatedRenderers.set(type.id, renderer);\n }\n return renderer;\n }\n /**\n * Angular calls begin()/end() around every change-detection tick. We track\n * whether a cycle is in progress so element creation can tell in-cycle\n * rendering (flushed by end() below) apart from content built OUTSIDE a cycle\n * — e.g. a lazy route component instantiated by RouterOutlet during\n * navigation — which needs its own safety-net flush (see scheduleSettleFlush\n * in lynx-element.ts).\n */\n begin?(): void {\n setInsideChangeDetection(true);\n }\n /**\n * Called by Angular after every change detection cycle completes.\n * On the background thread this is a no-op — there's no native tree to flush.\n * On the main thread, the order is critical:\n * 1. processPendingRemovals() — commits genuine element removals queued\n * during this cycle. MUST run before the flush so the __RemoveElement\n * calls land in the SAME flush as the cycle's other mutations; draining\n * them later (the old queueMicrotask) left removed subtrees occupying\n * native layout until a later cycle happened to flush (\"hidden element\n * leaves a gap\").\n * 2. __FlushElementTree() — commits all pending element mutations to native\n * 3. processPendingListUpdates() — sends update-list-info for lists that\n * gained/lost children during this CD cycle, then does a targeted flush\n * per list. This MUST run after the bare flush so list children's subtrees\n * are already committed when componentAtIndex appends them.\n * Reversing this order causes list items to appear empty (subtree not committed)\n * or crashes from re-entrant __FlushElementTree.\n *\n * Step 1 is skipped entirely while isFirstRenderPending() — see that\n * function's doc comment. Every CD cycle that runs as part of the initial\n * bootstrap is still nested inside the native engine's own renderPage call;\n * we avoid driving a layout-triggering flush (which, for pages with a\n * <list>, reentrantly calls back into componentAtIndex) from inside a call\n * frame native hasn't finished unwinding. Native performs its own implicit\n * flush once renderPage returns, so skipping this is safe — element\n * creation/attribute calls above already mutate native elements directly,\n * independent of flushing.\n */\n end?(): void {\n // This change-detection cycle is finishing: clear the flag first, on EVERY\n // return path, so mutations after this point are correctly seen as\n // outside-a-cycle (see begin() / scheduleSettleFlush). The flush below is\n // unconditional, so clearing the flag now does not affect it.\n setInsideChangeDetection(false);\n if (__MAIN_THREAD__) {\n // During SSR hydration the native tree already exists from the snapshot\n // — flushing would be redundant and could cause visual glitches.\n // `__ENABLE_SSR__` is a build-time `define` (false in the Vitest config)\n // so this guard is dead from the test bundle's point of view.\n /* v8 ignore start */\n if (__ENABLE_SSR__ && (globalThis as any).__LYNX_IS_HYDRATING__) {\n return;\n }\n /* v8 ignore stop */\n\n // Build-time `define` gate — false in the Vitest config, so this\n // profiling block is dead code from the test bundle's point of view.\n /* v8 ignore start */\n if (__PROFILE__) {\n devStats.cdCycles++;\n devStats.flushCount++;\n }\n /* v8 ignore stop */\n\n // Commit queued removals into this cycle's flush (see doc above). Drained\n // even while the first-render flush is skipped: the __RemoveElement calls\n // mutate native elements directly, and native performs its own flush once\n // renderPage returns.\n processPendingRemovals();\n // Re-derive positional edge whitespace for texts mutated this cycle, after\n // removals (so torn-down subtrees are skipped) and before the flush (so the\n // corrected text is painted in the same pass). Runs even while the first\n // render's explicit flush is skipped: it only mutates native `text`\n // attributes directly, which native commits in its own post-renderPage\n // flush — same rationale as processPendingRemovals above.\n processPendingTextNormalization();\n if (!isFirstRenderPending()) {\n __FlushElementTree();\n }\n processPendingListUpdates();\n }\n }\n}\n","import { APP_BASE_HREF, IMAGE_CONFIG } from '@angular/common';\nimport {\n DOCUMENT,\n ErrorHandler,\n type EnvironmentProviders,\n makeEnvironmentProviders,\n RendererFactory2,\n} from '@angular/core';\nimport { LynxErrorHandler } from '../error-handler/lynx-error-handler';\nimport { LynxBackgroundDocument, LynxDocument } from '../lynx-document';\nimport { LynxHydrateDocument } from '../ssr/hydrate-document';\nimport { LynxRendererFactory2 } from './lynx-renderer-factory2';\nimport { LYNX_DOCUMENT } from './token';\n\n/**\n * Central DI configuration for the Lynx renderer. Must be included in every\n * Lynx Angular app's providers (typically via app.config.ts). Sets up:\n * 1. Thread-aware document (LynxDocument vs LynxBackgroundDocument)\n * 2. DOCUMENT stub (Angular requires this token but Lynx has no DOM Document)\n * 3. APP_BASE_HREF (prevents BrowserPlatformLocation from crashing)\n * 4. Renderer factory (creates LynxRenderer / EmulatedLynxRenderer)\n * 5. Error handler (routes to _ReportError + __lynxLastError)\n */\nexport const provideRenderer = (): EnvironmentProviders => {\n return makeEnvironmentProviders([\n {\n provide: LYNX_DOCUMENT,\n useFactory: () => {\n // Three paths based on thread + SSR state:\n // 1. Main thread + SSR hydrating → LynxHydrateDocument (reuse snapshot elements)\n // 2. Main thread + normal → LynxDocument (create native elements via PAPI)\n // 3. Background thread → LynxBackgroundDocument (virtual in-memory tree)\n if (__MAIN_THREAD__) {\n // `__ENABLE_SSR__` is a build-time `define` — `false` in the Vitest\n // config, so the SSR-hydrating branch is dead code from the test\n // bundle's point of view. LynxHydrateDocument itself is covered by\n // hydrate-document.test.ts.\n /* v8 ignore next 6 */\n if (__ENABLE_SSR__ && (globalThis as any).__LYNX_IS_HYDRATING__) {\n return new LynxHydrateDocument(\n (globalThis as any).__LYNX_HYDRATE_PAGE__,\n (globalThis as any).__LYNX_HYDRATE_QUEUE__,\n );\n }\n return new LynxDocument();\n }\n return new LynxBackgroundDocument();\n },\n },\n {\n // Angular's internal code occasionally accesses @Inject(DOCUMENT). In Lynx\n // there is no DOM document, so we provide a minimal stub. Specific access\n // points (defaultView, querySelector) on the global `document` are\n // polyfilled in polyfills.ts.\n provide: DOCUMENT,\n useValue: {\n // TransferState's root factory calls\n // `inject(DOCUMENT).getElementById(APP_ID + '-state')` to restore the\n // `<script>` that Angular SSR inlines. `resource()` and `httpResource()`\n // inject TransferState on construction, so without this every resource\n // threw \"getElementById is not a function\". Lynx never has that script\n // (AngularLynx SSR hydrates from its own element snapshot), so `null` —\n // \"no transferred state\" — is the correct answer, not just a stub.\n getElementById: () => null,\n },\n },\n // Provide a base href so Angular's PathLocationStrategy uses it directly\n // instead of calling getBaseHrefFromDOM(), which crashes in Lynx because\n // BrowserPlatformLocation (platform-level) tries to querySelector on an\n // undefined DOCUMENT.\n {\n provide: APP_BASE_HREF,\n useValue: '/',\n },\n // Disable Angular's ImagePerformanceWarning. It runs on every bootstrap and,\n // unless *both* warnings are disabled, calls Angular's internal getDocument()\n // to scan the page for oversized/lazy <img> elements. Lynx has no DOM\n // document — getDocument() throws NG0210 and aborts the whole bootstrap.\n //\n // This only bit the *web* runtime: ImagePerformanceWarning.start() early-\n // returns when `PerformanceObserver` is undefined, which is the case in the\n // native (iOS/Android) background-thread JS engine. On web the background\n // thread is a real Web Worker, which *does* have PerformanceObserver, so it\n // proceeded to getDocument() and crashed. Disabling both warnings makes\n // start() early-return before that call on every platform — and it's\n // semantically correct anyway: Lynx renders native <image>, not HTML <img>,\n // so these DOM-scanning diagnostics can never apply.\n {\n provide: IMAGE_CONFIG,\n useValue: {\n disableImageSizeWarning: true,\n disableImageLazyLoadWarning: true,\n },\n },\n LynxRendererFactory2,\n {\n provide: RendererFactory2,\n useExisting: LynxRendererFactory2,\n },\n {\n provide: ErrorHandler,\n useClass: LynxErrorHandler,\n },\n ]);\n};\n","import { type LocationChangeListener, LocationStrategy } from '@angular/common';\nimport { Injectable } from '@angular/core';\n\n/**\n * In-memory LocationStrategy for Lynx — equivalent to React Router's MemoryRouter.\n *\n * Lynx is a native mobile runtime with no browser URL or History API.\n * Angular's default PathLocationStrategy chains through PlatformLocation →\n * window.history/window.location, which breaks Lynx's background thread\n * even with mocked globals.\n *\n * This strategy keeps all routing state in memory: a history stack,\n * current index, and popstate listeners — no browser APIs touched.\n *\n * Registered via `provideRouter()` in `lynx-router.ts`.\n */\n@Injectable()\nexport class LynxLocationStrategy extends LocationStrategy {\n #path = '/';\n #baseHref = '/';\n #history: { state: unknown; url: string }[] = [{ state: null, url: '/' }];\n #historyIndex = 0;\n #listeners: LocationChangeListener[] = [];\n\n override path(): string {\n return this.#path;\n }\n\n override prepareExternalUrl(internal: string): string {\n return internal;\n }\n\n override getBaseHref(): string {\n return this.#baseHref;\n }\n\n override getState(): unknown {\n return this.#history[this.#historyIndex]?.state ?? null;\n }\n\n override pushState(\n state: unknown,\n _title: string,\n url: string,\n queryParams: string,\n ): void {\n const fullUrl = url + (queryParams ? `?${queryParams}` : '');\n // Discard forward history when pushing a new entry\n this.#history.length = this.#historyIndex + 1;\n this.#history.push({ state, url: fullUrl });\n this.#historyIndex++;\n this.#path = fullUrl;\n }\n\n override replaceState(\n state: unknown,\n _title: string,\n url: string,\n queryParams: string,\n ): void {\n const fullUrl = url + (queryParams ? `?${queryParams}` : '');\n this.#history[this.#historyIndex] = { state, url: fullUrl };\n this.#path = fullUrl;\n }\n\n override back(): void {\n this.historyGo(-1);\n }\n\n override forward(): void {\n this.historyGo(1);\n }\n\n override historyGo(relativePosition: number = 0): void {\n const target = this.#historyIndex + relativePosition;\n if (target < 0 || target >= this.#history.length) return;\n this.#historyIndex = target;\n this.#path = this.#history[target].url;\n for (const fn of this.#listeners) {\n fn({ type: 'popstate', state: this.#history[target].state });\n }\n }\n\n override onPopState(fn: LocationChangeListener): VoidFunction {\n this.#listeners.push(fn);\n return () => {\n this.#listeners = this.#listeners.filter((l) => l !== fn);\n };\n }\n}\n","// cspell:ignore ɵfac\nimport {\n type LocationChangeEvent,\n type LocationChangeListener,\n PlatformLocation,\n} from '@angular/common';\nimport { Injectable } from '@angular/core';\n\n/**\n * PlatformLocation implementation for Lynx.\n *\n * Angular's default BrowserPlatformLocation uses `new URL()`, which doesn't\n * exist in the Lynx JS runtime. This class avoids `URL` entirely by manually\n * parsing pathname, search, and hash from the URL string.\n *\n * Registered via `provideRouter()` in `lynx-router.ts`.\n *\n * The `@Injectable()` decorator is required so Angular generates a `ɵfac`\n * factory for this class. Without it, `getUndecoratedInjectableFactory()`\n * walks the prototype chain, finds PlatformLocation's factory\n * (`() => inject(BrowserPlatformLocation)`), and silently creates the wrong\n * class — which crashes in Lynx because `window.location` doesn't exist.\n */\n@Injectable()\nexport class LynxPlatformLocation extends PlatformLocation {\n #history: { state: unknown; title: string; url: string }[] = [\n { state: null, title: '', url: '/' },\n ];\n #index = 0;\n #popStateListeners: LocationChangeListener[] = [];\n\n get #current() {\n return this.#history[this.#index];\n }\n\n /**\n * Manual URL parsing — avoids `new URL()` which is unavailable in Lynx runtime.\n */\n #parseUrl(): { pathname: string; search: string; hash: string } {\n const url = this.#current.url;\n const hashIndex = url.indexOf('#');\n const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;\n const hash = hashIndex >= 0 ? url.slice(hashIndex) : '';\n const searchIndex = withoutHash.indexOf('?');\n const pathname =\n searchIndex >= 0 ? withoutHash.slice(0, searchIndex) : withoutHash;\n const search = searchIndex >= 0 ? withoutHash.slice(searchIndex) : '';\n return { pathname: pathname || '/', search, hash };\n }\n\n override getBaseHrefFromDOM(): string {\n return '/';\n }\n\n override get href(): string {\n const { pathname, search, hash } = this.#parseUrl();\n return `lynx://app${pathname}${search}${hash}`;\n }\n\n override get protocol(): string {\n return 'lynx:';\n }\n\n override get hostname(): string {\n return 'app';\n }\n\n override get port(): string {\n return '';\n }\n\n override get pathname(): string {\n return this.#parseUrl().pathname;\n }\n\n override get search(): string {\n return this.#parseUrl().search;\n }\n\n override get hash(): string {\n return this.#parseUrl().hash;\n }\n\n override onPopState(fn: LocationChangeListener): VoidFunction {\n this.#popStateListeners.push(fn);\n return () => {\n this.#popStateListeners = this.#popStateListeners.filter((l) => l !== fn);\n };\n }\n\n override onHashChange(_fn: LocationChangeListener): VoidFunction {\n // Hash changes are handled via popState in this implementation\n return () => {};\n }\n\n override replaceState(state: unknown, title: string, url: string): void {\n this.#history[this.#index] = { state, title, url };\n }\n\n override pushState(state: unknown, title: string, url: string): void {\n // Discard forward history when pushing\n this.#history.length = this.#index + 1;\n this.#history.push({ state, title, url });\n this.#index++;\n }\n\n override forward(): void {\n this.historyGo(1);\n }\n\n override back(): void {\n this.historyGo(-1);\n }\n\n override historyGo(relativePosition: number = 0): void {\n const targetIndex = this.#index + relativePosition;\n if (targetIndex < 0 || targetIndex >= this.#history.length) {\n return;\n }\n this.#index = targetIndex;\n const event: LocationChangeEvent = {\n type: 'popstate',\n state: this.#current.state,\n };\n for (const listener of this.#popStateListeners) {\n listener(event);\n }\n }\n\n override getState(): unknown {\n return this.#current.state;\n }\n}\n","import { Injectable } from '@angular/core';\nimport type {\n ActivatedRouteSnapshot,\n DetachedRouteHandle,\n RouteReuseStrategy,\n} from '@angular/router';\n\n/**\n * Route reuse strategy that keeps component views alive across navigations.\n *\n * ## Why this is required on Lynx\n *\n * Lynx's native element APIs (`__CreateView`, `__CreateText`, etc.) allocate\n * elements in a fixed-size native pool. `__RemoveElement` detaches an element\n * from the tree but does NOT free its pool slot — there is no `__ReleaseElement`\n * API in Lynx's public surface. Angular's default `RouteReuseStrategy` destroys\n * components on every navigation, creating fresh native elements each time. Those\n * freed elements accumulate in the pool until it overflows (~256 slots on device),\n * causing a hard native crash on the 9th navigation in a back-and-forth pattern.\n *\n * ## What this strategy does\n *\n * Instead of destroying a component when navigating away, Angular calls\n * `ViewContainerRef.detach()`. The component's DOM elements are removed from the\n * native tree (the slots are occupied but unused). When navigating back,\n * `ViewContainerRef.insert()` re-adds those same native elements to the tree —\n * reusing their existing pool slots with no new allocations. The pool stays bounded\n * by (initial elements) + (max elements for any single route), regardless of how\n * many times the user navigates.\n */\n@Injectable()\nexport class LynxRouteReuseStrategy implements RouteReuseStrategy {\n readonly #stored = new Map<string, DetachedRouteHandle>();\n\n #key(route: ActivatedRouteSnapshot): string {\n // Use the full path from root to this route so nested routes don't collide.\n return route.pathFromRoot.map((r) => r.routeConfig?.path ?? '').join('/');\n }\n\n shouldDetach(_route: ActivatedRouteSnapshot): boolean {\n // Always detach instead of destroy — keeps native elements in the pool.\n return true;\n }\n\n store(\n route: ActivatedRouteSnapshot,\n handle: DetachedRouteHandle | null,\n ): void {\n if (handle) {\n this.#stored.set(this.#key(route), handle);\n } else {\n this.#stored.delete(this.#key(route));\n }\n }\n\n shouldAttach(route: ActivatedRouteSnapshot): boolean {\n return this.#stored.has(this.#key(route));\n }\n\n retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null {\n return this.#stored.get(this.#key(route)) ?? null;\n }\n\n shouldReuseRoute(\n future: ActivatedRouteSnapshot,\n curr: ActivatedRouteSnapshot,\n ): boolean {\n return future.routeConfig === curr.routeConfig;\n }\n}\n","import { LocationStrategy, PlatformLocation } from '@angular/common';\nimport {\n type EnvironmentProviders,\n makeEnvironmentProviders,\n} from '@angular/core';\nimport {\n provideRouter as ngProvideRouter,\n RouteReuseStrategy,\n type RouterFeatures,\n type Routes,\n withRouterConfig,\n} from '@angular/router';\nimport { LynxLocationStrategy } from './lynx-location-strategy';\nimport { LynxPlatformLocation } from './lynx-platform-location';\nimport { LynxRouteReuseStrategy } from './lynx-route-reuse-strategy';\n\n/**\n * Provides Angular Router configured for the Lynx runtime.\n *\n * Uses `LynxLocationStrategy` (in-memory routing) instead of Angular's default\n * `PathLocationStrategy` which relies on browser History/Location APIs. This is\n * the Angular equivalent of React Router's `MemoryRouter` — Lynx is a native\n * mobile runtime with no browser URL or History API.\n */\nexport const provideRouter = (\n routes: Routes,\n ...features: RouterFeatures[]\n): EnvironmentProviders => {\n return makeEnvironmentProviders([\n // In-memory routing — Lynx has no browser URL/history APIs.\n // Replaces the default BrowserPlatformLocation → PathLocationStrategy chain.\n // LynxPlatformLocation must be registered first: without it Angular falls back to\n // BrowserPlatformLocation, whose `this.location` is undefined in Lynx (no window.location),\n // so any access to `pathname`/`href` throws a TypeError that silently kills navigation.\n { provide: PlatformLocation, useClass: LynxPlatformLocation },\n { provide: LocationStrategy, useClass: LynxLocationStrategy },\n // Lynx's native element pool is finite (~256 slots on device) and\n // __RemoveElement only detaches elements — it does not free pool slots.\n // Angular's default strategy destroys components on navigation, creating\n // fresh elements each time and exhausting the pool (hard crash on ~9th nav).\n // LynxRouteReuseStrategy detaches views instead: elements are removed from\n // the tree but their pool slots are reused when the route is revisited.\n { provide: RouteReuseStrategy, useClass: LynxRouteReuseStrategy },\n ngProvideRouter(\n routes,\n // Lynx runs Angular on a background thread for layout calculation.\n // Unhandled navigation promise rejections (e.g. from unmatched routes or\n // lazy chunk loading failures) crash the background thread, causing a blank\n // screen with no errors. Resolving as false instead of rejecting prevents\n // this. Trade-off: lazy loading errors are silenced — navigation simply\n // doesn't happen rather than showing an error. Use Router.events with\n // NavigationError/NavigationCancel to detect these failures in app code.\n withRouterConfig({ resolveNavigationPromiseOnError: true }),\n ...features,\n ),\n ]);\n};\n","/**\n * On-device crash diagnostics.\n *\n * There is no console on the Lynx device, so we capture the last unhandled\n * error/rejection into a global (`__lynxLastError`) that Angular components can\n * surface via a `<text>` element. LynxErrorHandler covers Angular-managed\n * errors; the global `onerror`/`onunhandledrejection` handlers registered here\n * catch crashes that escape Angular entirely — native glue code, promise\n * rejections outside zones, etc.\n *\n * Split out of runtime.ts so `reportToNative` (and the handlers) can be\n * unit-tested on their own, and so the diagnostic seed runs before any other\n * runtime side effect.\n */\n\n// Seed the diagnostic slot so a read before the first crash returns '' rather\n// than undefined (components render it directly into <text>).\n(globalThis as any).__lynxLastError = '';\n\n/**\n * Forward an error to the native Lynx error reporting API when it exists.\n * errorCode 1101 = ErrCode::LYNX_ERROR_CODE_LEPUS (matches React Lynx's\n * convention). No-op off-device where `_ReportError` is absent.\n */\nexport const reportToNative = (err: Error): void => {\n if (typeof _ReportError === 'function') {\n _ReportError(err, { errorCode: 1101 });\n }\n};\n\n// Only install our handler when the host hasn't already provided one — a real\n// browser (web preview) supplies its own `onerror`, which we must not clobber.\nif (typeof (globalThis as any).onerror !== 'function') {\n (globalThis as any).onerror = (\n msg: string | Event,\n _src?: string,\n _line?: number,\n _col?: number,\n err?: Error,\n ) => {\n const e = err ?? new Error(String(msg));\n (globalThis as any).__lynxLastError =\n `${e.name}: ${e.message}\\n${e.stack ?? ''}`;\n reportToNative(e);\n };\n}\nif (typeof (globalThis as any).onunhandledrejection !== 'function') {\n (globalThis as any).onunhandledrejection = (event: PromiseRejectionEvent) => {\n const reason = event?.reason;\n const e =\n reason instanceof Error\n ? reason\n : new Error(`Unhandled rejection: ${String(reason)}`);\n (globalThis as any).__lynxLastError =\n `${e.name}: ${e.message}\\n${e.stack ?? ''}`;\n reportToNative(e);\n };\n}\n","/**\n * UTF-8 and percent-encoding helpers for the `URL` polyfill, following the\n * WHATWG URL Standard (https://url.spec.whatwg.org/#percent-encoded-bytes).\n *\n * They work on UTF-8 bytes rather than on `encodeURIComponent`/\n * `decodeURIComponent`, because those differ from the standard: they throw on\n * malformed input (lone surrogates, invalid `%` sequences) where URLs replace\n * the bad bytes with U+FFFD, and they encode a different set of characters.\n */\n\nconst REPLACEMENT_CHARACTER = 0xfffd;\n\n/**\n * Encodes a string as UTF-8 bytes. Lone surrogates become U+FFFD.\n *\n * Hand-written rather than using `TextEncoder`: that's a Web API, not part of\n * JavaScript, so neither of Lynx's threads can be assumed to have it, and the\n * polyfill exists precisely for runtimes that lack Web APIs.\n */\nexport const utf8Encode = (input: string): number[] => {\n const bytes: number[] = [];\n for (const char of input) {\n let codePoint = char.codePointAt(0) as number;\n // A lone surrogate can't be encoded as UTF-8; USVString conversion\n // replaces it, as browsers do.\n if (codePoint >= 0xd800 && codePoint <= 0xdfff) {\n codePoint = REPLACEMENT_CHARACTER;\n }\n if (codePoint < 0x80) {\n bytes.push(codePoint);\n } else if (codePoint < 0x800) {\n bytes.push(0xc0 | (codePoint >> 6), 0x80 | (codePoint & 0x3f));\n } else if (codePoint < 0x10000) {\n bytes.push(\n 0xe0 | (codePoint >> 12),\n 0x80 | ((codePoint >> 6) & 0x3f),\n 0x80 | (codePoint & 0x3f),\n );\n } else {\n bytes.push(\n 0xf0 | (codePoint >> 18),\n 0x80 | ((codePoint >> 12) & 0x3f),\n 0x80 | ((codePoint >> 6) & 0x3f),\n 0x80 | (codePoint & 0x3f),\n );\n }\n }\n return bytes;\n};\n\n/**\n * Decodes UTF-8 bytes, replacing each invalid sequence with U+FFFD the way\n * the Encoding Standard's UTF-8 decoder does\n * (https://encoding.spec.whatwg.org/#utf-8-decoder).\n */\nexport const utf8Decode = (bytes: readonly number[]): string => {\n let output = '';\n let index = 0;\n while (index < bytes.length) {\n const lead = bytes[index] as number;\n if (lead < 0x80) {\n output += String.fromCharCode(lead);\n index++;\n continue;\n }\n // The valid range of the first continuation byte narrows for some leads,\n // which rules out overlong encodings and surrogates.\n let lower = 0x80;\n let upper = 0xbf;\n let needed: number;\n let codePoint: number;\n if (lead >= 0xc2 && lead <= 0xdf) {\n needed = 1;\n codePoint = lead & 0x1f;\n } else if (lead >= 0xe0 && lead <= 0xef) {\n if (lead === 0xe0) lower = 0xa0;\n if (lead === 0xed) upper = 0x9f;\n needed = 2;\n codePoint = lead & 0xf;\n } else if (lead >= 0xf0 && lead <= 0xf4) {\n if (lead === 0xf0) lower = 0x90;\n if (lead === 0xf4) upper = 0x8f;\n needed = 3;\n codePoint = lead & 0x7;\n } else {\n output += String.fromCharCode(REPLACEMENT_CHARACTER);\n index++;\n continue;\n }\n let seen = 0;\n while (seen < needed) {\n const next = bytes[index + 1 + seen];\n if (next === undefined || next < lower || next > upper) break;\n lower = 0x80;\n upper = 0xbf;\n codePoint = (codePoint << 6) | (next & 0x3f);\n seen++;\n }\n if (seen < needed) {\n // The byte that broke the sequence starts the next one, so only the\n // lead and the valid continuation bytes are consumed.\n output += String.fromCharCode(REPLACEMENT_CHARACTER);\n index += 1 + seen;\n continue;\n }\n output += String.fromCodePoint(codePoint);\n index += 1 + needed;\n }\n return output;\n};\n\nconst toCodes = (chars: string): ReadonlySet<number> =>\n new Set(Array.from(chars, (char) => char.charCodeAt(0)));\n\n/**\n * The standard's percent-encode sets. Each also includes the C0 controls and\n * everything above U+007E, which `percentEncode` always encodes.\n *\n * That shared part is checked by a range test in `percentEncode` instead of\n * being stored in every set, so the C0 control set itself is empty: it adds\n * nothing to the range test (opaque paths and opaque hosts use it).\n */\nexport const C0_CONTROL_SET: ReadonlySet<number> = new Set();\nexport const FRAGMENT_SET = toCodes(' \"<>`');\nexport const QUERY_SET = toCodes(' \"#<>');\nexport const SPECIAL_QUERY_SET = toCodes(' \"#<>\\'');\nexport const PATH_SET = toCodes(' \"#<>?^`{}');\nexport const USERINFO_SET = toCodes(' \"#<>?^`{}/:;=@[\\\\]|');\n\n/**\n * The standard serializes escapes with uppercase hex and two digits (`%0A`,\n * `%2F`), and code comparing `href`s (such as the Router's same-URL check)\n * sees any other spelling as a different URL.\n */\nconst percentEncodeByte = (byte: number): string =>\n (byte < 0x10 ? '%0' : '%') + byte.toString(16).toUpperCase();\n\n/**\n * Percent-encodes the code points of `input` that are C0 controls, non-ASCII,\n * or in `encodeSet`. `%` itself is never encoded, so existing escapes survive.\n */\nexport const percentEncode = (\n input: string,\n encodeSet: ReadonlySet<number>,\n): string => {\n let output = '';\n for (const char of input) {\n const codePoint = char.codePointAt(0) as number;\n if (codePoint < 0x20 || codePoint > 0x7e || encodeSet.has(codePoint)) {\n for (const byte of utf8Encode(char)) output += percentEncodeByte(byte);\n } else {\n output += char;\n }\n }\n return output;\n};\n\nconst isHexDigit = (byte: number | undefined): boolean =>\n byte !== undefined &&\n ((byte >= 0x30 && byte <= 0x39) ||\n (byte >= 0x41 && byte <= 0x46) ||\n (byte >= 0x61 && byte <= 0x66));\n\n/**\n * Decodes `%XX` escapes as UTF-8. A `%` that doesn't start an escape is kept,\n * and invalid UTF-8 becomes U+FFFD, so it never throws.\n */\nexport const percentDecode = (input: string): string => {\n // Most names and values have no escapes, so skip the byte round trip.\n if (!input.includes('%')) return input;\n const bytes = utf8Encode(input);\n const decoded: number[] = [];\n for (let index = 0; index < bytes.length; index++) {\n const byte = bytes[index] as number;\n if (\n byte === 0x25 &&\n isHexDigit(bytes[index + 1]) &&\n isHexDigit(bytes[index + 2])\n ) {\n decoded.push(\n parseInt(\n String.fromCharCode(\n bytes[index + 1] as number,\n bytes[index + 2] as number,\n ),\n 16,\n ),\n );\n index += 2;\n } else {\n decoded.push(byte);\n }\n }\n return utf8Decode(decoded);\n};\n\n/**\n * The `application/x-www-form-urlencoded` byte serializer used by\n * `URLSearchParams`: spaces become `+`, and everything except ASCII\n * alphanumerics and `*-._` is percent-encoded.\n */\nexport const formUrlEncode = (input: string): string => {\n let output = '';\n for (const byte of utf8Encode(input)) {\n if (byte === 0x20) {\n output += '+';\n } else if (\n (byte >= 0x30 && byte <= 0x39) ||\n (byte >= 0x41 && byte <= 0x5a) ||\n (byte >= 0x61 && byte <= 0x7a) ||\n byte === 0x2a ||\n byte === 0x2d ||\n byte === 0x2e ||\n byte === 0x5f\n ) {\n output += String.fromCharCode(byte);\n } else {\n output += percentEncodeByte(byte);\n }\n }\n return output;\n};\n","import {\n C0_CONTROL_SET,\n percentDecode,\n percentEncode,\n} from './percent-encoding';\n\n/**\n * Host parsing for the `URL` polyfill, following the WHATWG URL Standard's\n * host parser (https://url.spec.whatwg.org/#host-parsing): domains, IPv4\n * (including the shorthand and hex/octal forms browsers accept), IPv6, and the\n * opaque hosts of non-special schemes.\n *\n * Domains are lowercased and non-ASCII labels Punycode-encoded. That covers\n * the internationalized-domain processing real hosts need, without the full\n * UTS #46 mapping tables, which would add far more to the bundle than they're\n * worth here.\n */\n\n/**\n * Thrown for any input the standard says fails to parse.\n *\n * A `TypeError` with the browsers' message, because callers rely on the\n * failure looking like the real `URL`'s: Angular's Router catches it to treat\n * a URL as unsafe, and `URL.canParse()` and `URL.parse()` turn it into\n * `false` and `null`.\n */\nexport const invalidUrl = (): TypeError => new TypeError('Invalid URL');\n\n// Opaque hosts (`foo://host`) only reject these delimiters; their control\n// characters and `%` are percent-encoded instead. Domains of special URLs\n// (`http://host`) also reject control characters and `%`, which by then have\n// been percent-decoded, so a `%` left over is a malformed escape.\n// oxlint-disable-next-line no-control-regex -- the URL Standard forbids NUL here\nconst FORBIDDEN_HOST = /[\\u0000\\t\\n\\r #/:<>?@[\\\\\\]^|]/;\n// oxlint-disable-next-line no-control-regex -- the URL Standard forbids C0 controls and DEL here\nconst FORBIDDEN_DOMAIN = /[\\u0000-\\u001f #%/:<>?@[\\\\\\]^|\\u007f]/;\n\n// RFC 3492 parameters for Punycode.\nconst BASE = 36;\nconst T_MIN = 1;\nconst T_MAX = 26;\nconst SKEW = 38;\nconst DAMP = 700;\nconst INITIAL_BIAS = 72;\nconst INITIAL_N = 128;\n\nconst adaptBias = (\n delta: number,\n numPoints: number,\n firstTime: boolean,\n): number => {\n let scaled = firstTime ? Math.floor(delta / DAMP) : delta >> 1;\n scaled += Math.floor(scaled / numPoints);\n let k = 0;\n while (scaled > ((BASE - T_MIN) * T_MAX) >> 1) {\n scaled = Math.floor(scaled / (BASE - T_MIN));\n k += BASE;\n }\n return Math.floor(k + ((BASE - T_MIN + 1) * scaled) / (scaled + SKEW));\n};\n\n/**\n * Maps a Punycode digit value (0-35) to `a`-`z` then `0`-`9`.\n */\nconst punycodeDigit = (digit: number): string =>\n String.fromCharCode(digit < 26 ? digit + 97 : digit + 22);\n\n/**\n * Punycode-encodes one label (RFC 3492, section 6.3).\n *\n * Implemented here because nothing on Lynx provides it: Node's `punycode`\n * module doesn't exist outside Node, and the encoder is small enough that a\n * dependency isn't worth it.\n */\nexport const punycodeEncode = (label: string): string => {\n const codePoints = Array.from(label, (char) => char.codePointAt(0) as number);\n let output = codePoints\n .filter((codePoint) => codePoint < 0x80)\n .map((codePoint) => String.fromCharCode(codePoint))\n .join('');\n const basicLength = output.length;\n let handled = basicLength;\n if (basicLength > 0) output += '-';\n\n let n = INITIAL_N;\n let delta = 0;\n let bias = INITIAL_BIAS;\n while (handled < codePoints.length) {\n const next = Math.min(...codePoints.filter((codePoint) => codePoint >= n));\n delta += (next - n) * (handled + 1);\n n = next;\n for (const codePoint of codePoints) {\n if (codePoint < n) delta++;\n if (codePoint !== n) continue;\n let q = delta;\n for (let k = BASE; ; k += BASE) {\n const t = k <= bias ? T_MIN : k >= bias + T_MAX ? T_MAX : k - bias;\n if (q < t) break;\n output += punycodeDigit(t + ((q - t) % (BASE - t)));\n q = Math.floor((q - t) / (BASE - t));\n }\n output += punycodeDigit(q);\n bias = adaptBias(delta, handled + 1, handled === basicLength);\n delta = 0;\n handled++;\n }\n delta++;\n n++;\n }\n return output;\n};\n\n/**\n * Converts a decoded domain to its ASCII form, so `http://München.de` and\n * `http://xn--mnchen-3ya.de` are the same host, as in browsers.\n *\n * `toLowerCase()` stands in for UTS #46's case mapping, which it matches for\n * the domains apps actually use.\n */\nconst domainToAscii = (domain: string): string =>\n domain\n .toLowerCase()\n // Domain name mapping turns the ideographic and full-width full stops\n // into `.`.\n .replace(/[。.。]/g, '.')\n .split('.')\n .map((label) =>\n // oxlint-disable-next-line no-control-regex -- matches any non-ASCII character\n /[^\\u0000-\\u007f]/.test(label) ? `xn--${punycodeEncode(label)}` : label,\n )\n .join('.');\n\n/**\n * Parses one IPv4 part: decimal, `0x` hex or leading-zero octal.\n */\nconst parseIpv4Number = (part: string): number | undefined => {\n if (part === '') return undefined;\n let digits = part;\n let radix = 10;\n if (/^0x/i.test(digits)) {\n digits = digits.slice(2);\n radix = 16;\n } else if (digits.length > 1 && digits.startsWith('0')) {\n digits = digits.slice(1);\n radix = 8;\n }\n if (digits === '') return 0;\n const valid =\n radix === 10 ? /^[0-9]+$/ : radix === 16 ? /^[0-9a-f]+$/i : /^[0-7]+$/;\n return valid.test(digits) ? parseInt(digits, radix) : undefined;\n};\n\n/**\n * Splits off the empty label a trailing `.` leaves behind.\n */\nconst ipv4Parts = (host: string): string[] => {\n const parts = host.split('.');\n if (parts[parts.length - 1] === '' && parts.length > 1) parts.pop();\n return parts;\n};\n\n/**\n * Whether the host must be parsed as IPv4: its last label is a number. A host\n * like `1.2.3.foo` stays a domain, but `foo.0x10` is an (invalid) address.\n */\nconst endsInANumber = (host: string): boolean => {\n const last = ipv4Parts(host).pop() as string;\n return /^[0-9]+$/.test(last) || parseIpv4Number(last) !== undefined;\n};\n\n/**\n * Parses and normalizes an IPv4 address, as browsers do, so the shorthand and\n * hex/octal spellings (`127.1`, `0x7f.0.0.1`) give the same host, and so the\n * same origin, as `127.0.0.1`.\n */\nconst parseIpv4 = (host: string): string => {\n const parts = ipv4Parts(host);\n if (parts.length > 4) throw invalidUrl();\n const numbers = parts.map((part) => {\n const value = parseIpv4Number(part);\n if (value === undefined) throw invalidUrl();\n return value;\n });\n const last = numbers.pop() as number;\n // Every part but the last is one byte; the last fills the remaining bytes.\n if (\n numbers.some((value) => value > 255) ||\n last >= 256 ** (4 - numbers.length)\n ) {\n throw invalidUrl();\n }\n let address = last;\n numbers.forEach((value, index) => {\n address += value * 256 ** (3 - index);\n });\n const bytes: number[] = [];\n for (let index = 0; index < 4; index++) {\n bytes.unshift(address % 256);\n address = Math.floor(address / 256);\n }\n return bytes.join('.');\n};\n\n/**\n * The IPv6 parser, transcribed from the standard's algorithm.\n */\nconst parseIpv6 = (input: string): number[] => {\n const address = [0, 0, 0, 0, 0, 0, 0, 0];\n let pieceIndex = 0;\n let compress: number | null = null;\n let pointer = 0;\n const at = (index: number): string | undefined => input[index];\n const isHex = (char: string | undefined): char is string =>\n char !== undefined && /[0-9a-f]/i.test(char);\n const isDigit = (char: string | undefined): char is string =>\n char !== undefined && /[0-9]/.test(char);\n\n if (at(pointer) === ':') {\n if (at(pointer + 1) !== ':') throw invalidUrl();\n pointer += 2;\n pieceIndex++;\n compress = pieceIndex;\n }\n while (at(pointer) !== undefined) {\n if (pieceIndex === 8) throw invalidUrl();\n if (at(pointer) === ':') {\n if (compress !== null) throw invalidUrl();\n pointer++;\n pieceIndex++;\n compress = pieceIndex;\n continue;\n }\n let value = 0;\n let length = 0;\n while (length < 4 && isHex(at(pointer))) {\n value = value * 0x10 + parseInt(at(pointer) as string, 16);\n pointer++;\n length++;\n }\n if (at(pointer) === '.') {\n // An embedded IPv4 address fills the last two pieces.\n if (length === 0 || pieceIndex > 6) throw invalidUrl();\n pointer -= length;\n let numbersSeen = 0;\n while (at(pointer) !== undefined) {\n if (numbersSeen > 0) {\n if (at(pointer) !== '.' || numbersSeen >= 4) throw invalidUrl();\n pointer++;\n }\n if (!isDigit(at(pointer))) throw invalidUrl();\n let ipv4Piece: number | null = null;\n while (isDigit(at(pointer))) {\n const digit = parseInt(at(pointer) as string, 10);\n if (ipv4Piece === 0) throw invalidUrl();\n ipv4Piece = ipv4Piece === null ? digit : ipv4Piece * 10 + digit;\n if (ipv4Piece > 255) throw invalidUrl();\n pointer++;\n }\n address[pieceIndex] =\n (address[pieceIndex] as number) * 0x100 + (ipv4Piece as number);\n numbersSeen++;\n if (numbersSeen === 2 || numbersSeen === 4) pieceIndex++;\n }\n if (numbersSeen !== 4) throw invalidUrl();\n break;\n }\n if (at(pointer) === ':') {\n pointer++;\n if (at(pointer) === undefined) throw invalidUrl();\n } else if (at(pointer) !== undefined) {\n throw invalidUrl();\n }\n address[pieceIndex] = value;\n pieceIndex++;\n }\n if (compress !== null) {\n // Move the pieces after `::` to the end of the address.\n let swaps = pieceIndex - compress;\n pieceIndex = 7;\n while (pieceIndex !== 0 && swaps > 0) {\n const swapIndex = compress + swaps - 1;\n const piece = address[pieceIndex] as number;\n address[pieceIndex] = address[swapIndex] as number;\n address[swapIndex] = piece;\n pieceIndex--;\n swaps--;\n }\n } else if (pieceIndex !== 8) {\n throw invalidUrl();\n }\n return address;\n};\n\n/**\n * Serializes an IPv6 address, compressing its longest run of zero pieces.\n */\nconst serializeIpv6 = (address: readonly number[]): string => {\n let compress: number | null = null;\n let longest = 1;\n for (let index = 0; index < 8; ) {\n let end = index;\n while (end < 8 && address[end] === 0) end++;\n if (end - index > longest) {\n longest = end - index;\n compress = index;\n }\n index = end === index ? index + 1 : end;\n }\n let output = '';\n for (let index = 0; index < 8; index++) {\n if (index === compress) {\n output += index === 0 ? '::' : ':';\n index += longest - 1;\n continue;\n }\n output += (address[index] as number).toString(16);\n if (index !== 7) output += ':';\n }\n return output;\n};\n\n/**\n * Parses a host. `isOpaque` is true for non-special schemes, whose hosts are\n * kept as written (only percent-encoded), as browsers do for `foo://Host`.\n *\n * A special URL's domain is percent-decoded before it's checked, because the\n * standard compares hosts by what they spell, not how they're escaped: a\n * percent-escaped letter names the same host as the letter itself.\n */\nexport const parseHost = (input: string, isOpaque: boolean): string => {\n if (input.startsWith('[')) {\n if (!input.endsWith(']')) throw invalidUrl();\n return `[${serializeIpv6(parseIpv6(input.slice(1, -1)))}]`;\n }\n if (isOpaque) {\n if (FORBIDDEN_HOST.test(input)) throw invalidUrl();\n return percentEncode(input, C0_CONTROL_SET);\n }\n const asciiDomain = domainToAscii(percentDecode(input));\n if (asciiDomain === '' || FORBIDDEN_DOMAIN.test(asciiDomain)) {\n throw invalidUrl();\n }\n return endsInANumber(asciiDomain) ? parseIpv4(asciiDomain) : asciiDomain;\n};\n","import { invalidUrl, parseHost } from './host';\nimport {\n C0_CONTROL_SET,\n FRAGMENT_SET,\n PATH_SET,\n percentEncode,\n QUERY_SET,\n SPECIAL_QUERY_SET,\n USERINFO_SET,\n} from './percent-encoding';\n\n/**\n * The parsed form of a URL: the standard's \"URL record\"\n * (https://url.spec.whatwg.org/#concept-url). `URL`'s getters and setters\n * read and replace its fields, and `serializeUrl` turns it back into `href`.\n *\n * Keeping the parsed fields, rather than re-parsing `href` on every access,\n * mirrors the standard's own model, which is what makes the setters'\n * documented behavior (each one changes one field and leaves the rest\n * alone) straightforward to follow.\n */\nexport type UrlRecord = {\n /** Lowercase, without the trailing `:`. */\n scheme: string;\n username: string;\n password: string;\n /** `null` when the URL has no authority (`mailto:x`, `foo:/path`). */\n host: string | null;\n /** `null` for no port, or for the scheme's default port. */\n port: number | null;\n /**\n * Path segments, serialized as `/` + each one. A string is an opaque path,\n * which non-special URLs without a `/` after the scheme have\n * (`mailto:someone@example.com`).\n */\n path: string[] | string;\n query: string | null;\n fragment: string | null;\n};\n\n// The special schemes and their default ports. A URL never stores its default\n// port, so `http://a:80/` and `http://a/` are the same URL and origin.\nconst SPECIAL_SCHEME_PORTS: Readonly<Record<string, number | null>> = {\n ftp: 21,\n file: null,\n http: 80,\n https: 443,\n ws: 80,\n wss: 443,\n};\n\n/**\n * Special schemes get the web's URL rules: `\\` works as `/`, the host is\n * required and lowercased, and the path is never empty.\n */\nexport const isSpecialScheme = (scheme: string): boolean =>\n Object.prototype.hasOwnProperty.call(SPECIAL_SCHEME_PORTS, scheme);\n\nexport const defaultPort = (scheme: string): number | null =>\n isSpecialScheme(scheme)\n ? (SPECIAL_SCHEME_PORTS[scheme] as number | null)\n : null;\n\nconst SCHEME = /^[a-zA-Z][a-zA-Z0-9+\\-.]*:/;\n\nconst isSlash = (char: string | undefined, special: boolean): boolean =>\n char === '/' || (special && char === '\\\\');\n\n/**\n * Dot segments also count in their percent-encoded forms (`%2e`, `.%2E`), as\n * the standard requires. Otherwise `/a/%2e%2e/b` would keep a `..` segment\n * that a server decodes and resolves, while the URL claims a different path.\n */\nconst isSingleDot = (segment: string): boolean =>\n segment === '.' || segment.toLowerCase() === '%2e';\n\nconst isDoubleDot = (segment: string): boolean =>\n ['..', '.%2e', '%2e.', '%2e%2e'].includes(segment.toLowerCase());\n\n/**\n * Splits off the query and fragment. Everything before them is the path (or\n * authority and path), which callers parse themselves.\n *\n * Splitting first matches the standard's parser, where `?` and `#` end the\n * authority and the path wherever they appear: in `http://a#b@c`, `a` is the\n * host and `b@c` the fragment, not credentials.\n */\nconst splitQueryAndFragment = (\n input: string,\n special: boolean,\n): { rest: string; query: string | null; fragment: string | null } => {\n const hashIndex = input.indexOf('#');\n const fragment =\n hashIndex === -1\n ? null\n : percentEncode(input.slice(hashIndex + 1), FRAGMENT_SET);\n const beforeFragment = hashIndex === -1 ? input : input.slice(0, hashIndex);\n const queryIndex = beforeFragment.indexOf('?');\n const query =\n queryIndex === -1\n ? null\n : percentEncode(\n beforeFragment.slice(queryIndex + 1),\n special ? SPECIAL_QUERY_SET : QUERY_SET,\n );\n const rest =\n queryIndex === -1 ? beforeFragment : beforeFragment.slice(0, queryIndex);\n return { rest, query, fragment };\n};\n\n/**\n * Appends the segments of `path` to `segments`, resolving `.` and `..` (also\n * in their percent-encoded forms). `path` excludes the slash that starts it.\n */\nconst appendPath = (\n segments: string[],\n path: string,\n special: boolean,\n): string[] => {\n const parts = path.split(special ? /[/\\\\]/ : '/');\n parts.forEach((part, index) => {\n // A trailing `.` or `..` keeps a trailing slash, so `/a/b/..` is `/a/`.\n const isLast = index === parts.length - 1;\n if (isDoubleDot(part)) {\n segments.pop();\n if (isLast) segments.push('');\n } else if (isSingleDot(part)) {\n if (isLast) segments.push('');\n } else {\n segments.push(percentEncode(part, PATH_SET));\n }\n });\n return segments;\n};\n\n/**\n * Parses the path that follows a host (or an absolute path), starting with\n * its optional leading slash. Special URLs always get at least `/`; other\n * URLs keep an empty path empty (`foo://host`).\n */\nexport const parsePathStart = (path: string, special: boolean): string[] => {\n if (special) {\n return appendPath([], isSlash(path[0], true) ? path.slice(1) : path, true);\n }\n if (path === '') return [];\n return appendPath([], path.startsWith('/') ? path.slice(1) : path, false);\n};\n\n/**\n * Parses `[user[:password]@]host[:port]`, then the path, query and fragment.\n */\nconst parseAuthority = (scheme: string, input: string): UrlRecord => {\n const special = isSpecialScheme(scheme);\n const { rest, query, fragment } = splitQueryAndFragment(input, special);\n const authorityEnd = rest.search(special ? /[/\\\\]/ : /\\//);\n const authority = authorityEnd === -1 ? rest : rest.slice(0, authorityEnd);\n const path = authorityEnd === -1 ? '' : rest.slice(authorityEnd);\n\n // The last `@` ends the credentials, so an unencoded `@` in a password\n // still parses (`http://a:p@ss@host`).\n const atIndex = authority.lastIndexOf('@');\n let username = '';\n let password = '';\n if (atIndex !== -1) {\n const userinfo = authority.slice(0, atIndex);\n const colonIndex = userinfo.indexOf(':');\n username = percentEncode(\n colonIndex === -1 ? userinfo : userinfo.slice(0, colonIndex),\n USERINFO_SET,\n );\n if (colonIndex !== -1) {\n password = percentEncode(userinfo.slice(colonIndex + 1), USERINFO_SET);\n }\n }\n const hostAndPort = authority.slice(atIndex + 1);\n const colonIndex = findPortColon(hostAndPort);\n const hostInput =\n colonIndex === -1 ? hostAndPort : hostAndPort.slice(0, colonIndex);\n // A URL with credentials or a port must have a host, and special URLs\n // (other than file:, parsed separately) always must.\n if (hostInput === '' && (special || atIndex !== -1 || colonIndex !== -1)) {\n throw invalidUrl();\n }\n return {\n scheme,\n username,\n password,\n host: parseHost(hostInput, !special),\n port:\n colonIndex === -1\n ? null\n : parsePort(scheme, hostAndPort.slice(colonIndex + 1)),\n path: parsePathStart(path, special),\n query,\n fragment,\n };\n};\n\n/**\n * Finds the `:` that starts the port in `host[:port]`: the first one outside\n * an IPv6 literal's brackets. Returns -1 when there is no port.\n */\nexport const findPortColon = (input: string): number => {\n let insideBrackets = false;\n for (let index = 0; index < input.length; index++) {\n const char = input[index];\n if (char === '[') insideBrackets = true;\n if (char === ']') insideBrackets = false;\n if (char === ':' && !insideBrackets) return index;\n }\n return -1;\n};\n\n/**\n * Parses a port, dropping the scheme's default port as browsers do.\n *\n * Only digits are accepted, and anything above 65535 fails: a port the\n * standard rejects must not turn into a different, valid one.\n */\nexport const parsePort = (scheme: string, input: string): number | null => {\n if (input === '') return null;\n if (!/^[0-9]+$/.test(input)) throw invalidUrl();\n const port = parseInt(input, 10);\n if (port > 65535) throw invalidUrl();\n return port === defaultPort(scheme) ? null : port;\n};\n\n/**\n * A copy of `base` without its path, query and fragment.\n */\nconst withBaseAuthority = (base: UrlRecord): UrlRecord => ({\n ...base,\n path: [],\n query: null,\n fragment: null,\n});\n\n/**\n * Resolves `input`, which has no scheme, against `base`: the standard's\n * \"relative state\".\n */\nconst parseRelative = (input: string, base: UrlRecord): UrlRecord => {\n const special = isSpecialScheme(base.scheme);\n if (isSlash(input[0], special)) {\n if (isSlash(input[1], special)) {\n // A scheme-relative URL (`//host/path`). Special URLs skip any number\n // of slashes before the host, as browsers do.\n return parseAuthority(\n base.scheme,\n special ? input.replace(/^[/\\\\]+/, '') : input.slice(2),\n );\n }\n const { rest, query, fragment } = splitQueryAndFragment(input, special);\n return {\n ...withBaseAuthority(base),\n path: parsePathStart(rest, special),\n query,\n fragment,\n };\n }\n const { rest, query, fragment } = splitQueryAndFragment(input, special);\n const basePath = (base.path as string[]).slice();\n if (rest === '') {\n // Only a query and/or fragment (or nothing): keep the base's path, and\n // its query too when the input has no query of its own.\n return { ...base, path: basePath, query: query ?? base.query, fragment };\n }\n basePath.pop();\n return {\n ...withBaseAuthority(base),\n path: appendPath(basePath, rest, special),\n query,\n fragment,\n };\n};\n\n/**\n * Parses a `file:` URL. File URLs have a host (possibly empty), and a\n * `localhost` host is the same as none. Windows drive-letter quirks are not\n * modeled: Lynx apps don't get Windows file paths.\n */\nconst parseFile = (input: string, base: UrlRecord | undefined): UrlRecord => {\n if (isSlash(input[0], true) && isSlash(input[1], true)) {\n const afterSlashes = input.slice(2);\n const hostEnd = afterSlashes.search(/[/\\\\?#]/);\n const hostInput =\n hostEnd === -1 ? afterSlashes : afterSlashes.slice(0, hostEnd);\n const host = hostInput === '' ? '' : parseHost(hostInput, false);\n const { rest, query, fragment } = splitQueryAndFragment(\n hostEnd === -1 ? '' : afterSlashes.slice(hostEnd),\n true,\n );\n return {\n scheme: 'file',\n username: '',\n password: '',\n host: host === 'localhost' ? '' : host,\n port: null,\n path: parsePathStart(rest, true),\n query,\n fragment,\n };\n }\n if (base?.scheme === 'file') return parseRelative(input, base);\n const { rest, query, fragment } = splitQueryAndFragment(input, true);\n return {\n scheme: 'file',\n username: '',\n password: '',\n host: '',\n port: null,\n path: parsePathStart(rest, true),\n query,\n fragment,\n };\n};\n\n/**\n * The basic URL parser (https://url.spec.whatwg.org/#concept-basic-url-parser).\n * Throws `TypeError: Invalid URL` where the standard returns failure.\n */\nexport const parseUrl = (rawInput: string, base?: UrlRecord): UrlRecord => {\n // Leading and trailing C0 controls and spaces are dropped, and tabs and\n // newlines are ignored anywhere, so a URL wrapped across lines still parses.\n const input = rawInput\n // oxlint-disable-next-line no-control-regex -- the standard trims C0 controls and spaces\n .replace(/^[\\u0000- ]+|[\\u0000- ]+$/g, '')\n .replace(/[\\t\\n\\r]/g, '');\n\n const schemeMatch = SCHEME.exec(input);\n if (schemeMatch) {\n const scheme = schemeMatch[0].slice(0, -1).toLowerCase();\n const rest = input.slice(schemeMatch[0].length);\n if (scheme === 'file') return parseFile(rest, base);\n if (isSpecialScheme(scheme)) {\n // Against a base with the same scheme, only `//` starts a host:\n // `http:path` and `http:/path` resolve against the base like `path`\n // and `/path` would.\n if (base?.scheme === scheme && !rest.startsWith('//')) {\n return parseRelative(rest, base);\n }\n // Otherwise any run of slashes and backslashes before the host is\n // skipped, so `http:example.com` and `http:\\\\example.com` parse like\n // `http://example.com`, as in browsers.\n return parseAuthority(scheme, rest.replace(/^[/\\\\]*/, ''));\n }\n if (rest.startsWith('//')) return parseAuthority(scheme, rest.slice(2));\n const { rest: path, query, fragment } = splitQueryAndFragment(rest, false);\n return {\n scheme,\n username: '',\n password: '',\n host: null,\n port: null,\n path: path.startsWith('/')\n ? parsePathStart(path, false)\n : percentEncode(path, C0_CONTROL_SET),\n query,\n fragment,\n };\n }\n\n if (!base) throw invalidUrl();\n if (typeof base.path === 'string') {\n // An opaque base (`mailto:x`) can only take a fragment.\n if (!input.startsWith('#')) throw invalidUrl();\n return { ...base, fragment: percentEncode(input.slice(1), FRAGMENT_SET) };\n }\n if (base.scheme === 'file') return parseFile(input, base);\n return parseRelative(input, base);\n};\n\n/**\n * Serializes the path as `pathname` reports it: an opaque path as written,\n * otherwise `/` before each segment, so `['a', '']` is `/a/`.\n */\nexport const serializePath = ({ path }: UrlRecord): string =>\n typeof path === 'string'\n ? path\n : path.map((segment) => `/${segment}`).join('');\n\n/**\n * The URL serializer (https://url.spec.whatwg.org/#concept-url-serializer).\n *\n * Its output is `href`, and parsing it again gives the same record, which is\n * what lets code compare URLs by their `href`.\n */\nexport const serializeUrl = (url: UrlRecord): string => {\n let output = `${url.scheme}:`;\n if (url.host !== null) {\n output += '//';\n if (url.username !== '' || url.password !== '') {\n output += url.username;\n if (url.password !== '') output += `:${url.password}`;\n output += '@';\n }\n output += url.host;\n if (url.port !== null) output += `:${url.port}`;\n } else if (\n typeof url.path !== 'string' &&\n url.path.length > 1 &&\n url.path[0] === ''\n ) {\n // Without this, `foo:/.//bar` would serialize to `foo://bar`, whose\n // `bar` would then parse as a host.\n output += '/.';\n }\n output += serializePath(url);\n if (url.query !== null) output += `?${url.query}`;\n if (url.fragment !== null) output += `#${url.fragment}`;\n return output;\n};\n","import { formUrlEncode, percentDecode } from './percent-encoding';\n\ntype Entry = [name: string, value: string];\n\nexport type URLSearchParamsInit =\n | string\n | Iterable<readonly unknown[]>\n | Record<string, unknown>\n | LynxURLSearchParams\n | null;\n\n/**\n * Parses `application/x-www-form-urlencoded` (`a=1&b=x+y`).\n *\n * `+` becomes a space before percent-decoding, so an escaped plus (`%2B`)\n * still decodes to a literal `+`.\n */\nconst parseQuery = (query: string): Entry[] =>\n query\n .split('&')\n .filter((sequence) => sequence !== '')\n .map((sequence) => {\n const equalsIndex = sequence.indexOf('=');\n const name =\n equalsIndex === -1 ? sequence : sequence.slice(0, equalsIndex);\n const value = equalsIndex === -1 ? '' : sequence.slice(equalsIndex + 1);\n return [\n percentDecode(name.replace(/\\+/g, ' ')),\n percentDecode(value.replace(/\\+/g, ' ')),\n ];\n });\n\n/**\n * Lets the owning `URL` keep its query and its `searchParams` in sync without\n * exposing a public method for it. Only url.ts imports it.\n *\n * A symbol rather than a `#private` method because `#private` members can't be\n * reached from another class, and a named method would add non-standard API\n * that app code could start relying on.\n */\nexport const LINK_TO_URL = Symbol('linkToUrl');\n\n/**\n * `URLSearchParams` for runtimes that don't have it (Lynx's main thread), per\n * the WHATWG URL Standard (https://url.spec.whatwg.org/#interface-urlsearchparams).\n *\n * The iterators return a snapshot of the entries rather than a live view.\n * Code iterates the params straight away in practice, and snapshots avoid\n * the bookkeeping a live iterator needs when the list changes mid-iteration.\n *\n * Every name and value goes through `String()`, as the WebIDL conversion of\n * the native class's arguments does, so `params.set('page', 2)` stores `'2'`.\n */\nexport class LynxURLSearchParams {\n #entries: Entry[] = [];\n /** Writes the serialized params back to the owning URL's query. */\n #updateUrl: ((query: string) => void) | undefined;\n\n constructor(init: URLSearchParamsInit = '') {\n // Anything but an object is converted to a string, so `null` is the\n // query `null`, as in browsers.\n if (typeof init !== 'object' || init === null) {\n const query = String(init);\n this.#entries = parseQuery(\n query.startsWith('?') ? query.slice(1) : query,\n );\n } else if (\n typeof (init as Iterable<unknown>)[Symbol.iterator] === 'function'\n ) {\n for (const pair of init as Iterable<readonly unknown[]>) {\n const items = Array.from(pair);\n if (items.length !== 2) {\n throw new TypeError(\n \"Failed to construct 'URLSearchParams': Each query pair must be an iterable [name, value] tuple\",\n );\n }\n this.#entries.push([String(items[0]), String(items[1])]);\n }\n } else {\n for (const name of Object.keys(init)) {\n this.#entries.push([\n name,\n String((init as Record<string, unknown>)[name]),\n ]);\n }\n }\n }\n\n /**\n * Called by the owning URL: replaces the entries with those of `query`, and\n * registers `updateUrl` to receive every later change.\n */\n [LINK_TO_URL](query: string, updateUrl: (query: string) => void): void {\n this.#entries = parseQuery(query);\n this.#updateUrl = updateUrl;\n }\n\n get size(): number {\n return this.#entries.length;\n }\n\n append(name: string, value: string): void {\n this.#entries.push([String(name), String(value)]);\n this.#update();\n }\n\n delete(name: string, value?: string): void {\n const match = (entry: Entry) =>\n entry[0] === String(name) &&\n (value === undefined || entry[1] === String(value));\n this.#entries = this.#entries.filter((entry) => !match(entry));\n this.#update();\n }\n\n get(name: string): string | null {\n const entry = this.#entries.find(\n (candidate) => candidate[0] === String(name),\n );\n return entry ? entry[1] : null;\n }\n\n getAll(name: string): string[] {\n return this.#entries\n .filter((entry) => entry[0] === String(name))\n .map((entry) => entry[1]);\n }\n\n has(name: string, value?: string): boolean {\n return this.#entries.some(\n (entry) =>\n entry[0] === String(name) &&\n (value === undefined || entry[1] === String(value)),\n );\n }\n\n /**\n * Sets the first entry named `name` to `value` and removes the others, or\n * appends one if there is none.\n */\n set(name: string, value: string): void {\n const key = String(name);\n const index = this.#entries.findIndex((entry) => entry[0] === key);\n if (index === -1) {\n this.#entries.push([key, String(value)]);\n } else {\n this.#entries[index] = [key, String(value)];\n this.#entries = this.#entries.filter(\n (entry, entryIndex) => entryIndex <= index || entry[0] !== key,\n );\n }\n this.#update();\n }\n\n /**\n * Stable-sorts by name, comparing UTF-16 code units as the standard does.\n *\n * Entries are tagged with their position to break ties, because\n * `Array.prototype.sort` was only required to be stable from ES2019, and\n * entries with the same name must keep their order.\n */\n sort(): void {\n this.#entries = this.#entries\n .map((entry, index) => ({ entry, index }))\n .sort((a, b) =>\n a.entry[0] < b.entry[0]\n ? -1\n : a.entry[0] > b.entry[0]\n ? 1\n : a.index - b.index,\n )\n .map(({ entry }) => entry);\n this.#update();\n }\n\n forEach(\n callback: (value: string, name: string, params: this) => void,\n thisArg?: unknown,\n ): void {\n // A copy, so a callback that changes the params can't skip or repeat\n // entries.\n for (const [name, value] of this.#entries.slice()) {\n callback.call(thisArg, value, name, this);\n }\n }\n\n entries(): IterableIterator<[string, string]> {\n return this.#entries\n .map((entry): [string, string] => [entry[0], entry[1]])\n [Symbol.iterator]();\n }\n\n keys(): IterableIterator<string> {\n return this.#entries.map((entry) => entry[0])[Symbol.iterator]();\n }\n\n values(): IterableIterator<string> {\n return this.#entries.map((entry) => entry[1])[Symbol.iterator]();\n }\n\n [Symbol.iterator](): IterableIterator<[string, string]> {\n return this.entries();\n }\n\n toString(): string {\n return this.#entries\n .map(([name, value]) => `${formUrlEncode(name)}=${formUrlEncode(value)}`)\n .join('&');\n }\n\n /**\n * Writes every change back to the owning URL's query, so `url.href`\n * reflects `url.searchParams.set(...)` right away, as in browsers.\n */\n #update(): void {\n this.#updateUrl?.(this.toString());\n }\n}\n","import { parseHost } from './host';\nimport {\n FRAGMENT_SET,\n percentEncode,\n QUERY_SET,\n SPECIAL_QUERY_SET,\n USERINFO_SET,\n} from './percent-encoding';\nimport {\n defaultPort,\n findPortColon,\n isSpecialScheme,\n parsePathStart,\n parsePort,\n parseUrl,\n serializePath,\n serializeUrl,\n type UrlRecord,\n} from './url-record';\nimport { LINK_TO_URL, LynxURLSearchParams } from './url-search-params';\n\n/**\n * `URL` for runtimes that don't have it, following the WHATWG URL Standard\n * (https://url.spec.whatwg.org/#url-class).\n *\n * Lynx's main thread (PrimJS) has no `URL` global, but Angular needs one:\n * since 22.2 the Router serializes every URL through\n * `new URL(url, 'http://fake')` to reject protocol-relative URLs, and treats\n * the `ReferenceError` as an unsafe URL. Every URL then serialized to `/`, so\n * each navigation looked like a navigation to the current URL and was\n * skipped. HttpClient and NgOptimizedImage's loaders use `URL` too.\n *\n * Known gaps, none of which Angular relies on: domains get lowercasing and\n * Punycode rather than the full UTS #46 mapping, `file:` URLs ignore Windows\n * drive letters, and `blob:` URLs only report the origin of an http(s) inner\n * URL.\n */\nexport class LynxURL {\n #url: UrlRecord;\n // One object for the URL's lifetime: `url.searchParams === url.searchParams`\n // in browsers, and code holding on to it must see later `search` changes.\n // `#linkSearchParams` refreshes its entries instead of replacing it.\n readonly #searchParams = new LynxURLSearchParams();\n\n constructor(\n url: string | { toString(): string },\n base?: string | { toString(): string },\n ) {\n this.#url = parseUrl(\n String(url),\n base === undefined ? undefined : parseUrl(String(base)),\n );\n this.#linkSearchParams();\n }\n\n static canParse(url: string, base?: string): boolean {\n try {\n new LynxURL(url, base);\n return true;\n } catch {\n return false;\n }\n }\n\n static parse(url: string, base?: string): LynxURL | null {\n try {\n return new LynxURL(url, base);\n } catch {\n return null;\n }\n }\n\n get href(): string {\n return serializeUrl(this.#url);\n }\n\n set href(value: string) {\n // `parseUrl` throws before the assignment, so an invalid `href` leaves the\n // URL unchanged and throws, as the native setter does.\n this.#url = parseUrl(String(value));\n this.#linkSearchParams();\n }\n\n get origin(): string {\n const { scheme, host, port } = this.#url;\n // A `blob:` URL created by a page carries that page's URL as its path, and\n // shares its origin, so blob URLs pass same-origin checks.\n if (scheme === 'blob') {\n const inner = LynxURL.parse(serializePath(this.#url));\n return inner && /^https?:$/.test(inner.protocol) ? inner.origin : 'null';\n }\n if (!isSpecialScheme(scheme) || scheme === 'file') return 'null';\n // Special URLs other than file: always have a host.\n return `${scheme}://${host as string}${port === null ? '' : `:${port}`}`;\n }\n\n get protocol(): string {\n return `${this.#url.scheme}:`;\n }\n\n set protocol(value: string) {\n // Browsers accept `https`, `https:` and even `https:anything`: only the\n // scheme before the first `:` is used. Anything else that isn't a valid\n // scheme leaves the URL unchanged.\n const match = /^([a-zA-Z][a-zA-Z0-9+\\-.]*)(:|$)/.exec(\n String(value).replace(/[\\t\\n\\r]/g, ''),\n );\n if (!match) return;\n const scheme = (match[1] as string).toLowerCase();\n const url = this.#url;\n // A URL can't switch between special and non-special schemes, since they\n // parse differently, nor become `file:` while it has credentials or a\n // port, which file URLs can't have.\n if (isSpecialScheme(url.scheme) !== isSpecialScheme(scheme)) return;\n if (\n scheme === 'file' &&\n (url.username !== '' || url.password !== '' || url.port !== null)\n ) {\n return;\n }\n if (url.scheme === 'file' && url.host === '') return;\n url.scheme = scheme;\n if (url.port === defaultPort(scheme)) url.port = null;\n }\n\n get username(): string {\n return this.#url.username;\n }\n\n set username(value: string) {\n if (this.#cannotHaveCredentialsOrPort()) return;\n this.#url.username = percentEncode(String(value), USERINFO_SET);\n }\n\n get password(): string {\n return this.#url.password;\n }\n\n set password(value: string) {\n if (this.#cannotHaveCredentialsOrPort()) return;\n this.#url.password = percentEncode(String(value), USERINFO_SET);\n }\n\n get host(): string {\n const { host, port } = this.#url;\n if (host === null) return '';\n return port === null ? host : `${host}:${port}`;\n }\n\n set host(value: string) {\n this.#setHost(String(value), true);\n }\n\n get hostname(): string {\n return this.#url.host ?? '';\n }\n\n set hostname(value: string) {\n this.#setHost(String(value), false);\n }\n\n get port(): string {\n return this.#url.port === null ? '' : String(this.#url.port);\n }\n\n set port(value: string) {\n if (this.#cannotHaveCredentialsOrPort()) return;\n const input = String(value).replace(/[\\t\\n\\r]/g, '');\n if (input === '') {\n this.#url.port = null;\n return;\n }\n // Like browsers, take the leading digits and ignore the rest (`8080abc`).\n const digits = /^[0-9]+/.exec(input);\n if (!digits) return;\n try {\n this.#url.port = parsePort(this.#url.scheme, digits[0]);\n } catch {\n // Out of range: the setter leaves the port unchanged.\n }\n }\n\n get pathname(): string {\n return serializePath(this.#url);\n }\n\n set pathname(value: string) {\n const url = this.#url;\n if (typeof url.path === 'string') return;\n const input = String(value).replace(/[\\t\\n\\r]/g, '');\n // A host-less URL keeps at least `/`, so `foo:/x` can't turn into an\n // opaque `foo:`.\n url.path =\n input === '' && url.host === null\n ? ['']\n : parsePathStart(input, isSpecialScheme(url.scheme));\n }\n\n get search(): string {\n const { query } = this.#url;\n return query === null || query === '' ? '' : `?${query}`;\n }\n\n set search(value: string) {\n // Setting `''` removes the query (no `?` left in `href`), and a leading\n // `?` is optional, as in browsers. Tabs and newlines are dropped like the\n // parser drops them.\n const input = String(value).replace(/[\\t\\n\\r]/g, '');\n if (input === '') {\n this.#url.query = null;\n } else {\n this.#url.query = percentEncode(\n input.startsWith('?') ? input.slice(1) : input,\n isSpecialScheme(this.#url.scheme) ? SPECIAL_QUERY_SET : QUERY_SET,\n );\n }\n this.#linkSearchParams();\n }\n\n get searchParams(): LynxURLSearchParams {\n return this.#searchParams;\n }\n\n get hash(): string {\n const { fragment } = this.#url;\n return fragment === null || fragment === '' ? '' : `#${fragment}`;\n }\n\n set hash(value: string) {\n // Same rules as `search`: `''` removes the fragment, a leading `#` is\n // optional.\n const input = String(value).replace(/[\\t\\n\\r]/g, '');\n this.#url.fragment =\n input === ''\n ? null\n : percentEncode(\n input.startsWith('#') ? input.slice(1) : input,\n FRAGMENT_SET,\n );\n }\n\n toString(): string {\n return this.href;\n }\n\n toJSON(): string {\n return this.href;\n }\n\n /**\n * URLs without a host, with an empty host, or `file:` URLs.\n */\n #cannotHaveCredentialsOrPort(): boolean {\n const { host, scheme } = this.#url;\n return host === null || host === '' || scheme === 'file';\n }\n\n /**\n * The `host` and `hostname` setters. Invalid input leaves the URL\n * unchanged, as the standard's setters do.\n */\n #setHost(value: string, withPort: boolean): void {\n const url = this.#url;\n if (typeof url.path === 'string') return;\n const special = isSpecialScheme(url.scheme);\n // Anything from the first path, query or fragment delimiter on is ignored.\n const input = value\n .replace(/[\\t\\n\\r]/g, '')\n .split(special ? /[/\\\\?#]/ : /[/?#]/)[0] as string;\n if (url.scheme === 'file') {\n // File URLs have no port, so a `:` makes the host invalid.\n try {\n const host = input === '' ? '' : parseHost(input, false);\n url.host = host === 'localhost' ? '' : host;\n } catch {\n // Invalid host: unchanged.\n }\n return;\n }\n const colonIndex = findPortColon(input);\n // `hostname` doesn't take a port, so `hostname = 'a:1'` is ignored.\n if (colonIndex !== -1 && !withPort) return;\n const hostInput = colonIndex === -1 ? input : input.slice(0, colonIndex);\n if (hostInput === '') {\n // Special URLs need a host, and so does a port or credentials.\n if (\n special ||\n colonIndex !== -1 ||\n url.username !== '' ||\n url.password !== '' ||\n url.port !== null\n ) {\n return;\n }\n }\n try {\n url.host = parseHost(hostInput, !special);\n } catch {\n // Invalid host: unchanged.\n return;\n }\n if (colonIndex === -1) return;\n // As with the `port` setter, only the leading digits count, and an\n // out-of-range port is ignored (the new host is still kept).\n // `[0-9]*` always matches, possibly the empty string.\n const [digits] = /^[0-9]*/.exec(\n input.slice(colonIndex + 1),\n ) as RegExpExecArray;\n if (digits === '') return;\n try {\n url.port = parsePort(url.scheme, digits);\n } catch {\n // Out of range: port unchanged.\n }\n }\n\n /**\n * Points `searchParams` at the current query, and writes changes back.\n *\n * Called whenever the query is replaced (construction, `href`, `search`).\n * An empty serialization becomes no query at all, so removing the last\n * param doesn't leave a dangling `?` in `href`.\n */\n #linkSearchParams(): void {\n this.#searchParams[LINK_TO_URL](this.#url.query ?? '', (query) => {\n this.#url.query = query === '' ? null : query;\n });\n }\n}\n","import { LynxURL } from './url';\nimport { LynxURLSearchParams } from './url-search-params';\n\nexport { LynxURL, LynxURLSearchParams };\n\n/**\n * Installs `URL` and `URLSearchParams` on `target` where it lacks them (Lynx's\n * main thread), keeping the platform's own implementations everywhere else.\n * Takes the global as a parameter so tests can pass a stand-in: replacing the\n * real `URL` would break the test runner's own module loading.\n */\nexport const installUrl = (target: {\n URL?: unknown;\n URLSearchParams?: unknown;\n}): void => {\n if (typeof target.URL === 'undefined') target.URL = LynxURL;\n if (typeof target.URLSearchParams === 'undefined') {\n target.URLSearchParams = LynxURLSearchParams;\n }\n};\n","/**\n * Environment polyfills for running Angular on the Lynx runtime.\n *\n * Lynx's PrimJS/Lepus context is not a browser: it has no DOM, no `window`, and\n * exposes timer/scheduling primitives on the `lynx` global rather than\n * `globalThis`. Angular (and its Router/forms/i18n/`@defer` machinery) assumes a\n * browser-shaped environment, so this module fills the gaps before bootstrap.\n *\n * Every shim is guarded by a `typeof … === 'undefined'`/`!== 'function'` check\n * so it is a no-op wherever the real API already exists (the web preview, jsdom,\n * or a browser main thread). Extracted from runtime.ts as one cohesive unit;\n * imported for its side effects only. Ordering matters (timers before\n * requestIdleCallback), so keep these blocks in sequence.\n */\n\nimport { installUrl } from './url';\n\n// Web-only: fail loud and clear when the page is not a secure context.\n//\n// cspell:disable-next-line\n// @lynx-js/web-core's engine chunk (kwift.*.js) calls crypto.randomUUID()\n// while registering handlers during startup, inside the background Web Worker\n// it spawns (new Worker(new URL('../background/index.js', import.meta.url))).\n// crypto.randomUUID() — like SharedArrayBuffer, which web-core also needs for\n// synchronous native-module calls — is a SECURE-CONTEXT-ONLY Web API: the\n// `crypto` object still exists (so crypto.getRandomValues works) but\n// crypto.randomUUID is simply absent. Opening the preview over an insecure\n// origin — e.g. the \"Network\" http://<LAN-IP>:<port> URL the dev server prints\n// alongside \"Local\" — therefore makes web-core throw a cryptic\n// \"crypto.randomUUID is not a function\" deep inside Lynx's own engine code,\n// which we neither ship nor can patch, and which runs before any of our code in\n// web-core's worker (so it cannot be polyfilled). The only fix is to load from\n// a secure context. localhost and 127.0.0.1 always qualify; any HTTPS origin\n// does too. Surface that here instead of leaving the developer with the\n// third-party stack trace. __WEB__ is a compile-time define (false on native),\n// so this block is dead-code-eliminated from native bundles — native unchanged.\nif (__WEB__ && globalThis.isSecureContext === false) {\n console.error(\n '[angular-lynx] The web preview is not running in a secure context, so ' +\n 'crypto.randomUUID() and SharedArrayBuffer are unavailable and ' +\n '@lynx-js/web-core will crash on startup (\"crypto.randomUUID is not a ' +\n 'function\"). Open the preview from a secure origin: use the \"Local\" ' +\n 'http://localhost:<port> URL, not the \"Network\" http://<LAN-IP>:<port> ' +\n 'URL (or serve over HTTPS).',\n );\n}\n\n// Angular Router v21+ uses AbortController in its navigation pipeline.\n// The rsbuild plugin's polyfills.js provides this as preEntry, but this\n// defensive polyfill covers consumers not using the plugin.\nif (typeof AbortController === 'undefined') {\n class LynxAbortSignal {\n aborted = false;\n reason: unknown = undefined;\n _listeners: ((event: { type: string }) => void)[] = [];\n addEventListener(\n type: string,\n listener: (event: { type: string }) => void,\n ) {\n if (type === 'abort') this._listeners.push(listener);\n }\n removeEventListener(\n type: string,\n listener: (event: { type: string }) => void,\n ) {\n if (type === 'abort') {\n this._listeners = this._listeners.filter((l) => l !== listener);\n }\n }\n dispatchEvent(event: { type: string }) {\n if (event.type === 'abort') {\n for (const listener of this._listeners.slice()) {\n listener(event);\n }\n }\n return true;\n }\n throwIfAborted() {\n if (this.aborted) throw this.reason;\n }\n }\n (globalThis as any).AbortSignal = LynxAbortSignal;\n (globalThis as any).AbortController = class LynxAbortController {\n signal = new LynxAbortSignal();\n abort(reason?: unknown) {\n if (this.signal.aborted) return;\n this.signal.aborted = true;\n if (reason === undefined) {\n const err = new Error('This operation was aborted');\n err.name = 'AbortError';\n reason = err;\n }\n this.signal.reason = reason;\n this.signal.dispatchEvent({ type: 'abort' });\n }\n };\n}\n\n// Lynx's main thread (PrimJS) has no `URL` or `URLSearchParams`. Since 22.2,\n// Angular's Router serializes every URL through `new URL(url, 'http://fake')`\n// to reject protocol-relative URLs, and treats the ReferenceError as such a\n// URL, so every URL serialized to `/`. Each navigation then looked like a\n// navigation to the current URL and was skipped (NavigationSkipped): no route\n// could be opened on device, lazy or not. HttpClient and NgOptimizedImage's\n// loaders use `URL` as well.\ninstallUrl(globalThis);\n\n// Angular core uses queueMicrotask for effect scheduling and change detection.\n// React Lynx polyfills this from lynx.queueMicrotask (see motion/src/polyfill/shim.ts).\nif (typeof globalThis.queueMicrotask !== 'function') {\n if (typeof lynx !== 'undefined' && (lynx as any).queueMicrotask) {\n (globalThis as any).queueMicrotask = (lynx as any).queueMicrotask;\n } else {\n const resolved = Promise.resolve();\n (globalThis as any).queueMicrotask = (fn: () => void) => {\n resolved.then(fn).catch((err: unknown) => {\n setTimeout(() => {\n throw err;\n }, 0);\n });\n };\n }\n}\n\n// Angular's i18n runtime (applyCreateOpCodes / applyMutableOpCodes in\n// @angular/core) branches on the DOM `Node` interface's node-type constants\n// (Node.COMMENT_NODE / Node.TEXT_NODE / Node.ELEMENT_NODE) to decide whether an\n// i18n opcode creates a comment, text, or element node. Any component with an\n// `i18n` attribute or a `$localize` string emits these opcodes at bootstrap;\n// Lynx's PrimJS has no DOM, so `Node` is undefined and the first opcode throws\n// \"Node is not defined\", aborting bootstrap. The rsbuild plugin's polyfills.js\n// provides this as preEntry — this defensive copy covers consumers not using\n// the plugin. Must be a class (not a plain object): Angular does `x instanceof\n// Node` in a few dev/debug paths, which throws on a non-callable right-hand\n// side; as a class it correctly returns false for Lynx elements while the\n// static constants (all the opcode dispatcher reads) resolve to spec values.\n// The shim alone is the complete fix: once `Node` resolves the opcodes dispatch\n// to renderer.createComment() / createText(), which the renderer already\n// implements (they also back @if/@for anchors and {{ }} interpolation). The\n// `typeof Node === 'undefined'` guard makes it a no-op on the web, where `Node`\n// is the real DOM global.\nif (typeof Node === 'undefined') {\n try {\n class LynxNode {}\n Object.assign(LynxNode, {\n ELEMENT_NODE: 1,\n ATTRIBUTE_NODE: 2,\n TEXT_NODE: 3,\n CDATA_SECTION_NODE: 4,\n PROCESSING_INSTRUCTION_NODE: 7,\n COMMENT_NODE: 8,\n DOCUMENT_NODE: 9,\n DOCUMENT_TYPE_NODE: 10,\n DOCUMENT_FRAGMENT_NODE: 11,\n DOCUMENT_POSITION_DISCONNECTED: 1,\n DOCUMENT_POSITION_PRECEDING: 2,\n DOCUMENT_POSITION_FOLLOWING: 4,\n DOCUMENT_POSITION_CONTAINS: 8,\n DOCUMENT_POSITION_CONTAINED_BY: 16,\n DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 32,\n });\n (globalThis as any).Node = LynxNode;\n } catch {\n // Read-only where Node is a non-configurable global (web main thread) —\n // Node already exists there, nothing to do.\n }\n}\n\nif (typeof document === 'undefined') {\n (globalThis as any).document = {\n // BrowserPlatformLocation uses document.defaultView to get the window\n // for addEventListener('popstate'/'hashchange'). Point to our window mock.\n defaultView: globalThis,\n // getBaseHrefFromDOM() calls document.querySelector('base').\n // Return null so Angular falls back to APP_BASE_HREF (provided in provideRenderer).\n querySelector: () => null,\n };\n}\n\ntry {\n if (typeof window === 'undefined') {\n (globalThis as any).window = globalThis;\n }\n} catch {\n // Read-only in web environment (lynx-view shadows window=void 0 but\n // globalThis.window is a non-configurable getter on the Window object)\n}\n\n// Angular's DefaultValueAccessor (from @angular/forms) is instantiated on every\n// <input [formControl]> / <textarea [formControl]> element — even when our custom\n// LynxInputValueAccessor is the *selected* accessor, DefaultValueAccessor still\n// gets created because its selector matches. Its constructor calls _isAndroid()\n// → getDOM().getUserAgent() → BrowserDomAdapter.getUserAgent(), which reads\n// window.navigator.userAgent. Lynx has no navigator global, so this throws a\n// TypeError that crashes the component mid-creation, blanks the page, and\n// corrupts the Router state (making subsequent routes also blank).\n// In a Web Worker (e.g. @lynx-js/go-web preview), `navigator` is a read-only\n// getter on WorkerGlobalScope — assignment throws. Only polyfill when it's\n// truly missing (native Lynx background thread).\ntry {\n if (typeof navigator === 'undefined') {\n (globalThis as any).navigator = { userAgent: '' };\n }\n} catch {\n // navigator exists as a read-only property (Web Worker) — no polyfill needed\n}\n\n// BrowserPlatformLocation.onPopState/onHashChange call window.addEventListener.\n// Lynx runtime doesn't have this API, so stub it out as a no-op.\nif (typeof globalThis.addEventListener !== 'function') {\n (globalThis as any).addEventListener = () => {};\n}\nif (typeof globalThis.removeEventListener !== 'function') {\n (globalThis as any).removeEventListener = () => {};\n}\n\n// Lynx provides timer/scheduling APIs on the `lynx` global, not on `globalThis`.\n// Angular's zoneless ChangeDetectionScheduler uses setTimeout to schedule CD\n// after markForCheck(). Without these polyfills, CD never fires after the initial\n// synchronous render, so dynamic content (RouterOutlet, signal updates) never appears.\n// React Lynx does the same polyfill — see @lynx-js/react worklet-runtime/api/lynxApi.ts.\nif (\n typeof globalThis.setTimeout !== 'function' &&\n typeof lynx !== 'undefined'\n) {\n const _lynx = lynx as any;\n (globalThis as any).setTimeout = _lynx.setTimeout;\n (globalThis as any).setInterval = _lynx.setInterval;\n (globalThis as any).clearTimeout = _lynx.clearTimeout;\n (globalThis as any).clearInterval =\n _lynx.clearInterval ?? _lynx.clearTimeInterval;\n if (_lynx.requestAnimationFrame) {\n (globalThis as any).requestAnimationFrame = _lynx.requestAnimationFrame;\n }\n if (_lynx.cancelAnimationFrame) {\n (globalThis as any).cancelAnimationFrame = _lynx.cancelAnimationFrame;\n }\n}\n\n// Angular's `@defer (on idle)` trigger schedules work through its internal\n// RequestIdleCallbackService. On any platform that lacks `requestIdleCallback`\n// Angular falls back to `cb => setTimeout(cb)` and then, inside IdleScheduler,\n// reads `deadline.timeRemaining()` on whatever object the scheduled callback was\n// invoked with. Browsers invoke it with a real IdleDeadline; Lynx does NOT —\n// its native `setTimeout` calls the callback with an *empty object* (the Lepus\n// runtime dispatches timed tasks with `Dictionary::Create()` — see\n// core/runtime/lepus/tasks/lepus_callback_manager.cc `SetTimeTask`). So\n// `deadline.timeRemaining` is `undefined`, and Angular's `deadline.timeRemaining()`\n// call throws \"TypeError: not a function\", crashing the main-thread frame the\n// instant an `@defer (on idle)` block renders. This is main-thread-only: the web\n// build has a genuine requestIdleCallback and never reaches the fallback, which is\n// why the same demo works in the browser preview but dies on-device.\n//\n// Fix: supply a matched requestIdleCallback/cancelIdleCallback pair that hands the\n// callback a correctly-shaped IdleDeadline. We define BOTH (never just one) because\n// Angular reuses the single `typeof requestIdleCallback !== 'undefined'` guard to\n// pick cancelIdleCallback too — a lone requestIdleCallback would make it bind an\n// undefined cancelIdleCallback. Defined after the timer polyfill above so\n// setTimeout/clearTimeout are already resolvable on both threads.\nif (\n typeof (globalThis as any).requestIdleCallback !== 'function' ||\n typeof (globalThis as any).cancelIdleCallback !== 'function'\n) {\n (globalThis as any).requestIdleCallback = (\n callback: (deadline: {\n didTimeout: boolean;\n timeRemaining: () => number;\n }) => void,\n ): number =>\n // A fresh idle period reports ~50ms remaining in browsers; returning a\n // positive value lets Angular's IdleScheduler drain its whole queue in one\n // pass rather than treating the period as already exhausted (which would make\n // it re-schedule endlessly). setTimeout(_, 0) mirrors the zoneless CD\n // scheduler's own use of a macrotask elsewhere in this file.\n setTimeout(\n () => callback({ didTimeout: false, timeRemaining: () => 50 }),\n 0,\n ) as unknown as number;\n (globalThis as any).cancelIdleCallback = (id: number): void =>\n clearTimeout(id as unknown as ReturnType<typeof setTimeout>);\n}\n","/**\n * Opcode format for Lynx SSR snapshot serialization.\n * Mirrors the opcode types used by React Lynx's renderToOpcodes system —\n * the Lynx engine expects this format from ssrEncode().\n */\nexport const enum Opcode {\n Begin = 0,\n End = 1,\n Attr = 2,\n Text = 3,\n}\n\n/**\n * Builds a flat opcode array in the format expected by ssrEncode().\n * The array is a packed sequence of [opcode, ...args] tuples concatenated\n * without delimiters. The consumer (buildElementQueueFromOpcodes) advances\n * by the fixed arg count for each opcode type.\n * Example: [Begin, \"0\", \"view\", Attr, \"style\", \"color:red\", End]\n */\nexport class OpcodeRecorder {\n readonly opcodes: unknown[] = [];\n #nextSsrId = 0;\n\n nextId(): string {\n return String(this.#nextSsrId++);\n }\n\n begin(ssrId: string, tag: string): void {\n this.opcodes.push(Opcode.Begin, ssrId, tag);\n }\n\n end(): void {\n this.opcodes.push(Opcode.End);\n }\n\n attr(key: string, value: unknown): void {\n this.opcodes.push(Opcode.Attr, key, value);\n }\n\n text(ssrId: string, content: string): void {\n this.opcodes.push(Opcode.Text, ssrId, content);\n }\n}\n","import type { ElementRef } from '../types/lynx';\nimport { Opcode } from './opcodes';\n\n/**\n * Parses the opcode stream produced by ssrEncode and maps each ssrId to its\n * native ElementRef via the refs map from __GetTemplateParts(). Returns an\n * ordered queue that LynxHydrateDocument consumes — one ElementRef per\n * createElement/createText/createComment call during Angular's bootstrap.\n */\nexport const buildElementQueueFromOpcodes = (\n opcodes: unknown[],\n refsMap: Record<string, ElementRef>,\n): ElementRef[] => {\n const queue: ElementRef[] = [];\n\n let i = 0;\n while (i < opcodes.length) {\n const opcode = opcodes[i];\n switch (opcode) {\n case Opcode.Begin: {\n // Begin: [opcode, ssrId, tag]\n const ssrId = opcodes[i + 1] as string;\n const ref = refsMap[ssrId];\n if (ref) {\n queue.push(ref);\n }\n i += 3;\n break;\n }\n case Opcode.End: {\n i += 1;\n break;\n }\n case Opcode.Attr: {\n // Attr: [opcode, key, value]\n i += 3;\n break;\n }\n case Opcode.Text: {\n // Text: [opcode, ssrId, content]\n const ssrId = opcodes[i + 1] as string;\n const ref = refsMap[ssrId];\n if (ref) {\n queue.push(ref);\n }\n i += 3;\n break;\n }\n default:\n i += 1;\n }\n }\n\n return queue;\n};\n","import type { ElementRef } from '../types/lynx';\nimport type { OpcodeRecorder } from './opcodes';\n\n/**\n * Walks the native Lynx element tree after Angular's initial render and\n * produces an opcode stream that the Lynx engine can store as a snapshot.\n * Each element is also marked via __MarkPartElement so the engine can\n * reconstruct the ElementRef→ssrId mapping during hydration.\n */\nexport const serializeElementTree = (\n root: ElementRef,\n recorder: OpcodeRecorder,\n): void => {\n __MarkTemplateElement(root);\n serializeNode(root, recorder);\n};\n\nconst serializeNode = (element: ElementRef, recorder: OpcodeRecorder): void => {\n const tag = __GetTag(element);\n\n // raw-text nodes are leaf text nodes — serialize with Text opcode\n if (tag === 'raw-text' || tag === 'rawtextelement') {\n const ssrId = recorder.nextId();\n __MarkPartElement(element, ssrId);\n const textContent = __GetAttributeByName(element, 'textContent') ?? '';\n recorder.text(ssrId, String(textContent));\n return;\n }\n\n const ssrId = recorder.nextId();\n __MarkPartElement(element, ssrId);\n recorder.begin(ssrId, tag);\n\n const attrs = __GetAttributes(element);\n for (const key in attrs) {\n const value = attrs[key];\n if (value != null && typeof value !== 'function') {\n recorder.attr(key, value);\n }\n }\n\n const classes = __GetClasses(element);\n if (classes.length > 0) {\n recorder.attr('class', classes.join(' '));\n }\n\n // __GetInlineStyles was added in a newer Lynx build — fall back to the\n // DOM-style `.style.cssText` property on older builds that lack the PAPI.\n // In Vitest we stub __GetInlineStyles as a function, so the else-branch is\n // unreachable — it exists for real Lynx runtimes older than the PAPI addition.\n /* v8 ignore next 4 */\n const inlineStyles =\n typeof __GetInlineStyles === 'function'\n ? __GetInlineStyles(element)\n : (element as any).style?.cssText;\n if (inlineStyles) {\n recorder.attr('style', inlineStyles);\n }\n\n const children = __GetChildren(element);\n for (const child of children) {\n serializeNode(child, recorder);\n }\n\n recorder.end();\n};\n","import { __pageElementRef } from '../lynx-document';\nimport { buildElementQueueFromOpcodes } from './build-element-queue';\nimport { OpcodeRecorder } from './opcodes';\nimport { serializeElementTree } from './serialize-tree';\n\n/**\n * SSR (Instant First-Frame Rendering) engine callbacks.\n *\n * Kept as plain exported functions — separate from the `if (__ENABLE_SSR__)`\n * registration in global-callbacks.ts — so the orchestration logic (the guard\n * throws + snapshot wiring) is unit-testable without flipping the compile-time\n * `__ENABLE_SSR__` define. The Lynx engine calls these by name (via the globals\n * global-callbacks installs) to snapshot the element tree after the first render\n * (encode) and to reconnect Angular to pre-existing native elements on\n * subsequent loads (hydrate).\n */\n\n/**\n * Walk the native element tree Angular just rendered and return an opcode-stream\n * snapshot the engine can persist. Throws if called before the page element\n * exists — the engine must only invoke this after the first render.\n */\nexport const ssrEncode = (): string => {\n if (!__pageElementRef) {\n throw new Error(\n 'ssrEncode called before Angular rendered the page element',\n );\n }\n const recorder = new OpcodeRecorder();\n serializeElementTree(__pageElementRef, recorder);\n return JSON.stringify({ __opcodes: recorder.opcodes });\n};\n\n/**\n * Rebuild the ElementRef queue from a persisted snapshot and stash it (plus the\n * hydrating flag + page element) on globals for LynxHydrateDocument to consume\n * during Angular's bootstrap. Cleared automatically once hydration completes.\n */\nexport const ssrHydrate = (info: string): void => {\n const nativePage = __GetPageElement();\n if (!nativePage) {\n throw new Error('SSR hydration failed: no page element from snapshot');\n }\n const refsMap = __GetTemplateParts(nativePage);\n const { __opcodes } = JSON.parse(info) as { __opcodes: unknown[] };\n const elementQueue = buildElementQueueFromOpcodes(__opcodes, refsMap);\n\n (globalThis as any).__LYNX_IS_HYDRATING__ = true;\n (globalThis as any).__LYNX_HYDRATE_PAGE__ = nativePage;\n (globalThis as any).__LYNX_HYDRATE_QUEUE__ = elementQueue;\n};\n","import { MainThreadElement } from './main-thread/main-thread-element';\n\n/**\n * Worklet registry state + the pure param transform shared by every worklet\n * entry point.\n *\n * Kept in its own module (rather than inline in runtime.ts) so the worklet\n * registry is a single, importable source of truth: the global callbacks that\n * register/invoke worklets (global-callbacks.ts), the cross-thread RPC bridge,\n * and bootstrapApplication's HMR reset all reference these exact maps. Nothing\n * here touches `globalThis` — that keeps `transformParams` a pure function that\n * can be unit-tested directly, without booting the whole runtime.\n */\n\n/**\n * Worklet registry — `mainThreadFn()`/`backgroundFn()` register functions here\n * on their owning thread; the native engine invokes them via `runWorklet` when\n * MTS events fire.\n */\nexport const __workletMap: Record<string, Function> = {};\n\n/**\n * MainThreadRef store, keyed by `_wvid`. `transformParams` reconstitutes a ref\n * from this map when it sees a `{ _wvid }` marker in event params, and\n * MainThreadRef registers itself here on creation.\n */\nexport const __mainThreadRefMap: Record<number, { current: unknown }> = {};\n\n/**\n * Pending cross-thread RPC Promises keyed by `resolveId`. Both the main- and\n * background-thread RPC listeners settle entries here when a return value\n * arrives, and LynxMainThread parks its resolvers here while a call is in\n * flight.\n */\nexport const __pendingResolvers: Record<\n number,\n { resolve: (v: unknown) => void; reject: (e: unknown) => void }\n> = {};\n\n// Monotonic id for correlating an outgoing RPC request with its response.\n// A module-local `let` cannot be mutated through an ES import binding, so the\n// counter is only ever advanced through `nextResolveId()`.\nlet __nextResolveId = 0;\n\n/**\n * Returns the next unique resolve id, advancing the counter. Exposed as a\n * function (not the raw `let`) so callers in other modules — and the\n * `__lynxMtsNextResolveId` global — share one monotonic sequence.\n */\nexport const nextResolveId = (): number => __nextResolveId++;\n\n/**\n * Recursively transforms raw Lynx event params into usable objects:\n * - Objects with `elementRefptr` become MainThreadElement wrappers\n * - Objects with `_wvid` resolve to their MainThreadRef instances\n *\n * Pure: reads `__mainThreadRefMap` but never mutates global state, so the whole\n * transform can be exercised in isolation.\n */\nexport const transformParams = (value: unknown): unknown => {\n if (typeof value !== 'object' || value === null) return value;\n if (Array.isArray(value)) return value.map(transformParams);\n const obj = value as Record<string, unknown>;\n if ('elementRefptr' in obj) {\n return new MainThreadElement(obj['elementRefptr'] as any);\n }\n if ('_wvid' in obj) {\n return __mainThreadRefMap[obj['_wvid'] as number] ?? obj;\n }\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = transformParams(obj[key]);\n }\n return result;\n};\n","import { Subject } from 'rxjs';\nimport { ssrEncode, ssrHydrate } from './ssr/ssr-callbacks';\nimport {\n __mainThreadRefMap,\n __pendingResolvers,\n __workletMap,\n nextResolveId,\n transformParams,\n} from './worklet-bridge';\n\n/**\n * Global callbacks the Lynx engine (and our own DI-instantiated services) invoke\n * by name. Grouped here — separate from bootstrapApplication and the environment\n * polyfills — because they share the worklet registry from worklet-bridge.ts and\n * are all installed as module-load side effects: the engine may call any of them\n * before Angular's bootstrap resolves. Imported for its side effects; only\n * `pageReady` is re-exported (bootstrapApplication awaits it).\n */\n\n/**\n * Resolves when the Lynx engine signals the page is ready to render.\n * `renderPage` (below) fires it; bootstrapApplication awaits it on the main\n * thread before handing control to Angular.\n */\nexport const pageReady = new Subject<void>();\n\n/**\n * Lynx lifecycle callbacks. The engine calls these globals at specific points:\n * - renderPage: called once when the page is ready to render. On the main thread,\n * bootstrapApplication() awaits this before calling Angular's bootstrap.\n * - updatePage: called when the host app sends updated data. No-op for now —\n * Angular's change detection handles reactivity via LynxInitData/LynxGlobalData.\n * - processData: called before data delivery for transformation. Overridden by\n * registerDataProcessors() if the app needs custom data processing.\n */\n// @ts-expect-error\nglobalThis.renderPage = () => {\n pageReady.next();\n};\n\n// @ts-expect-error\nglobalThis.updatePage = () => {};\n// @ts-expect-error\nglobalThis.processData = () => {};\n\n// SSR (Instant First-Frame Rendering) callbacks — called by the Lynx engine\n// to snapshot the element tree after the first render (encode) and to reconnect\n// Angular to pre-existing native elements on subsequent loads (hydrate). The\n// callback bodies live in ssr/ssr-callbacks.ts (unit-tested there); this only\n// wires them onto the engine globals when SSR is enabled.\nif (__ENABLE_SSR__) {\n (globalThis as any).ssrEncode = ssrEncode;\n (globalThis as any).ssrHydrate = ssrHydrate;\n}\n\nglobalThis.registerWorklet = (\n _type: string,\n id: string,\n fn: Function,\n): void => {\n __workletMap[id] = fn;\n};\n\nglobalThis.__workletRefMap = __mainThreadRefMap;\n\n// @ts-expect-error\nglobalThis.runWorklet = (ctx: unknown, params: unknown[]) => {\n // Legacy path: direct function callbacks (existing event handlers registered\n // via __AddEvent with a raw function value).\n if (typeof ctx === 'function') {\n return ctx(...params);\n }\n // Direct main-thread function handle: `{ _fn }`. Fiber-arch gesture callbacks\n // MUST be objects, not raw functions — the native binding stores a callable\n // callback in GestureCallback.lepus_function_, but the fiber-arch dispatch\n // (touch_event_handler.cc TriggerFiberElementWorklet) only reads\n // lepus_object_, so a function callback is silently dropped and the gesture\n // never fires. The LynxGestureDetector directive therefore wraps each callback\n // as `{ _fn }` (an object → lands in lepus_object_); we unwrap it here. Params\n // are forwarded as-is (like the raw-function path) — the native engine already\n // passes plain event objects.\n if (\n ctx &&\n typeof ctx === 'object' &&\n typeof (ctx as any)._fn === 'function'\n ) {\n return (ctx as any)._fn(...params);\n }\n // Worklet context path: look up by _wkltId\n if (ctx && typeof ctx === 'object' && '_wkltId' in ctx) {\n const fn = __workletMap[(ctx as { _wkltId: string })._wkltId];\n if (fn) {\n const transformed = params.map(transformParams);\n return fn(...transformed);\n }\n if (__DEV__) {\n console.warn(\n `[angular-lynx] Worklet not found: ${(ctx as { _wkltId: string })._wkltId}`,\n );\n }\n }\n};\n\n// Cross-thread RPC system. Lynx's JSContext event system is bidirectional:\n// Main → Background: 'Lynx.Worklet.runOnBackground' (request) + 'Lynx.Worklet.BgFunctionCallRet' (response)\n// Background → Main: 'Lynx.Worklet.runWorkletCtx' (request) + 'Lynx.Worklet.FunctionCallRet' (response)\n// Each thread registers listeners for incoming requests AND for return values\n// from its own outgoing calls. resolveId ties each response to its Promise.\nif (__MAIN_THREAD__) {\n try {\n if (typeof lynx !== 'undefined' && (lynx as any).getJSContext) {\n (lynx as any)\n .getJSContext()\n .addEventListener(\n 'Lynx.Worklet.runWorkletCtx',\n (event: { data: string }) => {\n const { worklet, params, resolveId } = JSON.parse(event.data);\n const fn = __workletMap[worklet._wkltId];\n let returnValue: unknown;\n let error: string | undefined;\n try {\n returnValue = fn?.(...params);\n } catch (e) {\n error = String(e);\n }\n (lynx as any).getJSContext().dispatchEvent({\n type: 'Lynx.Worklet.FunctionCallRet',\n data: JSON.stringify({ resolveId, returnValue, error }),\n });\n },\n );\n\n // Listen for return values from background-thread function calls\n (lynx as any)\n .getJSContext()\n .addEventListener(\n 'Lynx.Worklet.BgFunctionCallRet',\n (event: { data: string }) => {\n const { resolveId, returnValue, error } = JSON.parse(event.data);\n const resolver = __pendingResolvers[resolveId];\n if (resolver) {\n delete __pendingResolvers[resolveId];\n if (error) {\n resolver.reject(new Error(error));\n } else {\n resolver.resolve(returnValue);\n }\n }\n },\n );\n }\n } catch {\n // lynx.getJSContext() may not be available in all environments\n }\n\n /**\n * Global runOnBackground — callable from main-thread worklet functions.\n * Dispatches a function call to the background thread and returns a Promise.\n */\n (globalThis as any).runOnBackground = (\n handle: { _wkltId: string },\n ...args: unknown[]\n ): Promise<unknown> => {\n const resolveId = nextResolveId();\n return new Promise((resolve, reject) => {\n __pendingResolvers[resolveId] = { resolve, reject };\n try {\n (lynx as any).getJSContext().dispatchEvent({\n type: 'Lynx.Worklet.runOnBackground',\n data: JSON.stringify({\n worklet: { _wkltId: handle._wkltId },\n params: args,\n resolveId,\n }),\n });\n } catch (e) {\n delete __pendingResolvers[resolveId];\n reject(e);\n }\n });\n };\n}\n\n// Cross-thread RPC: background thread listens for return values from main thread\n// AND for runOnBackground execution requests from main thread.\n//\n// The background thread reaches the main thread through getCoreContext(), not\n// getJSContext(): each thread talks to the *other* thread's context (see the\n// \"RuntimeProxy API summary\" in investigations/lynx-vs-web-differences.md, and\n// React Lynx's runtime/src/worklet/call/runOnBackground.ts). Listening on\n// getJSContext() here meant native runOnBackground() requests never arrived, so\n// main-thread code (every Angular event handler) could not reach\n// background-only APIs such as NativeModules.\nif (!__MAIN_THREAD__) {\n try {\n if (typeof lynx !== 'undefined' && (lynx as any).getCoreContext) {\n (lynx as any)\n .getCoreContext()\n .addEventListener(\n 'Lynx.Worklet.FunctionCallRet',\n (event: { data: string }) => {\n const { resolveId, returnValue, error } = JSON.parse(event.data);\n const resolver = __pendingResolvers[resolveId];\n if (resolver) {\n delete __pendingResolvers[resolveId];\n if (error) {\n resolver.reject(new Error(error));\n } else {\n resolver.resolve(returnValue);\n }\n }\n },\n );\n\n // Listen for runOnBackground requests from main thread\n (lynx as any)\n .getCoreContext()\n .addEventListener(\n 'Lynx.Worklet.runOnBackground',\n (event: { data: string }) => {\n const { worklet, params, resolveId } = JSON.parse(event.data);\n const fn = __workletMap[worklet._wkltId];\n let returnValue: unknown;\n let error: string | undefined;\n try {\n returnValue = fn?.(...params);\n } catch (e) {\n error = String(e);\n }\n (lynx as any).getCoreContext().dispatchEvent({\n type: 'Lynx.Worklet.BgFunctionCallRet',\n data: JSON.stringify({ resolveId, returnValue, error }),\n });\n },\n );\n }\n } catch {\n // lynx.getCoreContext() may not be available in all environments\n }\n}\n\n/**\n * Exposed for LynxMainThread service (main-thread.ts) to dispatch cross-thread\n * calls. Can't use import because these globals bridge module-load side effects\n * (this file) with a DI-instantiated consumer (LynxMainThread).\n */\nglobalThis.__lynxMtsPendingResolvers = __pendingResolvers;\nglobalThis.__lynxMtsNextResolveId = nextResolveId;\n\n/**\n * Synchronously invoke a registered worklet by its _wkltId with raw,\n * already-in-process args. Used by LynxMainThread.runOnMainThread() when it is\n * called from code that is ALREADY running on the main thread — e.g. an Angular\n * `(bind*)`/`(catch*)` event handler, which the renderer registers as a\n * main-thread worklet and Lynx therefore invokes on the Lepus thread. In that\n * situation there is no background→main thread hop to perform, so we run the\n * target worklet in-place instead of dispatching a cross-thread RPC that would\n * have no counterpart to answer it. Mirrors the cross-thread runWorkletCtx\n * listener above, which likewise calls the registered fn with unmodified params.\n * Exposed as a global (rather than imported) because the __workletMap is a\n * module-load side-effect while LynxMainThread is DI-instantiated later.\n */\nglobalThis.__lynxRunMainThreadWorklet = (\n wkltId: string,\n args: unknown[],\n): unknown => {\n const fn = __workletMap[wkltId];\n if (!fn) {\n throw new Error(`[angular-lynx] Main-thread worklet not found: ${wkltId}`);\n }\n return fn(...args);\n};\n","declare const __MAIN_THREAD__: boolean;\n\n/**\n * The lazy-bundle import mode the chunk-loading runtime passes through from\n * `import(..., { with: { mode } })`. Only FetchBundle (engine 3.9+) can honor it.\n */\ntype LazyBundleMode = 'sync' | 'async';\n\n/** The QueryComponent callback payload (`detail.schema` is the bundle URL). */\ntype QueryComponentResult = {\n code: number;\n detail: { schema: string };\n};\n\n/**\n * The parts of the background-thread `lynx` global the loader uses. They are\n * not all declared in `@lynx-js/types` (e.g. `getDynamicComponentExports`), so\n * they're typed here rather than reaching for `any` at each call site.\n */\ntype BackgroundLynx = {\n QueryComponent?: (\n source: string,\n callback: (result: QueryComponentResult) => void,\n ) => void;\n getNativeLynx(): {\n QueryComponent(\n source: string,\n callback: (result: QueryComponentResult) => void,\n ): void;\n };\n getApp(): { getDynamicComponentExports(schema: string): unknown };\n};\n\ntype LoadLazyBundle = (\n source: string,\n mode?: LazyBundleMode,\n) => Promise<unknown>;\n\n/**\n * Installs `lynx.loadLazyBundle`, the hook Lynx's chunk-loading runtime calls\n * for every async chunk (each `loadComponent()` route and `@defer` block).\n *\n * Since rspeedy 0.17 the Lynx build engine encodes async chunks as lazy\n * bundles (`lazy-bundle/*.bundle`) and its `ChunkLoadingWebpackPlugin` runtime\n * loads them through `lynx.loadLazyBundle(url, mode, host)`. The platform does\n * not provide that function — the framework does (React Lynx installs it from\n * `@lynx-js/react`'s `core/lynx/lazy-bundle.ts`). Without it every dynamic\n * import throws `lynx.loadLazyBundle is not a function`.\n *\n * This is a port of React Lynx's QueryComponent loader, which is what React\n * uses for the default `engineVersion` (below 3.9, where FetchBundle is\n * unavailable) — the same default this plugin's `targetSdkVersion` uses.\n *\n * Calling it again (HMR re-bootstraps call `bootstrapApplication` a second\n * time) is safe: it only reassigns the same stateless function.\n */\nexport const installLazyBundleLoader = (): void => {\n const host = lynx as unknown as { loadLazyBundle?: LoadLazyBundle };\n host.loadLazyBundle = loadLazyBundleWithQueryComponent;\n};\n\n/**\n * Dispatches by thread, because each thread has a different native API: the\n * main thread evaluates synchronously via `__QueryComponent`, the background\n * thread loads asynchronously via `lynx.QueryComponent`.\n *\n * The chunk-loading runtime also passes a third `host` argument. It is\n * deliberately ignored: it only routes FetchBundle's main-thread prepare step\n * to the right host, and QueryComponent has no such step.\n */\nconst loadLazyBundleWithQueryComponent: LoadLazyBundle = (source, mode) => {\n if (__MAIN_THREAD__) {\n return loadOnMainThread(source);\n }\n return loadOnBackgroundThread(source, mode);\n};\n\n/**\n * Main thread: `__QueryComponent` evaluates the bundle synchronously. The\n * returned promise gets a synchronous `then` so first-screen rendering can use\n * the module in the same tick — the main thread renders exactly once, so an\n * async resolution would arrive after the first screen is already committed.\n */\nconst loadOnMainThread = (source: string): Promise<unknown> => {\n let result: unknown;\n try {\n // The native PAPI ignores the callback on the main thread; it's only part\n // of the shared signature.\n result = __QueryComponent(source, () => {}).evalResult;\n } catch {\n // A rejected promise here would surface as an unhandled rejection (an\n // error overlay) for something the main thread can't recover from anyway. A\n // never-settling promise matches React Lynx: the lazy content simply isn't\n // part of the first screen, and the background thread loads it instead.\n return new Promise(() => {});\n }\n return syncResolved(result);\n};\n\n/**\n * Background thread: `QueryComponent` fetches and evaluates the bundle, then\n * the exports are read back by schema. A cached bundle calls back\n * synchronously, in which case the result is also handed back with a sync\n * `then` (as React Lynx does) so already-loaded routes don't pay a microtask.\n */\nconst loadOnBackgroundThread = (\n source: string,\n mode: LazyBundleMode | undefined,\n): Promise<unknown> => {\n if (__DEV__ && mode !== undefined) {\n // Same guard as React Lynx: honoring `mode` needs FetchBundle, so silently\n // ignoring it would load a `sync` import asynchronously.\n throw new Error(\n `Lazy bundle import \\`mode: '${mode}'\\` requires FetchBundle, but the current build uses QueryComponent.`,\n );\n }\n\n const bgLynx = lynx as unknown as BackgroundLynx;\n // QueryComponent may invoke the callback synchronously (bundle already\n // cached) or later (bundle still downloading), and we can't tell which up\n // front. So the callback records a synchronous outcome in\n // `syncResult`/`syncError`, and only once QueryComponent has returned without\n // calling back do we create a pending promise and hand its resolvers to\n // `settle`. The callback fires at most once, so exactly one of these paths\n // runs.\n let settle: {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n } | null = null;\n let syncResult: { value: unknown } | null = null;\n let syncError: Error | null = null;\n\n const callback = (result: QueryComponentResult): void => {\n const { code, detail } = result;\n if (code === 0) {\n const exports = bgLynx.getApp().getDynamicComponentExports(detail.schema);\n // `code === 0` only means the bundle parsed; its JS may still have\n // thrown, in which case there are no exports to hand back.\n if (exports) {\n if (settle) {\n settle.resolve(exports);\n } else {\n syncResult = { value: exports };\n }\n return;\n }\n }\n const error = new Error(\n 'Lazy bundle load failed, schema: ' + result.detail.schema,\n );\n // ES5 targets have no `new Error(message, { cause })`, so assign it.\n (error as Error & { cause?: unknown }).cause = JSON.stringify(result);\n if (settle) {\n settle.reject(error);\n } else {\n syncError = error;\n }\n };\n\n // web-core exposes QueryComponent directly on the `lynx` global, while the\n // native background runtime exposes it on the native Lynx object. React Lynx\n // uses the same fallback.\n if (typeof bgLynx.QueryComponent === 'function') {\n bgLynx.QueryComponent(source, callback);\n } else {\n bgLynx.getNativeLynx().QueryComponent(source, callback);\n }\n\n if (syncResult !== null) {\n // The cast is needed because TypeScript can't see that the callback above\n // assigned `syncResult`, so it still narrows the variable to `null` here.\n return syncResolved((syncResult as { value: unknown }).value);\n }\n if (syncError !== null) {\n return Promise.reject(syncError);\n }\n return new Promise((resolve, reject) => {\n settle = { resolve, reject };\n });\n};\n\n/**\n * A resolved promise whose `then` runs its callback synchronously, so a chain\n * like `import('./x').then(m => m.Foo)` yields its value in the same tick.\n * Port of React Lynx's `makeSyncThen`.\n */\nconst syncResolved = <T>(value: T): Promise<T> => {\n const promise = Promise.resolve(value) as Promise<T>;\n // A sync `then` on a real promise is the point here (see above), so the\n // rule against adding `then` doesn't apply.\n // oxlint-disable-next-line unicorn/no-thenable\n promise.then = makeSyncThen(value) as unknown as Promise<T>['then'];\n return promise;\n};\n\n/**\n * Builds the synchronous `then` used by `syncResolved` (a port of React Lynx's\n * `makeSyncThen`).\n *\n * There is no `onRejected` parameter because the value is already resolved, so\n * a rejection handler could never run. A missing `onFulfilled` returns another\n * sync-resolved promise so further chaining stays synchronous. A throwing\n * callback becomes a normal rejected promise, matching native `then`.\n */\nconst makeSyncThen =\n <T>(value: T) =>\n <R>(onFulfilled?: ((value: T) => R | PromiseLike<R>) | null) => {\n if (!onFulfilled) {\n return syncResolved(value);\n }\n let next: R | PromiseLike<R>;\n try {\n next = onFulfilled(value);\n } catch (e) {\n return Promise.reject(e as Error);\n }\n // A thenable returned from the chain can't be made synchronous; hand it\n // back as-is (on the main thread its callback never fires, as in React).\n if (next && typeof (next as PromiseLike<R>).then === 'function') {\n return next as Promise<R>;\n }\n return syncResolved(next as R);\n };\n","import type { ApplicationConfig, ApplicationRef, Type } from '@angular/core';\nimport { bootstrapApplication as ngBootstrapApplication } from '@angular/platform-browser';\nimport { firstValueFrom } from 'rxjs';\nimport { markFirstRenderComplete } from './lynx-render-lifecycle';\n\n// Side-effect imports install the runtime's global environment before bootstrap.\n// Order mirrors the original monolithic runtime.ts: crash diagnostics first, then\n// the browser-shaped environment polyfills, then the Lynx lifecycle/worklet\n// callbacks. `pageReady` and `__workletMap` are the only values bootstrap itself\n// needs to reference (renderPage readiness + HMR worklet reset).\nimport './error-reporting';\nimport './polyfills';\nimport { pageReady } from './global-callbacks';\nimport { __workletMap } from './worklet-bridge';\nimport { installLazyBundleLoader } from './lazy-bundle/chunk-loader';\n\n/**\n * Bootstrap Angular application on the Lynx runtime. Waits for the main thread to\n * signal it's ready before initializing the framework, then registers global\n * callbacks for page updates and worklet invocations.\n */\nexport const bootstrapApplication = async (\n rootComponent: Type<unknown>,\n options?: ApplicationConfig,\n): Promise<ApplicationRef> => {\n // Lazy routes and @defer blocks are loaded by Lynx's chunk-loading runtime\n // through `lynx.loadLazyBundle`, which the framework must provide. Install it\n // on both threads before Angular can trigger any dynamic import. Placed before\n // the HMR teardown and the renderPage wait so it is in place even if a\n // re-bootstrap triggers an import immediately; re-installing is harmless.\n installLazyBundleLoader();\n\n // HMR re-bootstrap: destroy previous app so Angular's platform accepts a new one.\n // When webpack hot-updates a module and the entry re-evaluates, this function\n // is called again. We destroy the old app (which removes its Lynx elements)\n // and create a fresh one with the updated component definitions.\n const prev = (globalThis as any).__LYNX_ANGULAR_APP_REF__ as\n | ApplicationRef\n | undefined;\n if (prev) {\n prev.destroy();\n (globalThis as any).__LYNX_ANGULAR_APP_REF__ = undefined;\n // Clear worklet registry so re-evaluated modules re-register with fresh IDs\n for (const key of Object.keys(__workletMap)) {\n delete __workletMap[key];\n }\n }\n\n // On first boot (main thread), wait for Lynx's renderPage callback.\n // On re-bootstrap (HMR), the page is already ready — skip the wait.\n if (__MAIN_THREAD__ && !prev) {\n await firstValueFrom(pageReady);\n }\n\n const appRef = await ngBootstrapApplication(rootComponent, options);\n // Signal that the initial render is done. This is the point where control\n // has returned from Angular's whole bootstrap, so it's safe to run work that\n // must NOT happen while nested inside native's first renderPage() call —\n // specifically a <list>'s first update-list-info + layout flush, which\n // re-enters componentAtIndex (see lynx-render-lifecycle.ts). Any such update\n // queued during bootstrap was parked by _processUpdate()'s isFirstRenderPending()\n // guard; this call drains it onto a fresh setTimeout macrotask. Placed on the\n // line right after bootstrap resolves (not later) so the flag flips before the\n // first post-bootstrap change-detection cycle's end() hook runs.\n markFirstRenderComplete();\n (globalThis as any).__LYNX_ANGULAR_APP_REF__ = appRef;\n\n // Clear hydration state so subsequent change detection cycles flush normally.\n const wasHydrating =\n __ENABLE_SSR__ && (globalThis as any).__LYNX_IS_HYDRATING__;\n if (wasHydrating) {\n (globalThis as any).__LYNX_IS_HYDRATING__ = false;\n (globalThis as any).__LYNX_HYDRATE_PAGE__ = undefined;\n (globalThis as any).__LYNX_HYDRATE_QUEUE__ = undefined;\n }\n\n // Web-only: force the first element-tree flush after bootstrap.\n //\n // LynxRendererFactory2.end() deliberately SKIPS __FlushElementTree() on the\n // very first render (isFirstRenderPending) because the NATIVE engine performs\n // its own implicit flush once renderPage() returns. @lynx-js/web-core has no\n // such implicit flush, and its <lynx-view> reveal + page attach happen INSIDE\n // __FlushElementTree (web-core createElementAPI: rootDom.appendChild(page) +\n // host.style.display = 'flex'). Without an explicit flush the page is never\n // attached and the view stays display:none — so every app renders blank on\n // web until some later change-detection cycle (a tap/signal) happens to flush.\n //\n // Deferred to a macrotask so it runs after web-core's renderPage frame has\n // unwound — the same safe context the <list> first-update flush uses (see\n // lynx-render-lifecycle.ts). __WEB__ is a compile-time define (false on\n // native), so this whole block is dead-code-eliminated from native bundles:\n // native behavior is unchanged. Skipped during SSR hydration, where the\n // snapshot tree already exists and web-core shows the view via its [ssr] CSS\n // attribute (mirrors end()'s hydration guard).\n if (__WEB__ && __MAIN_THREAD__ && !wasHydrating) {\n setTimeout(() => __FlushElementTree(), 0);\n }\n\n return appRef;\n};\n"],"mappings":"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"}