@blotch/angular-lynx 22.2.5 → 22.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"blotch-angular-lynx.mjs","names":[],"sources":["../../src/lib/network/base64.ts","../../src/lib/network/background-fetch.ts","../../src/lib/background-call.ts","../../src/lib/animation/animation.ts","../../src/lib/main-thread/main-thread-element.ts","../../src/lib/accessibility/accessibility.ts","../../src/lib/data-flow/host-updates.ts","../../src/lib/data-flow/global-data.ts","../../src/lib/accessibility/accessibility-settings.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/init-data.ts","../../src/lib/error-handler/lynx-error-handler.ts","../../src/lib/exposure/exposure.ts","../../src/lib/exposure/global-exposure-bridge.ts","../../src/lib/exposure/global-exposure.ts","../../src/lib/font/font.ts","../../src/lib/lazy-bundle/lazy-bundle.ts","../../src/lib/hmr/hmr-accept.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/router/lynx-router-link-active.ts","../../src/lib/accessibility/accessibility-traits.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/worklet-bridge.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-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/lynx-document/element-creators/create-block-element.ts","../../src/lib/lynx-document/android-blur-capture.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/android-blur-material.ts","../../src/lib/lynx-document/page-ref.ts","../../src/lib/lynx-render-lifecycle.ts","../../src/lib/lynx-element/svg-content.ts","../../src/lib/lynx-element/web-long-press.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/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-back-button.ts","../../src/lib/router/lynx-router.ts","../../src/lib/error-reporting.ts","../../src/lib/network/dom-exception.ts","../../src/lib/network/headers.ts","../../src/lib/url/percent-encoding.ts","../../src/lib/network/text-codec.ts","../../src/lib/network/fetch.ts","../../src/lib/network/xhr.ts","../../src/lib/network/index.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/global-callbacks.ts","../../src/lib/lazy-bundle/chunk-loader.ts","../../src/lib/runtime.ts"],"sourcesContent":["/**\n * Base64 for the bytes of request and response bodies, which cross between\n * Lynx's threads as JSON. Hand-written because neither thread has `btoa` or\n * `atob`, and the main thread has no other way to turn bytes into a string.\n */\n\nconst ALPHABET =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\nconst VALUES = new Map(Array.from(ALPHABET, (char, index) => [char, index]));\n\n/**\n * Builds the string in slices: one `String.fromCharCode` call per slice keeps\n * the work linear, where adding a character at a time can copy the whole\n * string on every step in an engine without rope strings.\n */\nconst SLICE = 8192;\n\n/**\n * Encodes bytes as standard base64, with padding.\n *\n * @param bytes - The bytes to encode.\n * @returns The base64 text.\n */\nexport const bytesToBase64 = (bytes: Uint8Array): string => {\n const codes: number[] = [];\n let output = '';\n for (let index = 0; index < bytes.length; index += 3) {\n const a = bytes[index] as number;\n const b = bytes[index + 1];\n const c = bytes[index + 2];\n codes.push(\n ALPHABET.charCodeAt(a >> 2),\n ALPHABET.charCodeAt(((a & 0x3) << 4) | ((b ?? 0) >> 4)),\n b === undefined\n ? 0x3d\n : ALPHABET.charCodeAt(((b & 0xf) << 2) | ((c ?? 0) >> 6)),\n c === undefined ? 0x3d : ALPHABET.charCodeAt(c & 0x3f),\n );\n if (codes.length >= SLICE) {\n output += String.fromCharCode(...codes);\n codes.length = 0;\n }\n }\n return output + String.fromCharCode(...codes);\n};\n\n/**\n * Decodes standard base64. Padding is optional, and characters outside the\n * alphabet, such as line breaks, are skipped.\n *\n * @param base64 - The base64 text.\n * @returns The bytes.\n */\nexport const base64ToBytes = (base64: string): Uint8Array<ArrayBuffer> => {\n const values: number[] = [];\n for (const char of base64) {\n const value = VALUES.get(char);\n if (value !== undefined) values.push(value);\n }\n const bytes = new Uint8Array(Math.floor((values.length * 3) / 4));\n let byteIndex = 0;\n for (let index = 0; index < values.length; index += 4) {\n const a = values[index] as number;\n const b = values[index + 1] ?? 0;\n const c = values[index + 2];\n const d = values[index + 3];\n bytes[byteIndex++] = (a << 2) | (b >> 4);\n if (c !== undefined) bytes[byteIndex++] = ((b & 0xf) << 4) | (c >> 2);\n if (d !== undefined) bytes[byteIndex++] = ((c! & 0x3) << 6) | d;\n }\n return bytes;\n};\n","import { base64ToBytes, bytesToBase64 } from './base64';\n\n/**\n * The background thread's half of the main thread's `fetch` (see fetch.ts).\n * Lynx has `fetch` on the background thread only, and Angular runs on the\n * main thread, so the main thread's `fetch` sends each request here, where\n * background-call.ts's relay runs it, and this sends the response back.\n *\n * Everything crosses as JSON. A body is text when it can be, and base64\n * otherwise, since JSON can't carry bytes.\n */\n\n/** A request or response body as it crosses threads. */\nexport type RelayedBody = { text: string } | { base64: string } | null;\n\n/** A request as the main thread sends it. */\nexport type RelayedRequest = {\n url: string;\n method: string;\n /** Unique names, since the main thread's Headers joins repeated ones. */\n headers: [string, string][];\n body: RelayedBody;\n /** The rest of `RequestInit`, for hosts that use it (Lynx for Web's worker). */\n options: {\n cache?: string;\n credentials?: string;\n integrity?: string;\n keepalive?: boolean;\n mode?: string;\n priority?: string;\n redirect?: string;\n referrer?: string;\n referrerPolicy?: string;\n };\n};\n\n/** A response as the background thread sends it back. */\nexport type RelayedResponse = {\n status: number;\n statusText: string;\n url: string;\n redirected: boolean;\n headers: [string, string][];\n body: RelayedBody;\n};\n\n/**\n * Lynx's HTTP services don't reject when a request fails: they resolve with\n * status 499, the failure as its status text, and no headers\n * (`SDK_ERROR_STATUS_CODE` in LynxHttpService.m, `CODE_FAILED_INTERNALLY` in\n * LynxHttpService.kt). That covers a refused connection, a bad host, a\n * relative URL (\"unsupported URL\") and Android's cleartext block.\n */\nconst LYNX_FAILURE_STATUS = 499;\n\n/** Statuses whose responses have no body (the Fetch Standard's null body statuses). */\nconst NULL_BODY_STATUSES = new Set([101, 103, 204, 205, 304]);\n\n/**\n * Media types sent as text. Others go as base64, since text would lose bytes\n * that aren't valid UTF-8.\n */\nconst TEXT_TYPE =\n /^(text\\/|application\\/([\\w.+-]*\\+)?(json|xml|javascript|ecmascript|x-www-form-urlencoded|graphql)\\b)/;\n\n/**\n * Whether a body of this `Content-Type` is safe to send as text: a textual\n * type in UTF-8. Lynx decodes `response.text()` as UTF-8 whatever the\n * charset, so another charset goes as bytes, for the main thread to decode.\n */\nconst isUtf8Text = (contentType: string | null): boolean => {\n if (!contentType) return false;\n const type = contentType.toLowerCase();\n const charset = /;\\s*charset=\"?([^\";]+)/.exec(type)?.[1];\n return (\n TEXT_TYPE.test(type) && (charset === undefined || /^utf-?8$/.test(charset))\n );\n};\n\nconst decodeBody = (body: RelayedBody): string | ArrayBuffer | undefined => {\n if (body === null) return undefined;\n if ('text' in body) return body.text;\n const bytes = base64ToBytes(body.base64);\n // Lynx's Request copies `body.buffer` whole, so it must hold only the body.\n return bytes.buffer;\n};\n\n/**\n * The thread's own `fetch`, by name rather than from `globalThis`: Lynx's\n * background thread passes it into the bundle's wrapper function as a\n * parameter, so `globalThis.fetch` is undefined there.\n */\nconst backgroundFetch = (): typeof fetch | undefined =>\n typeof fetch === 'function' ? fetch : undefined;\n\n/** The controller for each request in flight, by the main thread's ID. */\nconst controllers = new Map<number, AbortController>();\n\n/**\n * Runs a request for the main thread and resolves with the response, body\n * included. It rejects with a TypeError when the request fails, as `fetch`\n * does.\n *\n * @param id - The main thread's ID for the request, to abort it by.\n * @param request - The request.\n * @returns The response.\n */\nexport const fetchForMainThread = async (\n id: number,\n request: RelayedRequest,\n): Promise<RelayedResponse> => {\n const fetchImpl = backgroundFetch();\n if (!fetchImpl) {\n throw new TypeError(\n \"fetch isn't available on the background thread in this environment\",\n );\n }\n const controller = new AbortController();\n controllers.set(id, controller);\n try {\n const response = await fetchImpl(request.url, {\n ...(request.options as RequestInit),\n method: request.method,\n headers: Object.fromEntries(request.headers),\n body: decodeBody(request.body),\n signal: controller.signal,\n });\n const headers: [string, string][] = [];\n response.headers.forEach((value, name) => headers.push([name, value]));\n if (response.status === LYNX_FAILURE_STATUS && headers.length === 0) {\n throw new TypeError(response.statusText || 'Network request failed');\n }\n let body: RelayedBody = null;\n if (!NULL_BODY_STATUSES.has(response.status)) {\n body = isUtf8Text(response.headers.get('content-type'))\n ? { text: await response.text() }\n : {\n base64: bytesToBase64(new Uint8Array(await response.arrayBuffer())),\n };\n }\n return {\n status: response.status,\n statusText: response.statusText,\n // Lynx leaves out `redirected`, and on Android `url` is the request's.\n url: response.url || request.url,\n redirected: response.redirected === true,\n headers,\n body,\n };\n } finally {\n controllers.delete(id);\n }\n};\n\n/**\n * Aborts a request the main thread sent, when its signal aborts. The main\n * thread has already rejected its own promise; this stops the work here.\n *\n * @param id - The main thread's ID for the request.\n */\nexport const abortFetchForMainThread = (id: number): void => {\n controllers.get(id)?.abort();\n};\n","import type { ObserverFrameRateOptions } from './exposure/exposure.types';\nimport {\n abortFetchForMainThread,\n fetchForMainThread,\n type RelayedRequest,\n type RelayedResponse,\n} from './network/background-fetch';\n\n/**\n * Some Lynx APIs exist only on the background thread's `lynx` object. The main\n * thread's (`Utils::CreateLynx` in Lynx core's renderer_ng.cc) has no\n * `accessibilityAnnounce`, `addFont`, `setObserverFrameRate`,\n * `subscribeSessionStorage`, `requestResourcePrefetch` or `getJSModule`, and\n * web-core's has no `stopExposure` or `resumeExposure` either. `NativeModules`\n * exists only on the background thread too, as does `fetch`. Angular runs on\n * the main thread, so no service can reach them directly. callOnBackground() runs the call on\n * the background thread and resolves with its result, from either thread.\n *\n * The relay uses the same cross-thread event channel as the worklet RPC in\n * global-callbacks.ts: the main thread dispatches on getJSContext(), and the\n * background thread listens and replies on getCoreContext(). Results travel as\n * JSON, and an error arrives as its message.\n *\n * The handlers live here rather than in the services, and the listeners are\n * installed at module load, because the background thread might never construct\n * a service that only a main-thread code path injects.\n */\n\nconst CALL_EVENT = 'AngularLynx.BackgroundCall';\nconst RESULT_EVENT = 'AngularLynx.BackgroundCallResult';\nconst SESSION_STORAGE_EVENT = 'AngularLynx.SessionStorageChange';\nconst CALLBACK_EVENT = 'AngularLynx.Callback';\n\n/**\n * `__MAIN_THREAD__` is a build-time define. Unit tests don't define it, and run\n * as the background thread unless they stub it.\n *\n * @returns Whether this code runs on the main thread.\n */\nexport const isMainThread = (): boolean =>\n typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__;\n\n/**\n * Returns a background-only `lynx` method, or throws the error the services\n * have always thrown where it's missing, such as in the web preview.\n */\nconst lynxApi = (name: string): ((...args: any[]) => any) => {\n const fn = typeof lynx !== 'undefined' ? (lynx as any)[name] : undefined;\n if (typeof fn !== 'function') {\n throw new Error(`lynx.${name} is not available in this environment`);\n }\n return fn.bind(lynx);\n};\n\n/** Native session storage subscriptions made for the main thread, by relay ID. */\nconst relayedSubscriptions = new Map<\n number,\n { key: string; listenerId: number }\n>();\n\n/** A function argument as it crosses threads: the ID to call it back by. */\ntype FunctionMarker = { __angularLynxCallback: number };\n\n/** Main thread: each function sent with a relayed call, by ID. */\nconst relayedFunctions = new Map<number, (...args: unknown[]) => unknown>();\n/** Main thread: the ID each function was sent with, so it keeps one. */\nconst relayedFunctionIds = new WeakMap<object, number>();\nlet nextFunctionId = 0;\n/** Background thread: the stand-in for each of the main thread's functions. */\nconst standIns = new Map<number, (...args: unknown[]) => void>();\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (typeof value !== 'object' || value === null) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n};\n\nconst isFunctionMarker = (value: unknown): value is FunctionMarker =>\n isPlainObject(value) && typeof value['__angularLynxCallback'] === 'number';\n\n/**\n * Main thread: the marker for a function, registered so the background\n * thread's stand-in can call it. A function keeps its ID, so passing the same\n * listener again, to remove it, reaches the same stand-in there. `owner` is the\n * object a method came from, which it's called on.\n */\nconst markFunction = (fn: Function, owner?: object): FunctionMarker => {\n let id = relayedFunctionIds.get(fn);\n if (id === undefined) {\n id = nextFunctionId++;\n relayedFunctionIds.set(fn, id);\n relayedFunctions.set(id, (...args) => fn.apply(owner, args));\n }\n return { __angularLynxCallback: id };\n};\n\n/**\n * Prepares a relayed call's arguments: on the main thread, each function in\n * them, or in a plain object or array in them, becomes a marker that the\n * background thread calls back. Elsewhere the call runs in place, so the\n * arguments are left alone.\n *\n * @param value - The arguments, or one of them.\n * @returns The value to send.\n */\nexport const relayFunctions = (value: unknown): unknown => {\n if (!isMainThread()) return value;\n const relay = (item: unknown, owner?: object): unknown => {\n if (typeof item === 'function') return markFunction(item, owner);\n if (Array.isArray(item)) return item.map((entry) => relay(entry));\n if (isPlainObject(item)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(item)) {\n result[key] = relay(item[key], item);\n }\n return result;\n }\n return item;\n };\n return relay(value);\n};\n\n/**\n * Prepares a JS module for registering from the main thread: its methods,\n * including ones on its prototype such as a class's, become markers bound to\n * it, and its other fields are copied.\n *\n * @param module - The module to register.\n * @returns The value to send.\n */\nexport const relayModuleObject = (module: object): unknown => {\n if (!isMainThread()) return module;\n const result: Record<string, unknown> = {};\n for (\n let source: object | null = module;\n source !== null && source !== Object.prototype;\n source = Object.getPrototypeOf(source)\n ) {\n for (const key of Object.getOwnPropertyNames(source)) {\n if (key === 'constructor' || key in result) continue;\n const value = (module as Record<string, unknown>)[key];\n result[key] =\n typeof value === 'function'\n ? markFunction(value, module)\n : relayFunctions(value);\n }\n }\n return result;\n};\n\n/**\n * Background thread: swaps each function marker for a stand-in that calls\n * the main thread's function, with its arguments copied as JSON. A value\n * without markers comes back as the same object, so a module registered on\n * this thread keeps its identity.\n */\nconst restoreFunctions = (value: unknown): unknown => {\n if (isFunctionMarker(value)) {\n const id = value.__angularLynxCallback;\n let standIn = standIns.get(id);\n if (!standIn) {\n standIn = (...args: unknown[]) => {\n try {\n (lynx as any).getCoreContext().dispatchEvent({\n type: CALLBACK_EVENT,\n data: JSON.stringify({ id, args }),\n });\n } catch {\n // Arguments JSON can't copy, such as a circular object, can't reach\n // the main thread. Native code calling back has nobody to tell.\n }\n };\n standIns.set(id, standIn);\n }\n return standIn;\n }\n if (Array.isArray(value)) {\n const items = value.map(restoreFunctions);\n return items.some((item, i) => item !== value[i]) ? items : value;\n }\n if (isPlainObject(value)) {\n let changed = false;\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(value)) {\n result[key] = restoreFunctions(value[key]);\n changed ||= result[key] !== value[key];\n }\n return changed ? result : value;\n }\n return value;\n};\n\n/**\n * The host's `NativeModules.bridge`, if it has one.\n */\nconst nativeBridge = ():\n | {\n call(\n name: string,\n params: unknown,\n callback: (...args: unknown[]) => void,\n ): void;\n on(name: string, callback: (...args: unknown[]) => void): void;\n }\n | undefined => {\n const bridge =\n typeof NativeModules !== 'undefined' && NativeModules != null\n ? (NativeModules as any).bridge\n : undefined;\n return typeof bridge?.call === 'function' ? bridge : undefined;\n};\n\n/**\n * A native module or JS module by name, or undefined.\n */\nconst findModule = (kind: ModuleKind, name: string): any => {\n if (kind === 'native') {\n return typeof NativeModules !== 'undefined' && NativeModules != null\n ? (NativeModules as any)[name]\n : undefined;\n }\n return typeof lynx !== 'undefined' &&\n typeof (lynx as any).getJSModule === 'function'\n ? (lynx as any).getJSModule(name)\n : undefined;\n};\n\n/** Which registry a relayed module comes from. */\nexport type ModuleKind = 'native' | 'js';\n\nconst handlers = {\n accessibilityAnnounce: (content: string): Promise<void> =>\n new Promise((resolve) =>\n lynxApi('accessibilityAnnounce')({ content }, () => resolve()),\n ),\n\n addFont: (fontFamily: string, src: string): Promise<void> =>\n new Promise((resolve, reject) =>\n lynxApi('addFont')({ 'font-family': fontFamily, src }, (err?: unknown) =>\n err ? reject(err) : resolve(),\n ),\n ),\n\n setObserverFrameRate: (options?: ObserverFrameRateOptions): void =>\n lynxApi('setObserverFrameRate')(options),\n\n // Native Lynx has these on both threads, but web-core only on the background\n // thread, where its exposure module reads `sendEvent` off the argument.\n stopExposure: (options?: { sendEvent: boolean }): void =>\n lynxApi('stopExposure')(options ?? {}),\n\n resumeExposure: (): void => lynxApi('resumeExposure')(),\n\n /**\n * Subscribes on the background thread and sends each change to the main\n * thread, where subscribeSessionStorageFromMainThread() delivers it.\n */\n subscribeSessionStorage: (key: string, relayId: number): void => {\n const listenerId: number = lynxApi('subscribeSessionStorage')(\n key,\n (value: unknown) =>\n (lynx as any).getCoreContext().dispatchEvent({\n type: SESSION_STORAGE_EVENT,\n data: JSON.stringify({ relayId, value }),\n }),\n );\n relayedSubscriptions.set(relayId, { key, listenerId });\n },\n\n unsubscribeSessionStorage: (relayId: number): void => {\n const subscription = relayedSubscriptions.get(relayId);\n if (!subscription) return;\n relayedSubscriptions.delete(relayId);\n lynxApi('unsubscribeSessionStorage')(\n subscription.key,\n subscription.listenerId,\n );\n },\n\n requestResourcePrefetch: (data: unknown): Promise<unknown> =>\n new Promise((resolve) => lynxApi('requestResourcePrefetch')(data, resolve)),\n\n cancelResourcePrefetch: (data: unknown): Promise<unknown> =>\n new Promise((resolve) => lynxApi('cancelResourcePrefetch')(data, resolve)),\n\n /**\n * Calls the host's bridge method and resolves with the first value it\n * passes back. Without a bridge, such as in the web preview, it resolves\n * `undefined`, as LynxNativeModule.call() always has.\n */\n nativeBridgeCall: (name: string, params: unknown): Promise<unknown> => {\n const bridge = nativeBridge();\n if (!bridge) return Promise.resolve(undefined);\n return new Promise((resolve) =>\n bridge.call(name, params, (...args: unknown[]) => resolve(args[0])),\n );\n },\n\n nativeBridgeOn: (name: string, callback: unknown): void => {\n nativeBridge()?.on(\n name,\n restoreFunctions(callback) as (...args: unknown[]) => void,\n );\n },\n\n /**\n * Calls a method of a native module or a JS module. The main thread's\n * module proxies (relayedModule() below) send their calls here.\n */\n callModule: (\n kind: ModuleKind,\n name: string,\n method: string,\n args: unknown[],\n ): unknown => {\n const module = findModule(kind, name);\n const fn = module?.[method];\n if (typeof fn !== 'function') {\n throw new Error(\n `${kind === 'native' ? 'NativeModules' : 'lynx.getJSModule'}: ${name}.${method} is not available`,\n );\n }\n return fn.apply(module, restoreFunctions(args) as unknown[]);\n },\n\n registerJSModule: (name: string, module: unknown): void => {\n lynxApi('registerModule')(name, restoreFunctions(module));\n },\n\n /**\n * The OS version, for LynxSystemInfo on the main thread: native Lynx builds\n * that thread's SystemInfo without one, and the background thread's global\n * has it.\n */\n osVersion: (): string | undefined =>\n typeof SystemInfo !== 'undefined' ? SystemInfo.osVersion : undefined,\n\n /** The main thread's `fetch` (network/fetch.ts) sends its requests here. */\n fetch: (id: number, request: RelayedRequest): Promise<RelayedResponse> =>\n fetchForMainThread(id, request),\n\n abortFetch: (id: number): void => abortFetchForMainThread(id),\n};\n\ntype Handlers = typeof handlers;\ntype HandlerName = keyof Handlers;\n\nconst pending = new Map<\n number,\n { resolve: (value: any) => void; reject: (error: Error) => void }\n>();\nlet nextCallId = 0;\n\n/**\n * Runs a background-only Lynx API, directly on the background thread or relayed\n * from the main thread.\n */\nexport const callOnBackground = <N extends HandlerName>(\n name: N,\n ...args: Parameters<Handlers[N]>\n): Promise<Awaited<ReturnType<Handlers[N]>>> => {\n if (!isMainThread()) {\n try {\n return Promise.resolve(\n (handlers[name] as (...a: unknown[]) => any)(...args),\n );\n } catch (error) {\n return Promise.reject(error);\n }\n }\n return new Promise((resolve, reject) => {\n const id = nextCallId++;\n pending.set(id, { resolve, reject });\n try {\n (lynx as any).getJSContext().dispatchEvent({\n type: CALL_EVENT,\n data: JSON.stringify({ id, name, args }),\n });\n } catch {\n pending.delete(id);\n reject(\n new Error(\n `Can't reach the background thread to call lynx.${name} in this environment`,\n ),\n );\n }\n });\n};\n\n/** Main thread: one proxy per module, so repeated lookups return the same one. */\nconst moduleProxies = new Map<string, object>();\n\n/**\n * Main thread: a stand-in for a native module or JS module, which only the\n * background thread can reach. Each method call runs there and returns a\n * promise of its result, and function arguments are called back here. Reading\n * `then` gives `undefined`, so the proxy isn't mistaken for a promise.\n *\n * @param kind - `'native'` for `NativeModules`, `'js'` for `lynx.getJSModule`.\n * @param name - The module's name.\n * @returns The proxy.\n */\nexport const relayedModule = (kind: ModuleKind, name: string): object => {\n const cacheKey = `${kind}:${name}`;\n let proxy = moduleProxies.get(cacheKey);\n if (!proxy) {\n const methods = new Map<string, (...args: unknown[]) => Promise<unknown>>();\n proxy = new Proxy(\n {},\n {\n get: (_target, method) => {\n if (typeof method !== 'string' || method === 'then') {\n return undefined;\n }\n let call = methods.get(method);\n if (!call) {\n call = (...args: unknown[]) =>\n callOnBackground(\n 'callModule',\n kind,\n name,\n method,\n relayFunctions(args) as unknown[],\n );\n methods.set(method, call);\n }\n return call;\n },\n },\n );\n moduleProxies.set(cacheKey, proxy);\n }\n return proxy;\n};\n\nconst sessionStorageListeners = new Map<number, (value: unknown) => void>();\nlet nextRelayId = 0;\n\n/**\n * Main thread only. Subscribes to a session storage key through the background\n * thread, the only thread that can, and returns the ID to unsubscribe with.\n */\nexport const subscribeSessionStorageFromMainThread = (\n key: string,\n listener: (value: unknown) => void,\n): number => {\n const relayId = nextRelayId++;\n sessionStorageListeners.set(relayId, listener);\n callOnBackground('subscribeSessionStorage', key, relayId).catch(() => {\n // Without a background thread there's nothing to subscribe to. The\n // caller's local listeners still see this thread's own writes.\n sessionStorageListeners.delete(relayId);\n });\n return relayId;\n};\n\nexport const unsubscribeSessionStorageFromMainThread = (\n relayId: number,\n): void => {\n if (!sessionStorageListeners.delete(relayId)) return;\n callOnBackground('unsubscribeSessionStorage', relayId).catch(() => {});\n};\n\nconst installRelay = (): void => {\n if (typeof lynx === 'undefined') return;\n try {\n if (isMainThread()) {\n const context = (lynx as any).getJSContext();\n context.addEventListener(RESULT_EVENT, (event: { data: string }) => {\n const { id, value, error } = JSON.parse(event.data);\n const call = pending.get(id);\n if (!call) return;\n pending.delete(id);\n if (error !== undefined) {\n call.reject(new Error(error));\n } else {\n call.resolve(value);\n }\n });\n context.addEventListener(\n SESSION_STORAGE_EVENT,\n (event: { data: string }) => {\n const { relayId, value } = JSON.parse(event.data);\n sessionStorageListeners.get(relayId)?.(value);\n },\n );\n context.addEventListener(CALLBACK_EVENT, (event: { data: string }) => {\n const { id, args } = JSON.parse(event.data);\n relayedFunctions.get(id)?.(...args);\n });\n return;\n }\n const context = (lynx as any).getCoreContext();\n context.addEventListener(CALL_EVENT, async (event: { data: string }) => {\n const { id, name, args } = JSON.parse(event.data);\n let reply: { id: number; value?: unknown; error?: string };\n try {\n const handler = handlers[name as HandlerName] as\n | ((...a: unknown[]) => unknown)\n | undefined;\n if (!handler) throw new Error(`Unknown background call: ${name}`);\n reply = { id, value: await handler(...args) };\n } catch (error) {\n reply = {\n id,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n let data: string;\n try {\n data = JSON.stringify(reply);\n } catch (error) {\n // A result JSON can't copy, such as a circular object from a native\n // module, would otherwise leave the caller waiting forever.\n // JSON.stringify only throws TypeErrors.\n data = JSON.stringify({\n id,\n error: `The result of ${name} can't be sent to the main thread: ${(error as Error).message}`,\n });\n }\n context.dispatchEvent({ type: RESULT_EVENT, data });\n });\n } catch {\n // The thread contexts may be missing outside a real Lynx host. Calls from\n // the main thread then reject in callOnBackground().\n }\n};\n\ninstallRelay();\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 * The public API of an animation, which `BaseLynxElement.animate()` returns.\n * LynxAnimation uses ES private fields (#element, #count), which brand the\n * class, so a structural type lets other implementations, such as a test\n * double, satisfy it.\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, except for\n * the key a named animation is controlled by (see the constructor).\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 // The string __ElementAnimate knows this animation by (see the constructor).\n readonly #key: string;\n // The DOM Animation web-core started, on web only (see the constructor).\n readonly #webAnimation?: Animation;\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 // __ElementAnimate finds an animation by the string after the operation,\n // and native Lynx and web-core need different strings for a named one\n // (issue #57):\n // - Native starts it under `options.name`, which its animation events\n // report, and PLAY/PAUSE write their string into the element's\n // `animation-name`. So play() and pause() have to pass the name: given\n // the generated id they left a named animation running on iOS and\n // Android. React Lynx always passes the id, so its named animations\n // can't be paused either.\n // - web-core ignores `options.name` and keys one map, shared by every\n // element on the page, by that string. Starting an animation cancels\n // whatever is already under its key, so two elements animating under\n // the same name would cancel each other. The unique id avoids that.\n this.#key = __WEB__ ? this.id : (options.name ?? this.id);\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 this.#key,\n keyframes,\n wireOptions,\n ]);\n\n // web-core's __ElementAnimate forgets an animation the moment it finishes\n // (its `onfinish` drops it from the map it looks names up in), so a later\n // ANIMATION_CANCEL finds nothing and does nothing. On native, cancel still\n // clears a finished animation. The difference shows with fill:'forwards':\n // on web the final frame then pins the property for good, and every\n // inline style set on it afterwards is hidden (a bottom sheet's drag\n // transform, for one). On web the element is a real DOM element and\n // web-core starts the animation with element.animate(), so keep that\n // Animation and cancel it directly. getAnimations() lists an element's\n // script animations in the order they were created, so the last one is\n // the animation just started.\n if (__WEB__) {\n this.#webAnimation = (\n this.#element as unknown as Partial<Pick<Element, 'getAnimations'>>\n )\n .getAnimations?.()\n .at(-1);\n }\n }\n\n play(): void {\n __ElementAnimate(this.#element, [ANIMATION_PLAY, this.#key]);\n }\n\n pause(): void {\n __ElementAnimate(this.#element, [ANIMATION_PAUSE, this.#key]);\n }\n\n cancel(): void {\n __ElementAnimate(this.#element, [ANIMATION_CANCEL, this.#key]);\n // Reaches the animation even after it finished (see the constructor).\n // Canceling an animation web-core already canceled is a no-op.\n this.#webAnimation?.cancel();\n }\n}\n","import type { ElementRef } from '../types/lynx';\nimport {\n LynxAnimation,\n type LynxAnimationOptions,\n} from '../animation/animation';\nimport type { MainThread } from './types';\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 * Measures the element's layout box, by default from the top-left corner of\n * the LynxView. `relativeTo` takes 'screen', or another element's `id`.\n *\n * Not part of the official @lynx-js/types Element interface, but useful for\n * touch tracking. Unlike the DOM's, it's asynchronous: native Lynx gives a\n * main-thread script the layout position only through the\n * `boundingClientRect` UI method. The computed `left` and `top` styles are\n * CSS offsets, often 0, not where the element is.\n */\n getBoundingClientRect(options?: {\n relativeTo?: string;\n }): Promise<MainThread.BoundingClientRect> {\n return this.invoke('boundingClientRect', options).then((rect) => {\n // The UI method also returns the element's id and dataset.\n const { left, top, right, bottom, width, height } =\n rect as MainThread.BoundingClientRect;\n return { left, top, right, bottom, width, height };\n });\n }\n}\n","import { Injectable } from '@angular/core';\nimport { callOnBackground } from '../background-call';\nimport { MainThreadElement } from '../main-thread/main-thread-element';\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()`. Only the background thread's `lynx`\n * has it, and event handlers run on the main thread, so the call goes\n * through the background thread (see background-call.ts).\n */\n announce(content: string): Promise<void> {\n return callOnBackground('accessibilityAnnounce', content);\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 * The main thread's `lynx` has no createSelectorQuery, but it's where event\n * handlers run and where the native elements live, so there the element is\n * found and called directly.\n */\n requestFocus(selector: string): Promise<void> {\n if (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__) {\n const element = new MainThreadElement(__GetPageElement()).querySelector(\n selector,\n );\n if (!element) {\n return Promise.reject(\n new Error(\n `requestAccessibilityFocus: no element matches ${selector}`,\n ),\n );\n }\n return element.invoke('requestAccessibilityFocus').then(() => undefined);\n }\n\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 { Subject } from 'rxjs';\nimport type { GlobalData, InitData } from './data-flow.types';\n\n/**\n * Host data that changes after the page has started. The engine reports each\n * change through a callback it calls by name (see global-callbacks.ts), outside\n * Angular's DI, so the callback stores the new value on `lynx` and publishes it\n * here, and LynxInitData and LynxGlobalData subscribe. Each thread runs its own\n * copy of this module, fed by that thread's callbacks: the main thread's copy\n * is the one that reaches the screen.\n */\nexport const initDataUpdates = new Subject<InitData>();\nexport const globalDataUpdates = new Subject<GlobalData>();\n\nconst asRecord = (data: unknown): Record<string, unknown> =>\n typeof data === 'object' && data !== null\n ? (data as Record<string, unknown>)\n : {};\n\n/**\n * Merges an InitData update into `lynx.__initData`, as React Lynx does, and\n * publishes the result. `reset` starts from an empty object, for a host that\n * resets the data instead of updating it. Always builds a new object, because\n * a signal given the same object again doesn't notify its readers.\n */\nexport const applyInitDataUpdate = (\n data: unknown,\n reset: boolean,\n): InitData => {\n const host = lynx as any;\n const next = {\n ...(reset ? {} : host.__initData),\n ...asRecord(data),\n } as InitData;\n host.__initData = next;\n initDataUpdates.next(next);\n return next;\n};\n\n/**\n * Merges a GlobalData update into `lynx.__globalProps`, as React Lynx does, and\n * publishes the result. The host sends the whole object, so the merge only\n * matters if it ever sends part of one. Builds a new object for the same reason\n * as applyInitDataUpdate().\n */\nexport const applyGlobalDataUpdate = (data: unknown): GlobalData => {\n const next = { ...lynx.__globalProps, ...asRecord(data) } as GlobalData;\n lynx.__globalProps = next as typeof lynx.__globalProps;\n globalDataUpdates.next(next);\n return next;\n};\n","import { DestroyRef, inject, Injectable, signal } from '@angular/core';\nimport type { GlobalData } from './data-flow.types';\nimport { globalDataUpdates } from './host-updates';\n\n@Injectable({ providedIn: 'root' })\nexport class LynxGlobalData {\n // Seeded from lynx.__globalProps at construction time; updated when the host\n // changes it. A host that never sets global props leaves __globalProps\n // undefined, so fall back to an empty object: readers like LynxTheme index\n // into it.\n readonly globalData = signal<GlobalData>(\n ((typeof lynx !== 'undefined' && lynx.__globalProps) || {}) as GlobalData,\n );\n\n constructor() {\n // The engine's update callbacks publish the merged data on each thread\n // (see host-updates.ts), so this works on the main thread, which draws\n // the UI, as well as on the background thread. Unsubscribe when the app\n // is destroyed, so an HMR re-bootstrap doesn't leave the old app listening.\n const subscription = globalDataUpdates.subscribe((data) =>\n this.globalData.set(data),\n );\n inject(DestroyRef).onDestroy(() => subscription.unsubscribe());\n }\n}\n","import {\n computed,\n DestroyRef,\n inject,\n Injectable,\n signal,\n type Signal,\n} from '@angular/core';\nimport { LynxGlobalData } from '../data-flow/global-data';\n\n/**\n * Each setting, by the name of the global prop a host app sends it as, with\n * the media query a browser reports it through.\n */\nconst MEDIA_QUERIES = {\n reduceMotion: '(prefers-reduced-motion: reduce)',\n reduceTransparency: '(prefers-reduced-transparency: reduce)',\n increaseContrast: '(prefers-contrast: more)',\n} as const;\n\ntype Setting = keyof typeof MEDIA_QUERIES;\n\n/**\n * Whether the host app turned a setting on: `true`, or `'true'`, the string\n * Lynx Explorer passes for a query parameter of the bundle URL\n * (`?reduceMotion=true`), which makes the settings easy to try out there.\n */\nconst isOn = (data: Record<string, unknown>, setting: Setting): boolean =>\n data[setting] === true || data[setting] === 'true';\n\n/**\n * The window the page is drawn in, on Lynx for Web: its main thread runs in an\n * iframe while its elements belong to the page, so the user's preferences\n * have to come from the page element's window, not this realm's. Native Lynx\n * has no media queries at all.\n */\nconst pageWindow = (): Window | undefined => {\n if (!__WEB__ || typeof __GetPageElement !== 'function') return undefined;\n const page = __GetPageElement() as unknown as\n | { ownerDocument?: Document }\n | undefined;\n return page?.ownerDocument?.defaultView ?? undefined;\n};\n\n/**\n * One signal per setting that follows the page's media query on the web, and\n * stays `false` elsewhere.\n */\nconst watchMediaQueries = (\n destroyRef: DestroyRef,\n): Record<Setting, Signal<boolean>> => {\n const win = pageWindow();\n const signals = {} as Record<Setting, Signal<boolean>>;\n for (const setting of Object.keys(MEDIA_QUERIES) as Setting[]) {\n const query =\n typeof win?.matchMedia === 'function'\n ? win.matchMedia(MEDIA_QUERIES[setting])\n : undefined;\n const matches = signal(query?.matches ?? false);\n if (query) {\n const update = () => matches.set(query.matches);\n query.addEventListener('change', update);\n destroyRef.onDestroy(() => query.removeEventListener('change', update));\n }\n signals[setting] = matches.asReadonly();\n }\n return signals;\n};\n\n/**\n * The user's accessibility display settings, as signals: Reduce Motion,\n * Reduce Transparency and Increase Contrast.\n *\n * Lynx has no API for them on any platform, so they come from the host app,\n * in its global props, like the theme does: `reduceMotion`,\n * `reduceTransparency` and `increaseContrast`, each `true` when on. The apps\n * `ng build --platform` makes send them, and send them again when the user\n * changes one:\n *\n * - **iOS:** `UIAccessibility.isReduceMotionEnabled`,\n * `isReduceTransparencyEnabled` and `isDarkerSystemColorsEnabled`\n * (Increase Contrast).\n * - **Android:** Remove animations (an animator duration scale of 0) for\n * Reduce Motion, and contrast above standard (Android 14) or high contrast\n * text (Android 16) for Increase Contrast. Android has no Reduce\n * Transparency setting.\n *\n * In the web preview they follow the browser's `prefers-reduced-motion`,\n * `prefers-reduced-transparency` and `prefers-contrast: more` too. Lynx\n * Explorer sends none of them, so they're off there, unless you add them to\n * the bundle URL: `?reduceMotion=true`.\n *\n * iOS 27's Liquid Glass appearance setting (clear or tinted glass) has no\n * public API, so it isn't here. UIKit's glass follows it, and Reduce\n * Transparency and Increase Contrast, by itself.\n *\n * @usageNotes\n * ```typescript\n * const settings = inject(LynxAccessibilitySettings);\n *\n * // Jump instead of sliding when the user asked for less motion.\n * const duration = computed(() => (settings.reduceMotion() ? 0 : 250));\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxAccessibilitySettings {\n readonly #globalData = inject(LynxGlobalData);\n readonly #media = watchMediaQueries(inject(DestroyRef));\n\n /**\n * The user asked for less motion. Replace movement, such as a slide or a\n * bounce, with a fade or an instant change.\n */\n readonly reduceMotion = this.#setting('reduceMotion');\n\n /**\n * The user asked for less transparency. Draw blurred and translucent\n * surfaces opaque.\n */\n readonly reduceTransparency = this.#setting('reduceTransparency');\n\n /**\n * The user asked for more contrast: iOS's Increase Contrast. Strengthen\n * borders and use full-strength text colors.\n */\n readonly increaseContrast = this.#setting('increaseContrast');\n\n #setting(setting: Setting): Signal<boolean> {\n return computed(\n () =>\n isOn(\n this.#globalData.globalData() as Record<string, unknown>,\n setting,\n ) || this.#media[setting](),\n );\n }\n}\n","import { Injectable } from '@angular/core';\nimport type { CommonPerformance } from '@lynx-js/types';\nimport type { LynxTraceOptions } from './devtools.types';\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 * Unlike the `LynxDevTools` counters, the calls aren't gated by `__PROFILE__`,\n * so they stay in production builds. A trace is worth recording from the build\n * you ship, without development mode's extra work in it. They cost little\n * there: release builds of the Lynx engine compile tracing out, so each call\n * returns at once.\n *\n * @usageNotes\n * ```typescript\n * const perf = inject(LynxPerformance);\n *\n * perf.profileStart('MyComponent::render', { args: { itemCount: '42' } });\n * // ... do work ...\n * perf.profileEnd();\n *\n * perf.profileMark('dataLoaded', { args: { source: 'cache' } });\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxPerformance {\n // Partial: each method is checked before it's called, in case an engine\n // lacks it.\n #perf: Partial<CommonPerformance> | null = this.#resolve();\n\n #resolve(): Partial<CommonPerformance> | 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(name: string, options?: LynxTraceOptions): 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(name: string, options?: LynxTraceOptions): 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","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\n/**\n * The current time in ms. Native Lynx has no `performance` global on either\n * thread; the web preview has one, and it times below a millisecond.\n * `Date.now()` is everywhere.\n */\nconst now = (): number =>\n typeof performance !== 'undefined' && typeof performance.now === 'function'\n ? performance.now()\n : Date.now();\n\n// One start time per change-detection cycle in progress. A stack rather than a\n// single value because cycles nest: a `detectChanges()` call during a tick\n// runs its own begin()/end() pair inside the tick's, and the tick's duration\n// must not start at the inner one's start.\nconst cdStartTimes: number[] = [];\n\n/**\n * Starts timing a change-detection cycle. The renderer factory calls it from\n * `begin()`, and `endCdTiming()` from `end()`.\n */\nexport const startCdTiming = (): void => {\n cdStartTimes.push(now());\n};\n\n/**\n * Stops timing the innermost change-detection cycle in progress, and records\n * its duration in `devStats.lastCdDurationMs`.\n */\nexport const endCdTiming = (): void => {\n const start = cdStartTimes.pop();\n if (start !== undefined) {\n devStats.lastCdDurationMs = now() - start;\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 in development builds, where the build plugin sets\n * `__PROFILE__` to true. In production builds, counters are never incremented\n * (the instrumentation code is dead-code-eliminated), so all values remain\n * 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. The engine runs the default processor\n * on the InitData before passing it to renderPage, so its result is what\n * LynxInitData starts with.\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 { DestroyRef, inject, Injectable, signal } from '@angular/core';\nimport type { InitData } from './data-flow.types';\nimport { initDataUpdates } from './host-updates';\n\n@Injectable({ providedIn: 'root' })\nexport class LynxInitData {\n // Seeded from lynx.__initData at construction time; updated when the host sends new data.\n // The runtime sets __initData from renderPage on the main thread and from the\n // loadCard params on the background thread (see global-callbacks.ts). Outside\n // Lynx, or before either has run, fall back to an empty object so reads like\n // initData().userId don't throw. __initData is not declared in @lynx-js/types,\n // so we access it via any.\n readonly initData = signal<InitData>(\n ((typeof lynx !== 'undefined' && (lynx as any).__initData) ||\n {}) as InitData,\n );\n\n constructor() {\n // The engine's update callbacks publish the merged data on each thread\n // (see host-updates.ts), so this works on the main thread, which draws\n // the UI, as well as on the background thread. Unsubscribe when the app\n // is destroyed, so an HMR re-bootstrap doesn't leave the old app listening.\n const subscription = initDataUpdates.subscribe((data) =>\n this.initData.set(data),\n );\n inject(DestroyRef).onDestroy(() => subscription.unsubscribe());\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 { Subject } from 'rxjs';\nimport type { GlobalExposureEvent } from './exposure.types';\n\nexport type GlobalExposureBatch = {\n type: 'exposure' | 'disexposure';\n events: GlobalExposureEvent;\n};\n\n/**\n * Every batch of global exposure events, on whichever thread this module runs.\n * LynxGlobalExposure subscribes.\n */\nexport const globalExposureBatches = new Subject<GlobalExposureBatch>();\n\nconst FORWARD_EVENT = 'AngularLynx.GlobalExposure';\n\n/**\n * Lynx reports global exposure (elements with an `exposure-id` entering or\n * leaving the screen) only on the background thread, through\n * GlobalEventEmitter. The main thread draws the UI, so its LynxGlobalExposure\n * signals never changed. The background thread now publishes each batch locally\n * and forwards it to the main thread, through the same cross-thread event\n * channel as the worklet RPC in global-callbacks.ts: the background thread\n * dispatches on getCoreContext(), and the main thread listens on getJSContext().\n *\n * Installed once at module load rather than by LynxGlobalExposure, because a\n * component the router creates after a tap exists only on the main thread, so\n * the background thread might never construct the service.\n */\nconst installGlobalExposureBridge = (): void => {\n if (typeof lynx === 'undefined') return;\n try {\n if (__MAIN_THREAD__) {\n (lynx as any)\n .getJSContext?.()\n ?.addEventListener(FORWARD_EVENT, (event: { data: string }) =>\n globalExposureBatches.next(JSON.parse(event.data)),\n );\n return;\n }\n const emitter = lynx.getJSModule?.('GlobalEventEmitter');\n if (!emitter?.addListener) return;\n for (const type of ['exposure', 'disexposure'] as const) {\n emitter.addListener(type, (...args: unknown[]) => {\n const batch = { type, events: args[0] as GlobalExposureEvent };\n globalExposureBatches.next(batch);\n (lynx as any).getCoreContext?.()?.dispatchEvent({\n type: FORWARD_EVENT,\n data: JSON.stringify(batch),\n });\n });\n }\n } catch {\n // The thread contexts and GlobalEventEmitter may be missing outside a real\n // Lynx host. Global exposure then simply never fires.\n }\n};\n\ninstallGlobalExposureBridge();\n","import { DestroyRef, inject, Injectable, signal } from '@angular/core';\nimport { callOnBackground } from '../background-call';\nimport { globalExposureBatches } from './global-exposure-bridge';\nimport type {\n GlobalExposureEvent,\n ObserverFrameRateOptions,\n} from './exposure.types';\n\n@Injectable({ providedIn: 'root' })\nexport class LynxGlobalExposure {\n // The most recent batch of elements that came on screen. Lynx batches them\n // and reports them through GlobalEventEmitter's 'exposure' event.\n readonly exposures = signal<GlobalExposureEvent>([]);\n\n // The most recent batch of elements that left the screen ('disexposure').\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 // Lynx reports these events only on the background thread. The bridge\n // forwards them to the main thread, which draws the UI, and publishes them\n // on both (see global-exposure-bridge.ts). Unsubscribe when the app is\n // destroyed, so an HMR re-bootstrap doesn't leave the old app listening.\n const subscription = globalExposureBatches.subscribe(({ type, events }) =>\n (type === 'exposure' ? this.exposures : this.disexposures).set(events),\n );\n inject(DestroyRef).onDestroy(() => subscription.unsubscribe());\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 if (typeof lynx.stopExposure === 'function') {\n lynx.stopExposure(options);\n } else {\n this.#relay(callOnBackground('stopExposure', options));\n }\n this.active.set(false);\n }\n\n resumeExposure(): void {\n if (typeof lynx === 'undefined') return;\n if (typeof lynx.resumeExposure === 'function') {\n lynx.resumeExposure();\n } else {\n this.#relay(callOnBackground('resumeExposure'));\n }\n this.active.set(true);\n }\n\n /**\n * Sets how often Lynx checks for exposure. Only the background thread's\n * `lynx` has setObserverFrameRate, so a call from an event handler, which\n * runs on the main thread, goes through the background thread (see\n * background-call.ts). Resolves once it's applied.\n */\n setObserverFrameRate(options?: ObserverFrameRateOptions): Promise<void> {\n if (typeof lynx === 'undefined') return Promise.resolve();\n return callOnBackground('setObserverFrameRate', options);\n }\n\n /**\n * Web-core's main thread has no stopExposure or resumeExposure, so there the\n * call goes through the background thread (see background-call.ts). These\n * methods return nothing, so report a failed relay rather than leave an\n * unhandled rejection.\n */\n #relay(call: Promise<void>): void {\n call.catch((error: unknown) => console.error(error));\n }\n}\n","import { computed, Injectable, signal } from '@angular/core';\nimport { callOnBackground } from '../background-call';\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 * Only the background thread's `lynx` has addFont, so a call from an event\n * handler, which runs on the main thread, goes through the background thread\n * (see background-call.ts).\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 // Any failure, including addFont itself being missing, must leave the\n // 'loading' state and the pending cache, so a later call can try again.\n const promise = callOnBackground('addFont', fontFamily, src).then(\n () => {\n this.#updateEntry(fontFamily, { fontFamily, src, status: 'loaded' });\n this.#pending.delete(fontFamily);\n },\n (err: unknown) => {\n const error = err instanceof Error ? err : new Error(String(err));\n this.#updateEntry(fontFamily, {\n fontFamily,\n src,\n status: 'error',\n error,\n });\n this.#pending.delete(fontFamily);\n throw error;\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 { type Type, ɵɵreplaceMetadata } from '@angular/core';\nimport { isMainThread } from '../background-call';\n\n/**\n * The parts of webpack's `module.hot` API that {@link ɵhmrAccept} uses.\n */\nexport type HotModule = {\n accept(): void;\n dispose(callback: (data: Record<string, unknown>) => void): void;\n invalidate(): void;\n /** What the module's previous version passed to its dispose handlers. */\n data?: Record<string, unknown>;\n};\n\n/**\n * What one version of a module hands the next through `hot.data`.\n */\ntype ModuleVersion = {\n /** The component classes the app renders, in declaration order. */\n components: Type<unknown>[];\n signature: string;\n code: string;\n /**\n * Set when this version passed the update on to the modules that import it.\n * The update then re-runs the module once more, as part of re-running\n * them, and that run must not pass it on again.\n */\n invalidated: boolean;\n};\n\nconst DATA_KEY = 'angularLynx';\n\n/**\n * Takes a hot update of a module that defines components. The build plugin\n * adds a call to the end of each such module in a development build, which\n * reassigns the module's component classes to what it returns.\n *\n * On the main thread, where the app runs, a new version of the module either\n * updates the running app in place or passes the update on:\n *\n * - **Only a template or stylesheet changed** (the source `signature`, which\n * leaves those out, is the same, and the compiled `code` isn't): each\n * component's new definition replaces the old one with Angular's\n * `ɵɵreplaceMetadata()`, which Angular's own dev server uses for the same\n * edits. It re-renders every view of the component in place and keeps the\n * component instances, so their state survives. The module's bindings are\n * pointed back at the old classes, so every module keeps using the one\n * class the app's instances and injectors know.\n * - **Anything else changed**, such as the class, an import, or a module this\n * one imports: the update can't be applied to the running instances, so\n * `hot.invalidate()` passes it on to the modules that import this one, up\n * to the app's entry, which bootstraps the app again (see\n * `bootstrapApplication`).\n *\n * The background thread runs no Angular, only the module-level code that\n * registers background functions. It accepts every version, which re-runs\n * the module and registers them again.\n *\n * @param hot - The module's `import.meta.webpackHot`.\n * @param components - The component classes this version of the module defines.\n * @param signature - A hash of the module's source without its components'\n * templates and styles.\n * @param code - A hash of the module's compiled code.\n * @returns The classes the module should use from now on.\n */\nexport const ɵhmrAccept = (\n hot: HotModule,\n components: Type<unknown>[],\n signature: string,\n code: string,\n): Type<unknown>[] => {\n hot.accept();\n if (!isMainThread()) return components;\n\n const previous = hot.data?.[DATA_KEY] as ModuleVersion | undefined;\n let live = components;\n let invalidated = false;\n if (previous && !previous.invalidated) {\n if (\n previous.code !== code &&\n previous.signature === signature &&\n previous.components.length === components.length\n ) {\n try {\n previous.components.forEach((type, index) =>\n replaceComponent(type, components[index]),\n );\n live = previous.components;\n } catch (error) {\n // A template that throws when it renders, for example. Re-bootstrapping\n // from the entry recovers, or reports the error in the app's own way.\n console.error('[HMR] Could not update the component in place:', error);\n invalidated = true;\n }\n } else {\n invalidated = true;\n }\n }\n\n hot.dispose((data) => {\n data[DATA_KEY] = {\n components: live,\n signature,\n code,\n invalidated,\n } satisfies ModuleVersion;\n });\n if (invalidated) hot.invalidate();\n return live;\n};\n\n/**\n * Swaps the component definition of `current` for `next`'s, and re-renders\n * every view of the component. `ɵɵreplaceMetadata()` merges the definitions\n * in place, keeping the old one's `type`, so the views it creates from now on\n * still instantiate `current`.\n */\nconst replaceComponent = (\n current: Type<unknown>,\n next: Type<unknown>,\n): void => {\n // The merge also keeps the old definition's dependencies, because Angular's\n // own update modules can't import them. Here the new definition comes from\n // the module's new version, whose dependencies are current: a component it\n // uses may have been re-run by the same update, as a new class. Copying them\n // onto the old definition first makes the merge keep the new ones.\n const currentDef = (current as any).ɵcmp;\n const nextDef = (next as any).ɵcmp;\n currentDef.directiveDefs = nextDef.directiveDefs;\n currentDef.pipeDefs = nextDef.pipeDefs;\n ɵɵreplaceMetadata(\n current,\n (type) => {\n (type as any).ɵcmp = (next as any).ɵcmp;\n },\n [],\n [],\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 * The app's own locale: `sourceLocale` from angular.json, which the build\n * injects as `__LYNX_SOURCE_LOCALE__`, or `'en-US'` without one.\n */\nexport const getSourceLocale = (): string =>\n typeof __LYNX_SOURCE_LOCALE__ !== 'undefined'\n ? __LYNX_SOURCE_LOCALE__\n : 'en-US';\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 return value ?? getSourceLocale();\n });\n}\n","import { getLocaleId } from '@angular/common';\nimport {\n type EnvironmentProviders,\n inject,\n LOCALE_ID,\n makeEnvironmentProviders,\n} from '@angular/core';\nimport { getSourceLocale, LynxLocale } from './lynx-locale';\n\n/**\n * Whether Angular has locale data for `locale`, or for its language (`fr`\n * for `fr-CA`). Its pipes and plural rules throw without it.\n */\nconst hasLocaleData = (locale: string): boolean => {\n try {\n // Throws NG0701 when there's none. Deprecated in favor of Intl, which\n // Lynx's JavaScript engine doesn't have; Angular's pipes still use it.\n getLocaleId(locale);\n return true;\n } catch {\n return false;\n }\n};\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 * The apps that `ng build --platform` makes send the phone's language, which\n * the app may not support. When Angular has no locale data for it (see\n * `registerLocaleData()`), `LOCALE_ID` is the app's source locale instead, as\n * a native app shows its own language on a phone set to one it lacks.\n * Otherwise Angular's date and number pipes would throw.\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: () => {\n const locale = inject(LynxLocale).locale();\n const source = getSourceLocale();\n if (locale === source || hasLocaleData(locale)) {\n return locale;\n }\n console.warn(\n `provideLocale(): Angular has no locale data for \"${locale}\", so LOCALE_ID is \"${source}\". Register it with registerLocaleData() to format dates and numbers for it.`,\n );\n return source;\n },\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 * Starts as `{ enabled: true }`, like React Lynx's gesture-runtime, so every\n * gesture sends a config, even one with no options of its own (Fling, Pinch,\n * Rotation). Gestures whose native handler reads options seed the rest of\n * their defaults too: once a config is present, iOS reads each key it leaves\n * out as `0` (see ./const).\n */\n _config: Record<string, unknown> = { enabled: true };\n /**\n * @internal\n */\n _waitFor: BaseGesture[] = [];\n /**\n * @internal\n */\n _simultaneousWith: BaseGesture[] = [];\n /**\n * @internal\n */\n _continueWith: BaseGesture[] = [];\n\n /**\n * Fires when the gesture starts tracking a touch, before it's recognized:\n * at touch-down for most gestures, and when the finger lifts for a fling.\n *\n * A continuous gesture doesn't need one for its `onStart` and `onEnd` to\n * fire. LynxGestureDetector registers an empty `onBegin` when you don't, since\n * Lynx's native handlers skip those callbacks without it. See\n * gesture-detector.ts.\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 /**\n * ⚠️ Not read by Lynx's native gesture handlers yet (as of Lynx 4.1, no\n * handler looks up `enabled`), so a disabled gesture still fires on a\n * device. Unbind the gesture from `[lynxGesture]` to turn it off. Kept for\n * API parity with Lynx's gesture-runtime.\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\n/**\n * Lynx's fling follows the momentum of a drag after the finger lifts: `onBegin`\n * fires on release, `onUpdate` on every frame (with `deltaX`/`deltaY` in the\n * params), and `onEnd` when it stops. Lynx starts that fling in its BEGAN\n * state and never activates it, so `onStart` doesn't fire\n * (LynxFlingGestureHandler.m / FlingGestureHandler.java). Lynx also flings only\n * the element that won the touch, and a fling ignores the touch until the\n * finger lifts, so it needs a pan on the same element (`Gesture.Simultaneous`).\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 * ⚠️ Not read by Lynx's native fling handlers yet: as of Lynx 4.1, iOS's\n * `handleConfigMap` is a TODO and Android's is empty, so every fling fires,\n * in any direction. Kept for API parity with Lynx's gesture-runtime.\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 * ⚠️ Not read by Lynx's native fling handlers yet (see `direction`).\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/…): `onBegin`\n * seeds the origin where the touch began, and `onEnd` clears it.\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 where the touch began, then report translation\n // relative to it, like react-native-gesture-handler: a pan that activates\n // after `minDistance` reports the distance moved before activating too.\n // The directive registers an `onBegin` on every continuous gesture, so\n // each touch re-anchors even when the previous one sent no `onEnd`. Any\n // other gesture anchors on its first event, and resets at `onEnd`.\n if (name === 'onBegin' || 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, ContinuousGesture } 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 constructor() {\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 //\n // It's set here, when the element is created, rather than when a gesture\n // is bound: Android decides whether an element gets a View of its own when\n // it first draws it, and turning flatten off afterwards doesn't give it one.\n // ngOnChanges came too late for a routed component's elements and for a\n // gesture bound after the first render (`[lynxGesture]=\"on ? pan : []\"`),\n // and those gestures never fired on Android (issue #56).\n const elementRef = (this.#el as any).element;\n if (elementRef) __SetAttribute(elementRef, 'flatten', false);\n }\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 // An element with no native handle (.element is undefined), such as the\n // renderer's in-memory test double, has nothing to register a gesture on.\n const elementRef = (this.#el as any).element;\n if (!elementRef) return;\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: g._config,\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`.\n *\n * Continuous gestures (pan, fling, pinch, rotation) always get an `onBegin`,\n * an empty one when the user didn't register theirs. Lynx's native fling\n * handler, and its pan handler before Lynx 3.9, fire `onStart` and `onEnd` only\n * after `onBegin` has fired, and fire `onBegin` only when one is registered\n * (LynxFlingGestureHandler.m / FlingGestureHandler.java), so without it those\n * two callbacks never ran, with no error. Running it also anchors the\n * gesture's translation where the touch began (see mapGestureEvent).\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 const callbacks = Object.entries(gesture._callbacks).map(([name, cb]) =>\n wrap(name, cb),\n );\n if (\n gesture instanceof ContinuousGesture &&\n !gesture._callbacks['onBegin']\n ) {\n // wrap() maps the event, which is what anchors the translation.\n callbacks.push(wrap('onBegin', () => {}));\n }\n return callbacks;\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 * (https://github.com/lynx-family/lynx-stack/blob/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 * ⚠️ Not read by Lynx's native pan handlers yet: as of Lynx 4.1 they read\n * only `minDistance` (LynxPanGestureHandler.m / PanGestureHandler.java\n * `handleConfigMap`). The same goes for activeOffsetY, failOffsetX/Y and\n * min/maxPointers. Kept for API parity with Lynx's gesture-runtime.\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 * ⚠️ Not read by Lynx's native pan handlers yet (see `activeOffsetX`). Call\n * the state manager's `fail()` from `onUpdate` instead.\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 { AccessibilityTrait } from '../accessibility/accessibility-traits';\nimport type { BaseLynxElement } from '../lynx-element/types';\n\n/**\n * A length Lynx's exposure detection parses, such as `'20px'` or `'-10rpx'`.\n * Lynx reads the margins as strings, so a bare number has no effect.\n */\nexport type ExposureMargin = `${number}px` | `${number}rpx`;\n\n/**\n * Lets a true/false input also be written as a static attribute, as Lynx's\n * guides and ours do: `flatten=\"false\"`, or a bare `ignore-focus` for true.\n * Angular type-checks a static attribute's string against the input, so\n * without this `<text flatten=\"false\">` stops compiling once `flatten` is an\n * input. Unlike Angular's `booleanAttribute`, `undefined` stays `undefined`,\n * so a binding can still remove the attribute and restore Lynx's default.\n */\n// oxlint-disable-next-line func-style, @blotch/no-function-declaration -- Angular's compiler takes a named input transform only as a function declaration (NG1010)\nfunction booleanInput(\n value: boolean | '' | 'true' | 'false' | undefined,\n): boolean | undefined {\n return typeof value === 'string' ? value !== 'false' : value;\n}\n\n/**\n * Lets `pan-intercept-direction` also be written as a static attribute,\n * `pan-intercept-direction=\"1\"`, and hands Lynx a number either way.\n */\n// oxlint-disable-next-line func-style, @blotch/no-function-declaration -- Angular's compiler takes a named input transform only as a function declaration (NG1010)\nfunction panInterceptDirectionInput(\n value: 0 | 1 | '0' | '1' | undefined,\n): 0 | 1 | undefined {\n return typeof value === 'string' ? (Number(value) as 0 | 1) : value;\n}\n\n/**\n * Lets `pan-intercept-scope` also be written as a static attribute,\n * `pan-intercept-scope=\"5\"`, and hands Lynx a number either way.\n */\n// oxlint-disable-next-line func-style, @blotch/no-function-declaration -- Angular's compiler takes a named input transform only as a function declaration (NG1010)\nfunction panInterceptScopeInput(\n value: 0 | 1 | 2 | 3 | 4 | 5 | '0' | '1' | '2' | '3' | '4' | '5' | undefined,\n): 0 | 1 | 2 | 3 | 4 | 5 | undefined {\n return typeof value === 'string'\n ? (Number(value) as 0 | 1 | 2 | 3 | 4 | 5)\n : value;\n}\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 { name: 'accessibility-element', transform: booleanInput },\n 'accessibility-label',\n // The current value a screen reader reads after the label (a slider's\n // position, a chart's focused point), and custom actions it offers\n // (string[]; the chosen one arrives as the accessibility action event's detail.name).\n 'accessibility-value',\n 'accessibility-actions',\n 'accessibility-traits',\n 'accessibility-elements',\n { name: 'accessibility-elements-hidden', transform: booleanInput },\n { name: 'accessibility-exclusive-focus', transform: booleanInput },\n 'a11y-id',\n { name: 'user-interaction-enabled', transform: booleanInput },\n { name: 'native-interaction-enabled', transform: booleanInput },\n { name: 'event-through', transform: booleanInput },\n 'hit-slop',\n { name: 'block-native-event', transform: booleanInput },\n { name: 'ignore-focus', transform: booleanInput },\n { name: 'ios-enable-simultaneous-touch', transform: booleanInput },\n { name: 'flatten', transform: booleanInput },\n { name: 'pan-intercept-direction', transform: panInterceptDirectionInput },\n { name: 'pan-intercept-scope', transform: panInterceptScopeInput },\n 'consume-slide-event',\n { name: 'enable-touch-pseudo-propagation', transform: booleanInput },\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 { name: 'enable-exposure-ui-margin', transform: booleanInput },\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 /**\n * The kind of element a screen reader announces. Plural, as Lynx reads it:\n * iOS, Android and Harmony ignore `accessibility-trait`. iOS also reads a\n * comma-separated list with no spaces, such as `button,selected`, which\n * is what LynxRouterLinkActive and LynxAccessibilityTraits write; Android\n * and Harmony read a single trait. @default 'none'\n */\n 'accessibility-traits'?:\n | AccessibilityTrait\n | `${AccessibilityTrait},${string}`;\n /**\n * Comma-separated `id`s of the child elements a screen reader visits, in\n * order. iOS and Android look each one up as an `id` selector.\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 * Lets Lynx draw the element into its parent's native view instead of\n * creating its own (Android). `false` gives it its own view, which sticky\n * positioning, text selection and reliable clipping need. @default true\n */\n flatten?: boolean;\n /**\n * Direction in which the element takes pan gestures from native views\n * outside Lynx: 0 = horizontal, 1 = vertical.\n */\n 'pan-intercept-direction'?: 0 | 1;\n /**\n * Which views `pan-intercept-direction` takes pans from: 0 = self,\n * 1 = ancestors, 2 = descendants, 3 = self and ancestors, 4 = self and\n * descendants, 5 = all.\n */\n 'pan-intercept-scope'?: 0 | 1 | 2 | 3 | 4 | 5;\n /**\n * Swipe angle ranges, `[start, end]` in degrees, that the element keeps\n * from platform gestures.\n */\n 'consume-slide-event'?: [number, number][];\n /**\n * Whether `:active` also applies to the ancestors on the touch's event path.\n */\n 'enable-touch-pseudo-propagation'?: 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 * How much of the element must be visible to count as exposed, as a\n * percentage string such as `'50%'`. @default '0%'\n */\n 'exposure-area'?: `${number}%`;\n /**\n * Extends/shrinks the viewport detection zone (top edge).\n */\n 'exposure-screen-margin-top'?: ExposureMargin;\n /**\n * Extends/shrinks the viewport detection zone (bottom edge).\n */\n 'exposure-screen-margin-bottom'?: ExposureMargin;\n /**\n * Extends/shrinks the viewport detection zone (left edge).\n */\n 'exposure-screen-margin-left'?: ExposureMargin;\n /**\n * Extends/shrinks the viewport detection zone (right edge).\n */\n 'exposure-screen-margin-right'?: ExposureMargin;\n /**\n * Adjusts the element's own bounding rect for exposure detection (top).\n * iOS and Android apply it only with `enable-exposure-ui-margin`.\n */\n 'exposure-ui-margin-top'?: ExposureMargin;\n /**\n * Adjusts the element's own bounding rect for exposure detection (bottom).\n * iOS and Android apply it only with `enable-exposure-ui-margin`.\n */\n 'exposure-ui-margin-bottom'?: ExposureMargin;\n /**\n * Adjusts the element's own bounding rect for exposure detection (left).\n * iOS and Android apply it only with `enable-exposure-ui-margin`.\n */\n 'exposure-ui-margin-left'?: ExposureMargin;\n /**\n * Adjusts the element's own bounding rect for exposure detection (right).\n * iOS and Android apply it only with `enable-exposure-ui-margin`.\n */\n 'exposure-ui-margin-right'?: ExposureMargin;\n /**\n * Turns on `exposure-ui-margin-*` on iOS and Android (always on for Harmony\n * and the web). It also changes how they apply `exposure-screen-margin-*`.\n * @default false\n */\n 'enable-exposure-ui-margin'?: boolean;\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 * Android only has the plain blur, a Gaussian blur of `blur-radius`. There\n * the runtime approximates `blur-effect`, `glass-style` and\n * `glass-tint-color` with a translucent background and rim over the blur,\n * which a background, background image or shadow the app sets replaces.\n * Nothing refracts, and `glass-interactive` and `spacing` do nothing.\n */\n@Directive({\n selector: 'blur-view',\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 'blur-material',\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\"`\n * (Android). The runtime points it at the page, so a blur-view inside\n * another blur-view still blurs what's behind it; an empty string restores\n * Android's own choice, the nearest ancestor that clips or contains it.\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. Android\n * gets a tint that approximates it. @default 'light'\n */\n 'blur-effect'?:\n | 'light'\n | 'extra-light'\n | 'dark'\n | 'glass'\n | 'glass-container';\n /**\n * One of UIKit's adaptive blur materials, which follow\n * `ios-user-interface-style` (iOS 13+, in apps built with\n * `ng build --platform ios`): `systemUltraThinMaterial` to\n * `systemThickMaterial`, or `systemChromeMaterial`, the bars'. While it's\n * set it replaces `blur-effect` and `blur-radius`. Lynx's own blur-view\n * doesn't have it, so Lynx Explorer and other hosts ignore it and draw the\n * `blur-effect`.\n */\n 'blur-material'?: 'ultra-thin' | 'thin' | 'regular' | 'thick' | 'chrome';\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; approximated on Android). @default 'transparent'\n */\n 'glass-tint-color'?: string;\n /**\n * Glass variant (iOS; approximated on Android). @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' })\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 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.\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 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 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 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 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 // 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 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 * Gaps between items aren't attributes: `list-main-axis-gap` and\n * `list-cross-axis-gap` are CSS properties, which Lynx's list reads from its\n * computed style, so set them in `style` (`[style.list-main-axis-gap]`).\n */\n@Directive({\n selector: 'list',\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 '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 * 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 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 ],\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","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Anonymous grouping element with no visual output.\n */\n@Directive({ selector: 'block' })\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' })\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' })\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 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 * The layer the overlay sits in when several are open: 1 is the top layer\n * and 4 the lowest. Within a layer the last one shown is on top. Lynx reads\n * it only while the overlay is hidden. @default 1\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 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})\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 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})\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})\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})\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 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 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 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 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 the text is laid out in. The text box ends after\n * that many lines, but the ellipsis needs `text-overflow: ellipsis`\n * (Tailwind's `text-ellipsis`). Without it, iOS cuts the text off at the\n * last line, and Android draws the remaining lines past the box.\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' })\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 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 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>`. Its\n * attributes (`flatten`, the pan-intercept ones, …) work on every element, so\n * they live on {@link LynxElementBase}.\n */\n@Directive({ selector: 'view' })\nexport class LynxView extends LynxElementBase {}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Horizontally swipeable paging container.\n */\n@Directive({\n selector: 'viewpager',\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})\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 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","import {\n DestroyRef,\n Directive,\n ElementRef,\n inject,\n InjectionToken,\n type OutputRef,\n} from '@angular/core';\nimport type { BaseLynxElement } from '../lynx-element/types';\n\n/**\n * Finds the `isActiveChange` output of Angular's `RouterLinkActive` on the\n * element being created, or null if it has none. Called in the injection\n * context of that element's LynxRouterLinkActive.\n *\n * `provideRouter()` provides it, rather than LynxRouterLinkActive importing\n * `RouterLinkActive` itself, because LynxRouterLinkActive is part of\n * LYNX_ELEMENTS, which every component imports: referring to the router from\n * there would put the whole router in the bundle of an app without routes.\n * Without `provideRouter()` there's no router to follow, and the token is\n * missing.\n */\nexport const ROUTER_LINK_ACTIVE_CHANGE = new InjectionToken<\n () => OutputRef<boolean> | null\n>('router-link-active-change');\n\n/**\n * Tells screen readers which router link is the current one: while Angular's\n * `RouterLinkActive` on the same element says its route is active, the\n * element has the `selected` accessibility trait, as the selected tab of a\n * native tab bar does. On the web, `routerLinkActive` only changes classes, or\n * `aria-current` with `ariaCurrentWhenActive`; Lynx elements have no ARIA,\n * and `accessibility-traits` is how they say this.\n *\n * It keeps the element's own traits: `accessibility-traits=\"button\"` becomes\n * `button,selected` while the link is active. On Android, which reads one\n * trait and has no selected trait, the element keeps its own traits as they\n * are.\n *\n * It's part of LYNX_ELEMENTS, so a component that imports LYNX_ELEMENTS and\n * Angular's `RouterLinkActive` gets it on every `routerLinkActive` element.\n * To add it to a component's host instead, list it in `hostDirectives` next\n * to `RouterLinkActive`.\n *\n * @usageNotes\n * ```ts\n * @Component({\n * imports: [LYNX_ELEMENTS, RouterLink, RouterLinkActive],\n * template: `\n * <view routerLink=\"/settings\" routerLinkActive=\"active\">\n * <text>Settings</text>\n * </view>\n * `,\n * })\n * ```\n */\n@Directive({ selector: '[routerLinkActive]' })\nexport class LynxRouterLinkActive {\n constructor() {\n const activeChange = inject(ROUTER_LINK_ACTIVE_CHANGE, {\n optional: true,\n })?.();\n if (!activeChange) return;\n const element: BaseLynxElement = inject(ElementRef).nativeElement;\n const subscription = activeChange.subscribe((active) =>\n element.setAccessibilityTrait('selected', active),\n );\n inject(DestroyRef).onDestroy(() => subscription.unsubscribe());\n }\n}\n","import { Directive, effect, ElementRef, inject, input } from '@angular/core';\nimport type { BaseLynxElement } from '../lynx-element/types';\n\n/**\n * One trait of `accessibility-traits`, each of which iOS turns into a\n * UIAccessibilityTraits flag (`LynxConverter+UI.m`).\n */\nexport type AccessibilityTrait =\n | 'text'\n | 'image'\n | 'button'\n | 'link'\n | 'header'\n | 'search'\n | 'selected'\n | 'playable'\n | 'keyboard'\n | 'summary'\n | 'disabled'\n | 'updating'\n | 'adjustable'\n | 'tabbar'\n | 'none';\n\n/**\n * Which traits LynxAccessibilityTraits adds, by name. `none` isn't one: it\n * says the element has no traits, so there's nothing to add.\n */\nexport type AccessibilityTraitStates = Partial<\n Record<Exclude<AccessibilityTrait, 'none'>, boolean>\n>;\n\n/**\n * Adds accessibility traits to an element's own `accessibility-traits` while\n * a binding says so, such as `selected` on the chosen one of several options,\n * or `disabled` on an item that can't be used now.\n *\n * Writing the state into the attribute instead,\n * `accessibility-traits=\"button,selected\"`, works only on iOS. Android reads\n * the attribute as a single trait, so a list stops being a button there. The\n * element merges these traits into its own instead (see\n * LynxElement.setAccessibilityTrait): `button` reads `button,selected` on iOS,\n * and stays `button` on Android, which has no selected trait to add. The\n * element can still set its own traits at any time, and neither undoes the\n * other.\n *\n * A trait that turns false, or that the map leaves out, is taken away again.\n * Only the traits this directive added are: the element's own stay.\n *\n * It's part of LYNX_ELEMENTS, so a component that imports LYNX_ELEMENTS can\n * bind it on any element.\n *\n * @usageNotes\n * ```html\n * <view\n * [accessibility-element]=\"true\"\n * accessibility-traits=\"button\"\n * [accessibility-label]=\"label()\"\n * [lynxAccessibilityTraits]=\"{ selected: selected() }\"\n * (bindtap)=\"chosen.emit()\"\n * >\n * ```\n */\n@Directive({ selector: '[lynxAccessibilityTraits]' })\nexport class LynxAccessibilityTraits {\n readonly lynxAccessibilityTraits = input<\n AccessibilityTraitStates | null | undefined\n >();\n\n readonly #element: BaseLynxElement = inject(ElementRef).nativeElement;\n /** The traits this has added, to take away those that turn off. */\n #added: string[] = [];\n\n constructor() {\n effect(() => {\n const states: Record<string, boolean | undefined> =\n this.lynxAccessibilityTraits() ?? {};\n const on = Object.keys(states).filter((trait) => states[trait]);\n for (const trait of this.#added) {\n if (!on.includes(trait)) {\n this.#element.setAccessibilityTrait(trait, false);\n }\n }\n for (const trait of on) this.#element.setAccessibilityTrait(trait, true);\n this.#added = on;\n });\n }\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';\nexport { LynxRouterLinkActive } from '../router/lynx-router-link-active';\nexport { LynxAccessibilityTraits } from '../accessibility/accessibility-traits';\n\nimport { LynxInputValueAccessor, LynxTextareaValueAccessor } 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';\nimport { LynxRouterLinkActive } from '../router/lynx-router-link-active';\nimport { LynxAccessibilityTraits } from '../accessibility/accessibility-traits';\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 // The same pair as LYNX_FORM_ACCESSORS, listed rather than spread: a minifier\n // keeps an array with a spread in it even when nothing uses the array, since\n // the spread runs the array's iterator. That kept every directive here, and\n // Angular with them, in the background bundle, which uses none of them.\n LynxInputValueAccessor,\n LynxTextareaValueAccessor,\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 // Activates on top of Angular's RouterLinkActive, like the CVA directives\n // on form attributes above: marks the active link `selected` for screen\n // readers. It doesn't import the router (see the file).\n LynxRouterLinkActive,\n // Adds accessibility traits, such as `selected`, from a binding, on any\n // element that binds `lynxAccessibilityTraits`.\n LynxAccessibilityTraits,\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: Angular, and so every LynxLogger call, runs on the main thread,\n * which has no fetch. Only the background thread has it. Logs are relayed to\n * 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: unknown[];\n};\n\nconst LOG_EVENT = '__lynx_log__';\n\n/**\n * The dev server's log endpoint, or '' when there's none (a production build,\n * or a dev build without a server).\n */\nconst logUrl = (): string =>\n __DEV__ && typeof __DEV_LOG_URL__ !== 'undefined' ? __DEV_LOG_URL__ : '';\n\n/**\n * This thread's fetch, which only the background thread has: Lynx injects it\n * through the background bundle's tt.define() wrapper, so it's in module scope\n * rather than on globalThis. Read once the module runs, on either thread.\n */\nconst resolveFetch = ():\n | ((url: string, init?: RequestInit) => Promise<Response>)\n | undefined => {\n try {\n if (typeof fetch === 'function') {\n return 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 return (globalThis as any).fetch;\n }\n /* v8 ignore stop */\n } catch {}\n return undefined;\n};\n\n/**\n * An argument as it travels to the dev server, which writes strings as they\n * are, objects and arrays as indented JSON, and an Error as its stack.\n *\n * The entry crosses to the background thread and then to the dev server as\n * JSON, which would turn an Error into `{}` (its message and stack aren't\n * enumerable): it goes as a plain object the dev server recognizes by its\n * `__type`. An object JSON can't hold, such as a circular one, goes as a\n * string, so it can't make the whole entry fail to send. So does everything\n * else: numbers, booleans, `undefined` and `null` print the same either way,\n * and JSON would turn `undefined` and `NaN` into `null`.\n */\nconst toLogArg = (arg: unknown): unknown => {\n if (arg instanceof Error) {\n return {\n __type: 'Error',\n name: arg.name,\n message: arg.message,\n stack: arg.stack,\n };\n }\n if (typeof arg === 'object' && arg !== null) {\n try {\n JSON.stringify(arg);\n return arg;\n } catch {}\n }\n return String(arg);\n};\n\n/**\n * Posts one entry to the dev server. Failures are dropped: logging must never\n * break the app.\n */\nconst postToServer = (\n fetchFn: (url: string, init?: RequestInit) => Promise<Response>,\n url: string,\n entry: LogEntry,\n): void => {\n try {\n fetchFn(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ logs: [entry] }),\n }).catch(() => {});\n } catch {}\n};\n\n/**\n * Background thread: posts the log entries the main thread relays. Installed\n * at module load, not by the service, because no Angular code, so no\n * LynxLogger, runs on this thread.\n */\nconst installLogRelay = (): void => {\n if (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__) return;\n const url = logUrl();\n const fetchFn = resolveFetch();\n if (!url || !fetchFn) return;\n try {\n if (\n typeof lynx !== 'undefined' &&\n typeof lynx.getCoreContext === 'function'\n ) {\n lynx.getCoreContext().addEventListener(LOG_EVENT, (event: any) => {\n try {\n postToServer(fetchFn, url, JSON.parse(event.data as string));\n } catch {}\n });\n }\n } catch {}\n};\n\ninstallLogRelay();\n\n@Injectable({ providedIn: 'root' })\nexport class LynxLogger {\n readonly #url: string = logUrl();\n /**\n * This thread's fetch: set when the logger runs on the background thread,\n * such as in a test, where it posts directly instead of relaying.\n */\n readonly #fetchFn = this.#url ? resolveFetch() : undefined;\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(toLogArg),\n };\n\n if (this.#fetchFn) {\n // Background thread: send directly via fetch.\n postToServer(this.#fetchFn, this.#url, entry);\n } else {\n // Main thread: no fetch available. Relay to background thread via IPC.\n // The relay installed above handles it there.\n try {\n if (\n typeof lynx !== 'undefined' &&\n typeof (lynx as any).getJSContext === 'function'\n ) {\n (lynx as any).getJSContext().dispatchEvent({\n type: LOG_EVENT,\n data: JSON.stringify(entry),\n });\n }\n } catch {}\n }\n }\n}\n","import { Injectable } from '@angular/core';\nimport {\n callOnBackground,\n isMainThread,\n relayedModule,\n relayFunctions,\n relayModuleObject,\n} from '../background-call';\nimport type { NativeModuleMap, NativeModuleProxy } 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 * Lynx provides both only on the background thread, while Angular runs on the\n * main thread. So on the main thread every method goes through the background\n * call relay (background-call.ts): calls run on the background thread, their\n * results and callbacks come back as JSON, and a module is a proxy whose\n * methods return promises.\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 typeof NativeModules !== 'undefined' && NativeModules != null;\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 * Resolves `undefined` when there is no bridge (web preview, tests).\n */\n call<T = unknown>(\n name: string,\n params: Record<string, unknown> = {},\n ): Promise<T | undefined> {\n if (isMainThread() && typeof lynx === 'undefined') {\n // No background thread to relay to.\n return Promise.resolve(undefined);\n }\n return callOnBackground('nativeBridgeCall', name, params) as Promise<\n T | undefined\n >;\n }\n\n /**\n * Subscribes to a native event via `NativeModules.bridge.on()`. From the\n * main thread, the callback gets the event's arguments copied as JSON.\n *\n * No-op when there is no bridge.\n */\n on(name: string, callback: (...args: unknown[]) => void): void {\n callOnBackground('nativeBridgeOn', name, relayFunctions(callback)).catch(\n () => {\n // Without a background thread there's no bridge to listen to.\n },\n );\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 * export {};\n *\n * declare module '@blotch/angular-lynx' {\n * interface NativeModuleMap {\n * NativeLocalStorageModule: { ... };\n * }\n * }\n *\n * const storage = modules.getNativeModule('NativeLocalStorageModule');\n * ```\n *\n * On the main thread, which can't reach native modules, it returns a proxy:\n * each method call runs on the background thread and returns a promise of\n * its result, and a call to a module or method the host doesn't have\n * rejects. The return type says so: a module in {@link NativeModuleMap}\n * comes back as a {@link NativeModuleProxy} of it, and any other name as\n * `unknown`.\n *\n * Returns `undefined` outside Lynx, or on the background thread when the\n * module is not registered.\n */\n getNativeModule<K extends string>(\n name: K,\n ): K extends keyof NativeModuleMap\n ? NativeModuleProxy<NativeModuleMap[K]> | undefined\n : unknown {\n if (isMainThread()) {\n return (\n typeof lynx !== 'undefined' ? relayedModule('native', name) : undefined\n ) as any;\n }\n if (!this.#hasNativeModules()) {\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`. On the main thread it returns a proxy, as\n * getNativeModule() does.\n *\n * Returns `undefined` when `lynx` is unavailable or, on the background\n * thread, when the module is not registered.\n */\n getJSModule<T = unknown>(name: string): T | undefined {\n if (isMainThread()) {\n return (\n typeof lynx !== 'undefined' ? relayedModule('js', name) : undefined\n ) as T | undefined;\n }\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()`. From the main thread, the\n * background thread registers a copy whose methods call this module's, with\n * their arguments copied as JSON and their return values dropped.\n *\n * No-op when `lynx` is unavailable.\n */\n registerJSModule<T extends object>(name: string, module: T): void {\n if (typeof lynx === 'undefined') {\n return;\n }\n callOnBackground('registerJSModule', name, relayModuleObject(module)).catch(\n () => {\n // Without a background thread there's no registry to add it to.\n },\n );\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 * The overlay's layer, from 1 (the top) to 4 (the lowest), as on\n * `<overlay>`. Lynx's default is 1.\n */\n level?: 1 | 2 | 3 | 4;\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","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` and `restoreRefs`\n * reconstitute a ref from this map when they see a `{ _wvid }` marker in\n * params, and MainThreadRef registers itself here on creation, on both threads.\n */\nexport const __mainThreadRefMap: Record<number | string, { current: unknown }> =\n {};\n\n/**\n * Pending runOnBackground() Promises keyed by `resolveId`. The main thread's\n * listener settles an entry when the background thread's reply arrives.\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 share one\n * monotonic sequence.\n */\nexport const nextResolveId = (): number => __nextResolveId++;\n\n/**\n * Rebuilds `value` with every `{ _wvid }` marker resolved to its MainThreadRef\n * and, when `elements` is set, every `{ elementRefptr }` wrapped as a\n * MainThreadElement.\n */\nconst transform = (value: unknown, elements: boolean): unknown => {\n if (typeof value !== 'object' || value === null) return value;\n if (Array.isArray(value)) {\n return value.map((item) => transform(item, elements));\n }\n const obj = value as Record<string, unknown>;\n if (elements && 'elementRefptr' in obj) {\n return new MainThreadElement(obj['elementRefptr'] as any);\n }\n if ('_wvid' in obj) {\n return __mainThreadRefMap[obj['_wvid'] as number | string] ?? obj;\n }\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = transform(obj[key], elements);\n }\n return result;\n};\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 transform(value, true);\n\n/**\n * Resolves the `{ _wvid }` markers in the arguments the main thread sends a\n * background function to this thread's MainThreadRef, the copy the function\n * would also see through its closure. Element handles are left alone: a\n * MainThreadElement only works on the main thread.\n */\nexport const restoreRefs = (value: unknown): unknown => transform(value, false);\n\n/**\n * Whether `value` is a promise, or any thenable an async function can return.\n */\nconst isThenable = (value: unknown): value is PromiseLike<unknown> =>\n typeof (value as { then?: unknown } | null | undefined)?.then === 'function';\n\n/**\n * The text a failed call sends back. The caller rejects with `new Error(text)`,\n * so an Error sends its message: `String(error)` would come out as\n * \"Error: Error: offline\".\n */\nconst errorText = (e: unknown): string =>\n e instanceof Error ? e.message : String(e);\n\n/**\n * Runs a function the other thread called and sends it the result, as the\n * JSON `{ resolveId, returnValue }` or `{ resolveId, error }` its pending\n * Promise settles from.\n *\n * A returned promise is awaited first, so an async function (anything that\n * awaits `fetch`) delivers its result rather than a promise, which JSON turns\n * into `{}`, and its rejection reaches the caller instead of going unhandled.\n * React Lynx doesn't await here (run-on-background.ts sends `f(...params)` as\n * is), so this is one place not to copy it: fetching on the background thread\n * is the main reason to call it.\n * A synchronous result is sent right away, without a microtask in between.\n * A result JSON can't encode, such as a circular object, is sent as an error,\n * so the caller doesn't wait forever.\n */\nexport const answerCall = (\n resolveId: number,\n run: () => unknown,\n send: (data: string) => void,\n): void => {\n const reply = (result: { returnValue?: unknown; error?: string }): void => {\n let data: string;\n try {\n data = JSON.stringify({ resolveId, ...result });\n } catch (e) {\n data = JSON.stringify({\n resolveId,\n error: `[angular-lynx] The return value can't be sent to the other thread: ${errorText(e)}`,\n });\n }\n send(data);\n };\n let returnValue: unknown;\n try {\n returnValue = run();\n } catch (e) {\n reply({ error: errorText(e) });\n return;\n }\n if (isThenable(returnValue)) {\n returnValue.then(\n (value) => reply({ returnValue: value }),\n (e: unknown) => reply({ error: errorText(e) }),\n );\n } else {\n reply({ returnValue });\n }\n};\n","import { DestroyRef, inject } from '@angular/core';\nimport { __workletMap } from '../worklet-bridge';\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\n/**\n * The DestroyRef of the component, directive or service being constructed, or\n * null outside an injection context, such as at module level. Angular has no\n * public check for an injection context, and `inject()` throws outside one.\n */\nconst constructorDestroyRef = (): DestroyRef | null => {\n try {\n return inject(DestroyRef);\n } catch {\n return null;\n }\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 // A class property with the 'main thread' directive becomes a\n // mainThreadFn() call in the constructor, so each instance registers its\n // own function. Releasing it with the instance keeps a component that's\n // created many times, such as a list row, from piling up registrations.\n constructorDestroyRef()?.onDestroy(() => {\n delete __workletMap[id];\n });\n }\n\n return {\n _wkltId: id,\n _workletType: 'main-thread',\n __isMainThreadFn: true,\n } as MainThreadFnHandle<TArgs, TReturn>;\n};\n","/**\n * The main thread calls a background function by its `_wkltId`, and the\n * background thread finds the function it registered under the same ID. A\n * module that calls backgroundFn() at module level runs on both threads: the\n * background thread's entry imports every such module at startup\n * (background-entry.ts in the build plugin). The build gives each such call an\n * ID from its file and position (cross-thread-transform.ts there), which\n * matches on both threads whatever order their modules load in.\n *\n * A call the build doesn't tag, such as one inside a function, takes the next\n * '__angular_bg_N' instead. That only matches if both threads make the same\n * calls in the same order, and Angular code such as a constructor runs on the\n * main thread only, so its handle reaches no 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\n/**\n * Registers `fn` on the background thread and returns a handle that\n * `runOnBackground()` calls it with from the main thread.\n *\n * @param fn - The function to run on the background thread.\n * @param id - Set by the build for a module-level call, so the handle has the\n * same ID on both threads. Don't pass it yourself.\n * @returns The handle.\n */\nexport const backgroundFn = <TArgs extends unknown[], TReturn>(\n fn: (...args: TArgs) => TReturn,\n id?: string,\n): BackgroundFnHandle<TArgs, TReturn> => {\n const workletId = id ?? '__angular_bg_' + nextBgWorkletId++;\n\n if (!__MAIN_THREAD__) {\n globalThis.registerWorklet('background', workletId, fn);\n }\n\n return {\n _wkltId: workletId,\n _workletType: 'background',\n __isBackgroundFn: true,\n } as BackgroundFnHandle<TArgs, TReturn>;\n};\n","import { __mainThreadRefMap } from '../worklet-bridge';\n\n/**\n * Cross-thread shared reference. Each thread has its own instance, found by\n * its _wvid in __mainThreadRefMap (also the `__workletRefMap` global).\n * When a MainThreadRef is passed as a param to runOnMainThread() or\n * runOnBackground(), JSON.stringify serializes it via toJSON() → { _wvid }.\n * The receiving thread's cross-thread listener (global-callbacks.ts) swaps the\n * marker for its own instance from the map, so the function gets the ref it\n * would also reach through its closure.\n *\n * A ref created at module level exists on both threads: the background\n * thread's entry imports every module that creates one (background-entry.ts\n * in the build plugin). The build gives each such call an ID from its file and\n * position (cross-thread-transform.ts in the build plugin), so it matches on\n * both threads whatever order their modules run in. A ref created anywhere\n * else, such as in a component, exists only on the main thread, where Angular\n * runs, and takes the next number instead.\n */\nlet nextRefId = 0;\n\nexport class MainThreadRef<T> {\n readonly _wvid: number | string;\n #_value: T;\n\n /**\n * @param initValue - The ref's starting value.\n * @param id - Set by the build for a ref created at module level, so the\n * ref has the same ID on both threads. Don't pass it yourself.\n */\n constructor(initValue: T, id?: string) {\n this._wvid = id ?? nextRefId++;\n this.#_value = initValue;\n\n // Both threads register: a ref passed to the other thread arrives as a\n // { _wvid } marker that the receiving thread resolves here.\n __mainThreadRefMap[this._wvid] = this;\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 resolves { _wvid } back to its own registered\n * MainThreadRef instance.\n */\n toJSON(): { _wvid: number | string } {\n return { _wvid: this._wvid };\n }\n}\n\n/**\n * Creates a {@link MainThreadRef}.\n *\n * @param initValue - The ref's starting value.\n * @param id - Set by the build for a ref created at module level. Don't pass\n * it yourself.\n * @returns The new ref.\n */\nexport const createMainThreadRef = <T>(\n initValue: T,\n id?: string,\n): MainThreadRef<T> => new MainThreadRef(initValue, id);\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 { __workletMap } from '../worklet-bridge';\nimport type { MainThreadFnHandle } from './main-thread-fn';\n\n/**\n * Plain functions are also accepted: the worklet build plugin turns one with\n * the 'main thread' directive into a MainThreadFnHandle at compile time, so\n * TypeScript only sees the function, and the directive registers any other\n * function itself.\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 // A desktop browser never fires touch events, so on Lynx for Web a mouse\n // drag needs these. Native Lynx on a phone never fires them, and a mobile\n // browser only fires them after a tap, so binding both is safe.\n mainThreadBindmousedown: ['bindEvent', 'mousedown'],\n mainThreadCatchmousedown: ['catchEvent', 'mousedown'],\n mainThreadBindmousemove: ['bindEvent', 'mousemove'],\n mainThreadCatchmousemove: ['catchEvent', 'mousemove'],\n mainThreadBindmouseup: ['bindEvent', 'mouseup'],\n mainThreadCatchmouseup: ['catchEvent', 'mouseup'],\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// IDs for the plain functions the directive registers itself. They have their\n// own prefix so they never collide with the IDs mainThreadFn() gives.\nlet nextHandlerId = 0;\n\n/**\n * The __AddEvent value that removes a main-thread handler: a worklet with no\n * ID, which runWorklet ignores. `undefined` works on the web, but native Lynx\n * keeps the handler: Element::RemoveEvent erases from `static_events_`, while\n * worklet handlers live in `lepus_events_` (attribute_holder.cc). React Lynx\n * removes them the same way (updateWorkletEvent in workletEvent.ts).\n */\nconst noHandler = (): {\n type: 'worklet';\n value: { _workletType: 'main-thread' };\n} => ({ type: 'worklet', value: { _workletType: 'main-thread' } });\n\n/** A handler the directive has passed to __AddEvent for one of its inputs. */\ntype Registration = {\n eventType: string;\n eventName: string;\n /** The ID the directive registered a plain function under, and releases. */\n ownId?: string;\n};\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)` handlers run on the main thread too (listen() registers\n * them as worklets), but each one goes through Angular's listener wrapper,\n * which marks the view for change detection on every dispatch: too much for\n * gesture-driven UI (scroll-tracking, drag, pinch) that mutates styles at\n * native frame rate. Their event's targets are also plain data.\n * - The `mainThreadBind*` / `mainThreadCatch*` family registers the function\n * itself as a *worklet* with `_workletType: 'main-thread'`, so Lynx invokes\n * it directly, and runWorklet hands it MainThreadElement targets, whose\n * __AddInlineStyle / __SetAttribute calls are synchronous. Angular does no\n * work per event.\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 '[mainThreadBindmousedown],[mainThreadCatchmousedown],' +\n '[mainThreadBindmousemove],[mainThreadCatchmousemove],' +\n '[mainThreadBindmouseup],[mainThreadCatchmouseup],' +\n '[mainThreadBindlongpress],[mainThreadCatchlongpress],' +\n '[mainThreadBindscroll],[mainThreadCatchscroll],' +\n '[mainThreadBindanimationstart],[mainThreadBindanimationend],' +\n '[mainThreadBindtransitionend],[mainThreadBindlayoutchange]',\n inputs: [\n 'mainThreadBindtap',\n 'mainThreadCatchtap',\n 'mainThreadBindtouchstart',\n 'mainThreadCatchtouchstart',\n 'mainThreadBindtouchmove',\n 'mainThreadCatchtouchmove',\n 'mainThreadBindtouchend',\n 'mainThreadCatchtouchend',\n 'mainThreadBindmousedown',\n 'mainThreadCatchmousedown',\n 'mainThreadBindmousemove',\n 'mainThreadCatchmousemove',\n 'mainThreadBindmouseup',\n 'mainThreadCatchmouseup',\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 readonly #registrations = new Map<string, Registration>();\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 mainThreadBindmousedown?: MaybeHandle;\n mainThreadCatchmousedown?: MaybeHandle;\n mainThreadBindmousemove?: MaybeHandle;\n mainThreadCatchmousemove?: MaybeHandle;\n mainThreadBindmouseup?: MaybeHandle;\n mainThreadCatchmouseup?: 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 this.#release(inputName);\n\n const registration: Registration = { eventType, eventName };\n let workletId: string | undefined;\n if (isMainThreadHandle(handle)) {\n workletId = handle._wkltId;\n } else if (typeof handle === 'function') {\n // A function the build didn't wrap, such as a method without the\n // directive. This copy of the app runs on the main thread, where the\n // function already lives, so registering it is all a handle would do.\n // Skipping it would leave the element silently without a handler.\n workletId = '__angular_mts_handler_' + nextHandlerId++;\n registration.ownId = workletId;\n __workletMap[workletId] = handle;\n }\n\n if (workletId === undefined) {\n // null or undefined removes the handler, as unbinding a DOM listener\n // would. Leaving it registered would keep the old handler firing.\n if (this.#registrations.delete(inputName)) {\n __AddEvent(elementRef, eventType, eventName, noHandler());\n }\n continue;\n }\n\n // type: 'worklet' tells the Lynx engine to invoke this handler via the\n // worklet system (runWorklet) on the main thread, NOT via the\n // background-thread event dispatch Lynx defaults to. _workletType:\n // 'main-thread' ensures the handler runs on the Lepus thread where it can\n // call __AddInlineStyle, __SetAttribute, etc. for 60fps animations\n // without cross-thread latency.\n // A new handler for the same event replaces the old one natively.\n __AddEvent(elementRef, eventType, eventName, {\n type: 'worklet',\n value: { _wkltId: workletId, _workletType: 'main-thread' },\n });\n this.#registrations.set(inputName, registration);\n }\n }\n\n ngOnDestroy(): void {\n const elementRef = (this.#el as any).element;\n if (!elementRef) return;\n\n // Lynx's PAPI has no __RemoveEvent: __AddEvent replaces the handler, here\n // with one that does nothing (see noHandler). Without this cleanup, the\n // worklet handle would keep its registration pointing at a destroyed\n // component, and any subsequent native dispatch would invoke a stale\n // closure (or, worse, leak a reference that pins the component graph).\n for (const [inputName, { eventType, eventName }] of this.#registrations) {\n __AddEvent(elementRef, eventType, eventName, noHandler());\n this.#release(inputName);\n }\n this.#registrations.clear();\n }\n\n /**\n * Unregisters the plain function the directive registered for an input, if\n * any, so replacing or removing it doesn't leave the old one in the registry.\n */\n #release(inputName: string): void {\n const ownId = this.#registrations.get(inputName)?.ownId;\n if (ownId !== undefined) {\n delete __workletMap[ownId];\n }\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 Angular\n * code, and getting their return values.\n *\n * Angular runs on the main thread only (see bootstrapApplication), so the\n * call never crosses threads: it invokes the registered worklet in place,\n * with the arguments as they are, and resolves with its result. Non-\n * serializable values (element handles, MainThreadRefs) pass through intact.\n *\n * It used to send the call across threads when it ran on the background\n * thread, for the copy of the app that booted there too. That copy is gone\n * (issue #81), and with it the background-to-main call channel.\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 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 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","import { Injectable } from '@angular/core';\nimport { callOnBackground } from '../background-call';\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 * Lynx has these APIs only on the background thread, while Angular runs on\n * the main thread, so the calls go through the background call relay\n * (background-call.ts).\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 return callOnBackground(\n 'requestResourcePrefetch',\n this.#toNativeData(resources),\n ) as Promise<ResourcePrefetchResult>;\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 return callOnBackground(\n 'cancelResourcePrefetch',\n this.#toNativeData(resources),\n ) as Promise<ResourcePrefetchResult>;\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, signal } from '@angular/core';\nimport type { SystemInfo, PlatformType } from '@lynx-js/types';\nimport { callOnBackground, isMainThread } from '../background-call';\n\n/**\n * The OS version the host app sent in its global props, if it sent one. The\n * apps `ng build --platform` makes send `osVersion`, because the native main\n * thread's `SystemInfo` has none (see {@link LynxSystemInfo.osVersion}).\n */\nconst hostOsVersion = (): string | undefined => {\n const value =\n typeof lynx !== 'undefined'\n ? (lynx.__globalProps as Record<string, unknown> | undefined)?.[\n 'osVersion'\n ]\n : undefined;\n return typeof value === 'string' && value !== '' ? value : undefined;\n};\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 * On iOS and Android (Lynx 4.1), the main thread has no global `SystemInfo`,\n * only `lynx.SystemInfo`, so that's read first. The background thread and the\n * web have the global. The main thread's copy has no `osVersion` either: see\n * {@link LynxSystemInfo.osVersion} for where that comes from instead.\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 * The OS version, from wherever it's known: SystemInfo, the host's global\n * props, or the background thread's SystemInfo, which answers later. A\n * signal, so a `computed()` reading {@link osVersion} sees the late answer.\n */\n readonly #osVersion = signal<string | undefined>(undefined);\n\n constructor() {\n const info =\n (typeof lynx !== 'undefined'\n ? (lynx as { SystemInfo?: SystemInfo }).SystemInfo\n : undefined) ??\n (typeof SystemInfo !== 'undefined' ? SystemInfo : undefined);\n if (!info) {\n throw new Error('SystemInfo is not available in this environment');\n }\n this.#info = info;\n this.#osVersion.set(info.osVersion || hostOsVersion());\n // Lynx builds the native main thread's SystemInfo, where Angular runs,\n // without the OS version (GenerateSystemInfo in Lynx core), so ask the\n // background thread's, which has it. It answers after the first frame, so\n // a host app that knows the version should send it as the `osVersion`\n // global prop, as the generated apps do.\n if (this.#osVersion() === undefined && isMainThread()) {\n callOnBackground('osVersion').then(\n (version) => {\n if (version) this.#osVersion.set(version);\n },\n () => {\n // No background thread to ask: the version stays unknown.\n },\n );\n }\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, such as `'26.1'` on iOS or `'15'`\n * on Android. Empty while it isn't known.\n *\n * The native main thread's SystemInfo lacks it, so there it comes from the\n * host app's `osVersion` global prop, or else from the background thread,\n * which answers shortly after the first frame. It reads a signal, so a\n * `computed()` that reads it updates when the answer arrives.\n */\n get osVersion(): string {\n return this.#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, Injector } 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 // LynxSystemInfo throws where there's no SystemInfo, such as in unit tests,\n // and only `platform` needs it, so it's looked up when that's read.\n readonly #injector = inject(Injector);\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.#injector.get(LynxSystemInfo).platform;\n }\n}\n","import {\n type Injector,\n DestroyRef,\n inject,\n Injectable,\n signal,\n} from '@angular/core';\nimport {\n subscribeSessionStorageFromMainThread,\n unsubscribeSessionStorageFromMainThread,\n} from '../background-call';\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. Subscriptions\n * made there go through the background thread (see background-call.ts).\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 /** Background-thread subscriptions made for main-thread listeners, by listener ID. */\n readonly #relayIds = new Map<number, number>();\n\n /**\n * Lynx for Web's background `lynx` declares the session storage methods\n * (lynx-core is the same script on every platform), but web-core's NativeApp\n * implements none of the ones they forward to: `getSessionStorageItem` throws\n * \"getNativeApp(...).getSessionStorageItem is not a function\" and crashed\n * the session-storage example in the docs' live preview. So the web uses the\n * in-memory fallback, like tests and SSR.\n *\n * `@lynx-js/types`' `PlatformType` leaves out the `'web'` that web-core\n * reports, hence the widening to `string`.\n */\n #hasNativeSessionStorage(): boolean {\n return (\n typeof lynx !== 'undefined' &&\n typeof (lynx as any).setSessionStorageItem === 'function' &&\n !(\n typeof SystemInfo !== 'undefined' &&\n (SystemInfo.platform as string) === 'web'\n )\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 * there uses the local listener map, plus a subscription made through the\n * background thread (see {@link subscribe}).\n */\n #hasNativeSubscription(): boolean {\n return this.#hasNativeSessionStorage() && !this.#isMainThread();\n }\n\n #isMainThread(): boolean {\n return typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__;\n }\n\n /**\n * Undoes setItem's main-thread wrapping of primitives, so callers get back\n * exactly what they stored. Applies wherever a value written on the main\n * thread can come back: main-thread reads, and background-thread reads and\n * notifications. The `Object.keys(raw).length === 1` guard keeps this from\n * mangling genuine user objects: a real payload that happens to have a\n * `__data` key (e.g. `{ __data, other }`) has more than one key and is\n * returned untouched, so only our own single-key wrapper { __data } is\n * unwrapped.\n */\n #unwrap<T>(raw: unknown): T {\n return (\n raw != null &&\n typeof raw === 'object' &&\n '__data' in raw &&\n Object.keys(raw).length === 1\n ? raw.__data\n : raw\n ) as T;\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 (this.#isMainThread()) {\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 (this.#isMainThread()) {\n return Promise.resolve(\n this.#unwrap<T>((lynx as any).getSessionStorageItem(key)),\n );\n }\n\n return new Promise<T>((resolve) => {\n (lynx as any).getSessionStorageItem(key, (value: unknown) =>\n resolve(this.#unwrap<T>(value)),\n );\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 (value: unknown) => callback(this.#unwrap<T>(value)),\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\n // The local map only sees this thread's own writes. On the main thread,\n // another LynxView's writes reach only a native subscription, which only\n // the background thread can make, so subscribe there too.\n if (this.#isMainThread() && this.#hasNativeSessionStorage()) {\n this.#relayIds.set(\n id,\n subscribeSessionStorageFromMainThread(key, (value) =>\n callback(this.#unwrap<T>(value)),\n ),\n );\n }\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 const relayId = this.#relayIds.get(subscription.listenerId);\n if (relayId !== undefined) {\n this.#relayIds.delete(subscription.listenerId);\n unsubscribeSessionStorageFromMainThread(relayId);\n }\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 // The web preview's main-thread lynx has no getTextInfo. Native has it on\n // both threads.\n if (\n typeof lynx === 'undefined' ||\n typeof (lynx as any).getTextInfo !== 'function'\n ) {\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 * The Material 3 color roles that dynamic color gives, by Material's names.\n * The error roles aren't here: Material keeps them red whatever the\n * wallpaper.\n */\nexport const DYNAMIC_COLOR_ROLES = [\n 'primary',\n 'onPrimary',\n 'primaryContainer',\n 'onPrimaryContainer',\n 'inversePrimary',\n 'secondary',\n 'onSecondary',\n 'secondaryContainer',\n 'onSecondaryContainer',\n 'tertiary',\n 'onTertiary',\n 'tertiaryContainer',\n 'onTertiaryContainer',\n 'background',\n 'onBackground',\n 'surface',\n 'onSurface',\n 'surfaceVariant',\n 'onSurfaceVariant',\n 'surfaceDim',\n 'surfaceBright',\n 'surfaceContainerLowest',\n 'surfaceContainerLow',\n 'surfaceContainer',\n 'surfaceContainerHigh',\n 'surfaceContainerHighest',\n 'inverseSurface',\n 'inverseOnSurface',\n 'outline',\n 'outlineVariant',\n] as const;\n\nexport type DynamicColorRole = (typeof DYNAMIC_COLOR_ROLES)[number];\n\n/**\n * Each role's color, as a hex color such as `#6750a4`.\n */\nexport type DynamicColorScheme = { readonly [R in DynamicColorRole]: string };\n\n/** The color scheme for each appearance: the app can be in either. */\nexport type DynamicColors = {\n readonly light: DynamicColorScheme;\n readonly dark: DynamicColorScheme;\n};\n\nconst HEX_COLOR = /^#[0-9a-f]{6}$/i;\n\n/**\n * A scheme as the host sent it, if it has a hex color (`#6750a4`) for every\n * role.\n * Half a scheme would mix the wallpaper's colors with the app's, so it counts\n * as none.\n */\nconst parseScheme = (value: unknown): DynamicColorScheme | null => {\n if (typeof value !== 'object' || value === null) return null;\n const colors = value as Record<string, unknown>;\n const scheme: Record<string, string> = {};\n for (const role of DYNAMIC_COLOR_ROLES) {\n const color = colors[role];\n if (typeof color !== 'string' || !HEX_COLOR.test(color)) return null;\n scheme[role] = color;\n }\n return scheme as DynamicColorScheme;\n};\n\nconst parseDynamicColors = (value: unknown): DynamicColors | null => {\n if (typeof value !== 'object' || value === null) return null;\n const { light, dark } = value as Record<string, unknown>;\n const lightScheme = parseScheme(light);\n const darkScheme = parseScheme(dark);\n return lightScheme && darkScheme\n ? { light: lightScheme, dark: darkScheme }\n : null;\n};\n\nconst sameColors = (a: DynamicColors | null, b: DynamicColors | null) =>\n a === b ||\n (a !== null &&\n b !== null &&\n DYNAMIC_COLOR_ROLES.every(\n (role) =>\n a.light[role] === b.light[role] && a.dark[role] === b.dark[role],\n ));\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 /**\n * The colors Android 12 and later take from the user's wallpaper (Material\n * You's dynamic color), as Material 3's color roles in light and dark, or\n * `null` where the host sends none.\n *\n * Lynx has no API for them, so they come from the host app, in its\n * `dynamicColors` global prop: `{ light, dark }`, each with a hex color,\n * such as `#6750a4`, for every role in {@link DYNAMIC_COLOR_ROLES}. The\n * Android app `ng build --platform android` makes sends them, and new ones\n * when the user changes their wallpaper or colors. iOS, the web preview and\n * Lynx Explorer have none.\n *\n * Both schemes come at once, so an app with a dark mode of its own can\n * follow it rather than the phone's.\n */\n readonly dynamicColors = computed(\n () =>\n parseDynamicColors(\n (this.#globalData.globalData() as Record<string, unknown>)[\n 'dynamicColors'\n ],\n ),\n // Every global prop update reaches here, such as new safe-area insets,\n // and the colors seldom change with them.\n { equal: sameColors },\n );\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 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 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 { 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","/**\n * The id the page gets on Android, so that every `blur-view` can name the\n * page as the view it blurs (`android-capture-target`).\n *\n * Android's blur-view isn't a real backdrop blur. It redraws one ancestor view\n * into a bitmap and blurs that, and while it redraws, every blur-view in that\n * ancestor skips drawing itself (so it doesn't blur its own output). Left to\n * itself, it picks the nearest ancestor that is `overflow: hidden` or contains\n * it. For a blur-view inside another blur-view, such as a glass shape in a\n * `glass-container` or a button on a frosted panel, that ancestor is the outer\n * blur-view: the redraw holds nothing, and the inner blur-view shows nothing.\n * Redrawing the page instead blurs what is on screen behind the blur-view,\n * which is what iOS does. Only the blur-view's own area is redrawn.\n */\nexport const ANDROID_BLUR_CAPTURE_TARGET = 'angular-lynx-page';\n\n/**\n * Whether this is Lynx's Android renderer. On the native main thread, where\n * elements are created, there is no global `SystemInfo`, only\n * `lynx.SystemInfo`; the background thread and web have the global.\n */\nexport const isAndroid = (): boolean => {\n const info =\n (typeof lynx !== 'undefined'\n ? (lynx as { SystemInfo?: { platform?: string } }).SystemInfo\n : undefined) ??\n (typeof SystemInfo !== 'undefined' ? SystemInfo : undefined);\n return info?.platform === 'Android';\n};\n","import type { ElementRef } from '../../types/lynx';\nimport {\n ANDROID_BLUR_CAPTURE_TARGET,\n isAndroid,\n} from '../android-blur-capture';\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 *\n * Lynx for Web's `blur-view` only implements `blur-radius` and doesn't lay its\n * children out like a view, so on web `attachWebGlass` adds both.\n *\n * On Android it blurs the page (see ANDROID_BLUR_CAPTURE_TARGET), so a\n * blur-view inside another one still shows its backdrop. An app's own\n * `android-capture-target` replaces this, and an empty one restores Android's\n * own choice.\n */\nexport const createBlurViewElement = (pageId: number): ElementRef => {\n const element = __CreateElement('blur-view', pageId);\n if (!__WEB__ && isAndroid()) {\n __SetAttribute(\n element,\n 'android-capture-target',\n ANDROID_BLUR_CAPTURE_TARGET,\n );\n }\n // `__WEB__` is a compile-time define: on native the bundler drops this\n // branch before it follows the import, so none of the WebGL code ships\n // there. A static import wouldn't do: the minifier can't prove the glass\n // classes side-effect free once they're compiled for the main thread, so it\n // would keep them. On web the build inlines the import, and the glass\n // attaches a microtask after the element is created, before it's on screen.\n // Only the main thread draws; web's background thread never gets here with\n // a real element, but `__MAIN_THREAD__` keeps it from loading the module.\n if (__WEB__ && __MAIN_THREAD__) {\n import('../../web-glass/web-glass')\n .then(({ attachWebGlass }) => attachWebGlass(element))\n .catch(() => {\n // Glass is decoration: without its module the blur fallback stays.\n });\n }\n return element;\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\n/**\n * No defaults to set: like React Lynx, an `<image>` starts with Lynx's own\n * `mode`, `scaleToFill`, which iOS, Android and the web all share (and which\n * matches the web's `object-fit: fill`). Setting a different one would have to\n * go through `__SetAttribute`: `__SetConfig` only stores a table for\n * `__GetConfig`, and never reaches the native image or `x-image`.\n */\nexport const createImageElement = (pageId: number): ElementRef => {\n return __CreateImage(pageId);\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 *\n * No default styles, as in React Lynx: a field is one line of text tall on\n * every platform (iOS and Android measure it from the font), and it has no\n * border. Inline defaults would beat the app's classes, so `h-[120px]` or\n * `border-zinc-200` on an `<input>` would never apply.\n */\nexport const createInputElement = (\n tag: 'input' | 'textarea',\n pageId: number,\n): ElementRef => {\n return __CreateElement(tag, pageId);\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 { isAndroid } from './android-blur-capture';\n\n/**\n * The CSS variables that the build plugin's `blur-view` rule reads (its\n * `blur-view.css`, which only the native bundle gets):\n *\n * blur-view {\n * background-color: var(--angular-lynx-blur-background, transparent);\n * background-image: var(--angular-lynx-blur-background-image, none);\n * box-shadow: var(--angular-lynx-blur-box-shadow, none);\n * }\n *\n * Lynx implements `blur-effect` and the `glass-*` attributes on iOS only, so\n * on Android every blur-view is a plain Gaussian blur. Android's BlurView draws\n * the blurred backdrop first and then the view's own background and children,\n * so a translucent background on top approximates iOS's materials, as the web\n * build does in glass-host-style.ts.\n *\n * The runtime can't set that background inline: an inline style beats the\n * app's classes (`bg-white/30`), and the runtime can't tell which classes set\n * one. So it sets only these variables inline, and the rule above uses them.\n * A type selector loses to any class, id or inline style the app sets, so the\n * app's own background or shadow still wins.\n *\n * Every Android blur-view sets all three variables, `transparent` and `none`\n * when it has no material. CSS variables inherit, so a blur-view inside a `dark`\n * panel would otherwise take the panel's tint.\n */\nexport const BLUR_BACKGROUND_VARIABLE = '--angular-lynx-blur-background';\nexport const BLUR_BACKGROUND_IMAGE_VARIABLE =\n '--angular-lynx-blur-background-image';\nexport const BLUR_BOX_SHADOW_VARIABLE = '--angular-lynx-blur-box-shadow';\n\n/** The attributes the approximation depends on. */\nexport const BLUR_MATERIAL_ATTRIBUTES: ReadonlySet<string> = new Set([\n 'blur-effect',\n 'blur-radius',\n 'glass-style',\n 'glass-tint-color',\n]);\n\n/**\n * The tint each material puts over the blur. Fitted to the iOS Simulator's\n * pixels in the element-blur-view example: `extra-light` washes the backdrop\n * with white and `dark` with black, the same values as on web. iOS's `light`\n * brightens and saturates the backdrop. Web does that with `brightness()`,\n * which Android's blur-view can't apply to the backdrop, so here a white\n * gives it the same lightness, though paler.\n */\nconst MATERIAL_BACKGROUNDS: Readonly<Record<string, string>> = {\n light: 'rgba(255, 255, 255, 0.3)',\n 'extra-light': 'rgba(255, 255, 255, 0.75)',\n dark: 'rgba(0, 0, 0, 0.6)',\n};\n\n/**\n * A glass shape's frosted look: a white sheen with `glass-tint-color` over\n * it, and a rim, like iOS's glass without the refraction. iOS lightens what's\n * behind the glass before it tints it, so the tint goes on the sheen, as a\n * background image, rather than replacing it. `clear` glass is barely\n * lightened. Fitted to the same example as the materials.\n *\n * The rim is a bright top edge and a faint dark outline, which is what keeps\n * iOS's glass visible over white. Inset shadows draw it without changing the\n * layout, as a border would.\n */\nconst GLASS_SHEEN = 'rgba(255, 255, 255, 0.3)';\nconst CLEAR_GLASS_SHEEN = 'rgba(255, 255, 255, 0.1)';\nconst GLASS_RIM =\n 'inset 0 1px 0 rgba(255, 255, 255, 0.5), inset 0 0 0 1px rgba(0, 0, 0, 0.12)';\n\n/**\n * Whether blur-views get the approximation: only on Android's native\n * renderer. iOS draws the real materials, and web has its own (see web-glass).\n */\nexport const usesAndroidBlurMaterials = (): boolean => !__WEB__ && isAndroid();\n\nconst declarations = (\n background: string,\n { image = 'none', boxShadow = 'none' } = {},\n): string =>\n `${BLUR_BACKGROUND_VARIABLE}: ${background}; ` +\n `${BLUR_BACKGROUND_IMAGE_VARIABLE}: ${image}; ` +\n `${BLUR_BOX_SHADOW_VARIABLE}: ${boxShadow}`;\n\n/**\n * The inline declarations that give a blur-view with `attrs` its material on\n * Android. Like on iOS, a material needs a blur radius, while glass doesn't,\n * and a `glass-container` draws nothing of its own.\n */\nexport const androidBlurMaterialStyle = (\n attrs: ReadonlyMap<string, unknown>,\n): string => {\n const effect = attrs.get('blur-effect') ?? 'light';\n if (effect === 'glass') {\n const tint = attrs.get('glass-tint-color');\n return declarations(\n attrs.get('glass-style') === 'clear' ? CLEAR_GLASS_SHEEN : GLASS_SHEEN,\n {\n // A one-color gradient is how CSS layers a color over a background\n // color.\n image:\n typeof tint === 'string' && tint !== '' && tint !== 'transparent'\n ? `linear-gradient(${tint}, ${tint})`\n : 'none',\n boxShadow: GLASS_RIM,\n },\n );\n }\n if (\n effect === 'glass-container' ||\n !parseFloat(String(attrs.get('blur-radius') ?? ''))\n ) {\n return declarations('transparent');\n }\n // iOS falls back to `light` for an effect it doesn't know.\n return declarations(\n MATERIAL_BACKGROUNDS[String(effect)] ?? MATERIAL_BACKGROUNDS['light'],\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\n/**\n * Set by a hot update's re-bootstrap (see `bootstrapApplication`), so the next\n * root element takes over the page the old app rendered into rather than\n * creating one (see `LynxDocument.createRootElement`). Only a re-bootstrap\n * may: anything else that creates a new app, such as each test's `render()`,\n * runs in a fresh Lynx environment, where the page this module remembers is\n * gone.\n */\nlet handingOverPage = false;\n\nexport const handOverPageToNextApp = (): void => {\n handingOverPage = true;\n};\n\n/**\n * Whether the next app takes over the current page. Reading it clears it.\n */\nexport const takePageHandOver = (): boolean => {\n const handing = handingOverPage;\n handingOverPage = false;\n return handing;\n};\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","/**\n * Keeps `<svg content>` strings parseable by Lynx's native SVG engine.\n *\n * ServalSVG, which draws `<svg>` on iOS (and in Lynx's C++ SVG core generally),\n * parses `stroke-dasharray` with a loop that only advances while it's reading a\n * number. Any other token, such as `none`, a unit like `4px`, or `inherit`,\n * leaves it stuck on the same character forever. Worse, the parse runs on one\n * serial queue shared by every `<svg>` in the process, so a single such\n * attribute (TanStack Charts writes `stroke-dasharray=\"none\"` on its bars)\n * blanks every icon and chart in the app until it's killed, with no error.\n *\n * The rewrite keeps what ServalSVG can draw: bare numbers, and `px` lengths,\n * which equal user units in SVG. Anything else is dropped, which on native is\n * the only way to get a drawing at all. `none` is the default anyway; a value\n * that can't be resolved here (`%`, `em`) would have hung the engine.\n */\n\nconst DASHARRAY_ATTRIBUTE =\n /(\\s)stroke-dasharray\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)')/g;\n// A declaration inside an inline `style=\"…\"` (ServalSVG reads those too).\nconst DASHARRAY_DECLARATION = /(^|[;\"'\\s])stroke-dasharray\\s*:\\s*([^;\"']*);?/g;\nconst DASH_LENGTH = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:e[+-]?\\d+)?(?:px)?$/i;\n\n/**\n * Returns the dash lengths as a space-separated list of bare numbers, or\n * `null` when any part of the value isn't a plain length.\n */\nexport const normalizeDashArray = (value: string): string | null => {\n const tokens = value\n .trim()\n .split(/[\\s,]+/)\n .filter((token) => token.length > 0);\n if (tokens.length === 0 || !tokens.every((t) => DASH_LENGTH.test(t))) {\n return null;\n }\n return tokens.map((token) => token.replace(/px$/i, '')).join(' ');\n};\n\nexport const sanitizeSvgContent = (content: string): string => {\n // Most SVG (icons) has no dash arrays: skip the regex work entirely.\n if (!content.includes('stroke-dasharray')) return content;\n return content\n .replace(\n DASHARRAY_ATTRIBUTE,\n (_match, space: string, double?: string, single?: string) => {\n // The pattern matches one quote style or the other, so one is set.\n const normalized = normalizeDashArray((double ?? single)!);\n return normalized === null\n ? ''\n : `${space}stroke-dasharray=\"${normalized}\"`;\n },\n )\n .replace(DASHARRAY_DECLARATION, (_match, before: string, value: string) => {\n const normalized = normalizeDashArray(value);\n return normalized === null\n ? before\n : `${before}stroke-dasharray:${normalized};`;\n });\n};\n","/**\n * Long presses on Lynx for Web, which never fires `longpress`.\n *\n * Native Lynx recognizes a long press itself and fires `longpress` instead\n * of `tap` when a finger stays down. Lynx for Web's event handling has no\n * recognizer for it (`@lynx-js/web-core` passes DOM events through and maps\n * `click` to `tap`, and nothing else), so `(bindlongpress)` never ran in the\n * web preview: a long press was a tap. LynxElement recognizes one from the\n * element's touch and mouse events instead (see #listenForWebLongPress).\n */\n\n/**\n * How long a press is held before it's a long press, in ms: iOS's default\n * (`UILongPressGestureRecognizer.minimumPressDuration`), close to Android's.\n */\nexport const LONG_PRESS_DURATION = 500;\n\n/**\n * How far a press can move, in px, and still become a long press. Further,\n * it's a drag or a scroll.\n */\nconst LONG_PRESS_SLOP = 10;\n\n/**\n * How long after a long press ends the tap that follows is dropped, in ms.\n * The browser sends `click`, which web-core turns into `tap`, right after the\n * finger or the mouse button comes up, where native Lynx sends no tap at all.\n */\nconst TAP_GRACE = 300;\n\n/** Whether taps are dropped now (see dropsTap). */\nlet tapsDropped = false;\n\n/**\n * Counts long presses, so that the end of an earlier one can't let taps\n * through again during a later one.\n */\nlet longPresses = 0;\n\n/**\n * Whether a tap now ends a long press, and so shouldn't run: from the moment\n * a long press fires until just after it ends. The browser's `click` goes to\n * whatever was under the pointer, so it's dropped wherever it lands.\n */\nexport const dropsTap = (): boolean => tapsDropped;\n\n/** Where a press is, in the `<lynx-view>`'s pixels. */\nexport type LongPressPoint = { readonly x: number; readonly y: number };\n\n/**\n * Where a web-core touch or mouse event happened. A touch event has the\n * first touch's position in `detail`; a mouse event has it on the event, and\n * its `detail` is the DOM's click count.\n */\nconst pointOf = (event: {\n readonly detail?: unknown;\n readonly x?: number;\n readonly y?: number;\n}): LongPressPoint => {\n const { x = 0, y = 0 } =\n typeof event.detail === 'object' && event.detail !== null\n ? (event.detail as LongPressPoint)\n : event;\n return { x, y };\n};\n\n/**\n * Recognizes long presses from one element's touch and mouse events, and\n * calls `fire` with where the press is when one has lasted\n * LONG_PRESS_DURATION without moving away.\n */\nexport class WebLongPress {\n readonly #fire: (point: LongPressPoint) => void;\n #timer: ReturnType<typeof setTimeout> | undefined;\n #start: LongPressPoint | null = null;\n #fired = false;\n\n constructor(fire: (point: LongPressPoint) => void) {\n this.#fire = fire;\n }\n\n /** `touchstart` and `mousedown`: a press starts. */\n readonly start = (event: {\n readonly detail?: unknown;\n readonly x?: number;\n readonly y?: number;\n readonly button?: number;\n }): void => {\n // A right click opens the browser's own menu; only the main button\n // presses. A touch has no button.\n if (event.button !== undefined && event.button !== 0) return;\n this.#stop();\n this.#fired = false;\n const point = pointOf(event);\n this.#start = point;\n this.#timer = setTimeout(() => {\n this.#timer = undefined;\n this.#fired = true;\n longPresses++;\n tapsDropped = true;\n this.#fire(point);\n }, LONG_PRESS_DURATION);\n };\n\n /** `touchmove` and `mousemove`: a press that moves too far is no long press. */\n readonly move = (event: {\n readonly detail?: unknown;\n readonly x?: number;\n readonly y?: number;\n }): void => {\n if (!this.#start) return;\n const { x, y } = pointOf(event);\n if (Math.hypot(x - this.#start.x, y - this.#start.y) > LONG_PRESS_SLOP) {\n this.#stop();\n }\n };\n\n /**\n * `touchend`, `touchcancel`, `mouseup` and `mouseleave`: the press is over.\n * The tap that ends a long press is dropped (see dropsTap).\n */\n readonly end = (): void => {\n this.#stop();\n this.#start = null;\n if (this.#fired) {\n this.#fired = false;\n const longPress = longPresses;\n setTimeout(() => {\n if (longPress === longPresses) tapsDropped = false;\n }, TAP_GRACE);\n }\n };\n\n #stop(): void {\n // The main thread's clearTimeout throws for undefined.\n if (this.#timer !== undefined) clearTimeout(this.#timer);\n this.#timer = undefined;\n }\n}\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\n/**\n * DOM event names whose Lynx event has another name. A listener for one of\n * them hears the Lynx event, bubbling, as if it were bound with `bind`: a\n * `(click)` listener runs on a tap. This is the mapping Lynx for Web makes\n * between the two (web-core's `W3cEventNameToLynx` turns a DOM `click` into\n * `tap`), and it's what lets Angular's own directives that listen for\n * `click`, such as `RouterLink`, work on Lynx elements.\n */\nexport const DOM_EVENT_ALIASES: ReadonlyMap<string, string> = new Map([\n ['click', 'tap'],\n]);\n\nimport type { Element as LynxJsElement } from '@lynx-js/types/main-thread';\n\n/**\n * Uses BaseLynxAnimation (not LynxAnimation), the animation's public API,\n * because LynxAnimation's ES private fields brand the class.\n */\nimport type {\n BaseLynxAnimation,\n LynxAnimationOptions,\n} from '../animation/animation';\n\n/**\n * The `nativeElement` of a Lynx element's `ElementRef`: AngularLynx's\n * wrapper around the native element, not a DOM element. Type an\n * `ElementRef` with it to call its methods, such as `animate()`, `invoke()`\n * or `setAccessibilityTrait()`.\n *\n * @usageNotes\n * ```ts\n * readonly option = viewChild.required<ElementRef<BaseLynxElement>>('option');\n * ```\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 /**\n * Adds a class that stays when the whole class list is replaced, for\n * ViewEncapsulation.Emulated's scope classes (see EmulatedLynxRenderer).\n */\n addScopeClass(name: string): void;\n removeClass(name: string): void;\n /**\n * Adds a trait to the element's own `accessibility-traits`, or takes it\n * away, keeping the traits the app sets. For state that changes, such as\n * `selected` on an active router link (see LynxRouterLinkActive). In a\n * template, LynxAccessibilityTraits does it from a binding.\n */\n setAccessibilityTrait(trait: string, on: boolean): 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 * LynxElement implements it via __InvokeUIMethod.\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 { isAndroid } from '../lynx-document/android-blur-capture';\nimport {\n androidBlurMaterialStyle,\n BLUR_MATERIAL_ATTRIBUTES,\n usesAndroidBlurMaterials,\n} from '../lynx-document/android-blur-material';\nimport { getPageId } from '../lynx-document/page-ref';\nimport {\n isFirstRenderPending,\n isInsideChangeDetection,\n} from '../lynx-render-lifecycle';\nimport type { ElementRef } from '../types/lynx';\nimport { sanitizeSvgContent } from './svg-content';\nimport { dropsTap, WebLongPress } from './web-long-press';\nimport {\n type BaseLynxElement,\n DOM_EVENT_ALIASES,\n EVENT_PREFIXES,\n type LynxEventType,\n} from './types';\n\ntype Listener = {\n eventType: LynxEventType;\n eventName: string;\n listener: (event: any) => any;\n};\n\n/**\n * The key native Lynx stores an element's event handler under. It keeps ONE\n * handler per event name (`AttributeHolder::SetStaticEvent` assigns into a map\n * keyed by name), whatever its bind/catch/capture type, so a second\n * `__AddEvent` for `tap` replaces the first. Global events have a map of\n * their own.\n */\nconst nativeEventKey = (type: LynxEventType, name: string): string =>\n type === 'global-bindEvent' ? `global:${name}` : name;\n\n/**\n * The one type an element's listeners for an event name can be registered\n * with natively (see nativeEventKey). `catch` wins over `bind`: every listener\n * on the element still runs, and the event stops there, as a `catch` listener\n * asked. A capture listener alongside a bubbling one is registered bubbling,\n * since the two phases can't share one native handler.\n */\nconst combinedEventType = (listeners: Listener[]): LynxEventType => {\n if (listeners[0].eventType === 'global-bindEvent') return 'global-bindEvent';\n const capture = listeners.every((l) => l.eventType.startsWith('capture-'));\n const stops = listeners.some((l) => l.eventType.endsWith('catchEvent'));\n if (capture) return stops ? 'capture-catchEvent' : 'capture-bindEvent';\n return stops ? 'catchEvent' : 'bindEvent';\n};\n\n/**\n * Parses a listener name from Angular (`bindtap`, `catchscroll`, `click`, …)\n * into the Lynx event type and name `__AddEvent` takes, or undefined for a\n * name Lynx has no event for.\n */\nconst parseEventName = (\n name: string,\n): Pick<Listener, 'eventType' | 'eventName'> | undefined => {\n const alias = DOM_EVENT_ALIASES.get(name);\n if (alias) return { eventType: 'bindEvent', eventName: alias };\n for (const [prefix, eventType] of EVENT_PREFIXES) {\n if (name.startsWith(prefix)) {\n return { eventType, eventName: name.slice(prefix.length) };\n }\n }\n return undefined;\n};\n\n/**\n * The `accessibility-traits` value to give an element: the app's own traits\n * plus the ones the runtime adds (see LynxElement.setAccessibilityTrait).\n *\n * iOS reads a comma-separated list with no spaces (`LynxConverter\n * toAccessibilityTraits:` splits on \",\" and compares each part exactly), so\n * that's what this writes. Android reads a single trait by exact match (none,\n * image or button), so a list would read as none there and drop the app's\n * own `button`; and it has no selected trait to add. So on Android the app's\n * traits are left as they are.\n */\nconst withAddedTraits = (own: unknown, added: readonly string[]): unknown => {\n if (added.length === 0 || isAndroid()) return own;\n const traits =\n own == null\n ? []\n : String(own)\n .split(',')\n .map((trait) => trait.trim())\n .filter((trait) => trait !== '' && trait !== 'none');\n for (const trait of added) {\n if (!traits.includes(trait)) traits.push(trait);\n }\n return traits.join(',');\n};\n\n/**\n * Whether a `setStyle` name is a CSS variable (`--x`), which only\n * `__SetInlineStyles` can set: `__AddInlineStyle` looks the name up as a CSS\n * property and drops it.\n */\nconst isCustomProperty = (name: string): boolean => name.startsWith('--');\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 * `element` and its ancestors, nearest first, up to the root of its tree.\n */\nconst ancestry = (element: ElementRef): ElementRef[] => {\n const path: ElementRef[] = [];\n for (let cur: ElementRef | null = element; cur; cur = __GetParent(cur)) {\n path.push(cur);\n }\n return path;\n};\n\n/**\n * True if a flush handles `first`'s child insertions and removals before\n * `second`'s. Lynx's flush (`Element::FlushActions` in\n * `core/renderer/dom/fiber/fiber_element.cc`) walks the element tree in\n * pre-order: an element's own child actions, then each child's subtree in\n * order. So an ancestor goes first, and otherwise the element whose branch\n * comes earlier under the two's nearest common ancestor. Elements in\n * different trees (one not attached yet) have no order, and count as not.\n *\n * Compares by unique ID for the same reason wouldFormCycle does.\n */\nconst flushesBefore = (first: ElementRef, second: ElementRef): boolean => {\n const firstPath = ancestry(first);\n const secondPath = ancestry(second);\n const secondDepth = new Map(\n secondPath.map((element, depth) => [__GetElementUniqueID(element), depth]),\n );\n for (let depth = 0; depth < firstPath.length; depth++) {\n const shared = secondDepth.get(__GetElementUniqueID(firstPath[depth]!));\n if (shared === undefined) continue;\n // firstPath[depth] is the nearest common ancestor. If it's `first` itself,\n // `first` is the ancestor; if it's `second`, `second` is.\n if (depth === 0) return true;\n if (shared === 0) return false;\n // The common ancestor has both branches among its children.\n const order = __GetChildren(firstPath[depth]!).map((child) =>\n __GetElementUniqueID(child),\n );\n return (\n order.indexOf(__GetElementUniqueID(firstPath[depth - 1]!)) <\n order.indexOf(__GetElementUniqueID(secondPath[shared - 1]!))\n );\n }\n return false;\n};\n\n/**\n * Whether this is Lynx's iOS renderer. On the native main thread there is no\n * global `SystemInfo`, only `lynx.SystemInfo` (see isAndroid).\n */\nconst isIOS = (): boolean => {\n const info =\n (typeof lynx !== 'undefined'\n ? (lynx as { SystemInfo?: { platform?: string } }).SystemInfo\n : undefined) ??\n (typeof SystemInfo !== 'undefined' ? SystemInfo : undefined);\n return info?.platform === 'iOS';\n};\n\n/**\n * Whether inserting `child` into `parent` before a sibling would leave it\n * drawing nothing: on iOS, a `<blur-view>` (a UIVisualEffectView) put among a plain\n * element's children anywhere but at the end shows nothing, nor do its\n * children, though the layout keeps its space. That's every blur-view at the\n * top of an `@if`, `@switch` or `@for` block, which Angular inserts before the\n * block's anchor. Appended, it draws, and so it does inside another\n * blur-view, whose native view inserts children its own way.\n */\nconst insertHidesBlurView = (\n parent: LynxElement,\n child: LynxElement,\n): boolean =>\n !__WEB__ &&\n child.tagName === 'blur-view' &&\n parent.tagName !== 'blur-view' &&\n isIOS();\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 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 #activeAnimations: LynxAnimation[] = [];\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 /**\n * ViewEncapsulation.Emulated's scope classes (see EmulatedLynxRenderer).\n * Angular writes static and bound classes as one whole class string through\n * setAttribute('class'), which would drop them, so they're added back each\n * time.\n */\n #scopeClasses: string[] = [];\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 /**\n * Inline declarations the runtime adds ahead of the app's own style=\"...\":\n * the CSS variables of a blur-view's material on Android (see\n * android-blur-material). Only `__SetInlineStyles` can set a CSS variable;\n * `__AddInlineStyle` drops any name that isn't a CSS property.\n */\n #runtimeStyle = '';\n /**\n * The CSS variables `[style.--x]` bindings set, which go into the inline\n * style string after the app's style=\"...\", for the same reason as\n * #runtimeStyle.\n */\n #customProperties = new Map<string, string>();\n /**\n * The app's own `accessibility-traits`, and the traits the runtime adds to\n * them (see setAccessibilityTrait). They're kept apart so that the app\n * setting its traits keeps the runtime's, and the runtime taking one away\n * restores the app's.\n */\n #ownTraits: unknown = null;\n #addedTraits: string[] = [];\n /** Every listener Angular added, in the order it added them. */\n #listeners: Listener[] = [];\n /** Recognizes long presses on Lynx for Web (see #listenForWebLongPress). */\n #webLongPress: WebLongPress | null = null;\n /**\n * The handler registered natively for each event (see nativeEventKey). It\n * runs every listener for that event, since native Lynx keeps only one.\n */\n #nativeHandlers = new Map<\n string,\n {\n eventType: LynxEventType;\n eventName: string;\n dispatch: (event: any) => unknown;\n }\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 * Elements with attributes removed this cycle, which reach Lynx only when\n * the cycle flushes (see #removedAttributes).\n */\n static #pendingAttributeRemovals = new Set<LynxElement>();\n\n /**\n * The attributes removed (set to null) since the last flush, which haven't\n * reached Lynx yet. Lynx queues a removal apart from the values set in the\n * same flush and applies it after them (`Element::SetAttribute` puts an\n * empty value in `reset_attr_vec_`, and `ConsumeAllAttributes` resets those\n * after setting `updated_attr_map_`), so an attribute removed and then set\n * again before a flush stayed removed on native. A glass button that a\n * sheet pairs with its glass in the same change detection as the button's\n * first render, for one, kept no `glass-effect-id`. So a removal waits here\n * for the flush, and a value set meanwhile takes it back.\n */\n readonly #removedAttributes = new Set<string>();\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 const classes = [\n ...new Set([\n ...String(value ?? '')\n .split(/\\s+/)\n .filter(Boolean),\n ...this.#scopeClasses,\n ]),\n ].join(' ');\n __SetClasses(this.element, classes);\n this.#classes = classes;\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 // A stroke-dasharray the engine can't parse hangs Lynx's native SVG engine and\n // blanks every <svg> in the app (see svg-content.ts), so it's rewritten\n // before it leaves JS. The cleaned value is also what's mirrored below,\n // so a recreated element gets it too.\n if (\n this.tagName === 'svg' &&\n name === 'content' &&\n typeof value === 'string'\n ) {\n value = sanitizeSvgContent(value);\n }\n if (name === 'accessibility-traits') {\n this.#ownTraits = value ?? null;\n value = withAddedTraits(this.#ownTraits, this.#addedTraits);\n }\n if (value == null) {\n // At the flush, unless it's set again first: see #removedAttributes.\n this.#removedAttributes.add(name);\n LynxElement.#pendingAttributeRemovals.add(this);\n scheduleSettleFlush();\n } else {\n this.#removedAttributes.delete(name);\n __SetAttribute(this.element, name, value);\n }\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 if (this.tagName === 'blur-view' && BLUR_MATERIAL_ATTRIBUTES.has(name)) {\n this.updateBlurMaterial();\n }\n }\n }\n\n /**\n * On Android, gives a blur-view the CSS variables that approximate its iOS\n * material (see android-blur-material). LynxDocument calls it when it\n * creates one, and setAttribute whenever an attribute it depends on changes.\n */\n updateBlurMaterial(): void {\n if (usesAndroidBlurMaterials()) {\n this.#setRuntimeStyle(androidBlurMaterialStyle(this.#attrs));\n }\n }\n\n /**\n * Adds `trait` to the app's own `accessibility-traits`, or takes it away.\n * The app can still set its traits at any time: setAttribute merges the two\n * (see withAddedTraits), so neither undoes the other.\n */\n setAccessibilityTrait(trait: string, on: boolean): void {\n if (this.#addedTraits.includes(trait) === on) return;\n this.#addedTraits = on\n ? [...this.#addedTraits, trait]\n : this.#addedTraits.filter((added) => added !== trait);\n this.setAttribute('accessibility-traits', this.#ownTraits);\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 if (isCustomProperty(key)) {\n // Angular removes a binding's style with an empty or null value too.\n if (value == null || value === '') {\n this.removeStyle(key);\n return;\n }\n const text = String(value);\n if (this.#customProperties.get(key) === text) return;\n this.#customProperties.set(key, text);\n this.#rewriteInlineStyle();\n return;\n }\n __AddInlineStyle(this.element, key, value);\n this.#inlineStyleKeys.set(key, value);\n }\n removeStyle(key: string): void {\n if (isCustomProperty(key)) {\n if (this.#customProperties.delete(key)) this.#rewriteInlineStyle();\n return;\n }\n __AddInlineStyle(this.element, key, null);\n this.#inlineStyleKeys.delete(key);\n }\n setInlineStyles(inlineStyle: string): void {\n __SetInlineStyles(this.element, this.#withRuntimeStyle(inlineStyle));\n this.#inlineStyleWhole = inlineStyle;\n }\n\n /**\n * The whole inline style to give the native element: the runtime's\n * declarations first, so the app's own wins where both set the same name,\n * then the app's style=\"...\", then its `[style.--x]` variables, which win\n * over the attribute as bindings do on the web. Without runtime\n * declarations or variables it's the app's value as is.\n */\n #withRuntimeStyle(inlineStyle: string | null): string | null {\n if (!this.#runtimeStyle && this.#customProperties.size === 0) {\n return inlineStyle;\n }\n const variables = [...this.#customProperties]\n .map(([name, value]) => `${name}: ${value}`)\n .join('; ');\n return [this.#runtimeStyle, inlineStyle?.replace(/[\\s;]+$/, ''), variables]\n .filter(Boolean)\n .join('; ');\n }\n\n #setRuntimeStyle(style: string): void {\n if (style === this.#runtimeStyle) return;\n this.#runtimeStyle = style;\n this.#rewriteInlineStyle();\n }\n\n /**\n * Gives the native element its whole inline style again.\n */\n #rewriteInlineStyle(): void {\n __SetInlineStyles(\n this.element,\n this.#withRuntimeStyle(this.#inlineStyleWhole),\n );\n // __SetInlineStyles replaces every inline style, including the [style.x]\n // ones __AddInlineStyle set, which the app didn't ask to drop.\n for (const [key, value] of this.#inlineStyleKeys) {\n __AddInlineStyle(this.element, key, value);\n }\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 newChild.#removeIfMoveWouldBeLost(this);\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 if (insertHidesBlurView(this, newChild)) {\n this.#appendBefore(newChild, refChild);\n } else {\n __InsertElementBefore(this.element, newChild.element, refChild.element);\n }\n this.#adoptChild(newChild, refChild);\n if (isTextish(this) || isTextish(newChild)) {\n LynxElement.#enqueueTextNormalization(newChild);\n }\n }\n }\n\n /**\n * Puts `newChild` before `refChild` by appending it, then moving `refChild`\n * and every native sibling after it to the end behind it, in order: the\n * same order as `__InsertElementBefore`, reached only by appends (see\n * insertHidesBlurView). The moves are in the same flush as the insert, so\n * the siblings keep their painting nodes, as any Angular move does.\n */\n #appendBefore(newChild: LynxElement, refChild: LynxElement): void {\n const childId = __GetElementUniqueID(newChild.element);\n const following: ElementRef[] = [];\n for (\n let sibling: ElementRef | null = refChild.element;\n sibling;\n sibling = __NextElement(sibling)\n ) {\n if (__GetElementUniqueID(sibling) !== childId) following.push(sibling);\n }\n __AppendElement(this.element, newChild.element);\n for (const sibling of following) {\n __AppendElement(this.element, sibling);\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.#removeIfMoveWouldBeLost(this);\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 addScopeClass(name: string): void {\n if (this.#scopeClasses.includes(name)) return;\n this.#scopeClasses.push(name);\n this.addClass(name);\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 /**\n * Sends Lynx the attribute removals that weren't taken back this cycle\n * (see #removedAttributes). Called by `LynxRendererFactory2.end()` and the\n * settle flush, after removals and before `__FlushElementTree()`, so the\n * removals land in the same flush as the cycle's other mutations.\n */\n static commitPendingAttributeRemovals(): void {\n if (LynxElement.#pendingAttributeRemovals.size === 0) return;\n const elements = [...LynxElement.#pendingAttributeRemovals];\n LynxElement.#pendingAttributeRemovals.clear();\n for (const el of elements) {\n for (const name of el.#removedAttributes) {\n __SetAttribute(el.element, name, null);\n }\n el.#removedAttributes.clear();\n }\n }\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 * Before this element moves under `newParent`: removes it for good if Lynx\n * would lose the move, so the insert that follows rebuilds it (see\n * #recreateIfDead) instead.\n *\n * Native Lynx (4.1) loses a move to another parent when the flush reaches\n * the new parent first. `__AppendElement` and `__InsertElementBefore` queue\n * the removal on the old parent and the insertion on the new one, and the\n * flush handles each parent's queue in tree order (see flushesBefore). When\n * the insertion runs first, the element is still in its old parent's\n * layout; the removal then finds a different parent and does nothing\n * (`HandleRemoveChildAction` in `fiber_element.cc`). The element ends up in\n * neither: the new parent lays out empty and the element sits unattached\n * at the top-left of the screen. Moving out of an `<overlay>` back to the\n * page it came from, which follows the page in the tree, always hit this\n * (CDK's DomPortal and the context menu's lifted element do it). Lynx's\n * develop branch fixes it (`FixFiberReinsertDetachFromOldRenderParent`),\n * after 4.1.\n *\n * A removal and a rebuild in the same flush don't depend on the order:\n * the old element leaves its parent, and a fresh one with the same state\n * goes into the new one. Moves the flush does handle in order (the old\n * parent first, or the same parent, as for an `@for` reorder) stay native\n * moves. Lynx for Web moves DOM nodes and doesn't have the problem.\n */\n #removeIfMoveWouldBeLost(newParent: LynxElement): void {\n if (__WEB__ || this.#paintingDead || this._virtualParent) return;\n const oldParent = __GetParent(this.element);\n if (\n !oldParent ||\n __GetElementUniqueID(oldParent) ===\n __GetElementUniqueID(newParent.element)\n ) {\n return;\n }\n if (flushesBefore(newParent.element, oldParent)) this.#doRemove();\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 // Each animation cancels itself, because only it knows the key it was\n // started under (its id, or a name it was given; see LynxAnimation).\n // Canceling a completed animation is harmless — a no-op at the native level.\n for (const anim of this.#activeAnimations) {\n anim.cancel();\n }\n if (this.#activeAnimations.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.#activeAnimations.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 const inlineStyle = this.#withRuntimeStyle(this.#inlineStyleWhole);\n if (inlineStyle != null) {\n __SetInlineStyles(fresh, inlineStyle);\n }\n for (const [key, value] of this.#inlineStyleKeys) {\n __AddInlineStyle(fresh, key, value);\n }\n for (const {\n eventType,\n eventName,\n dispatch,\n } of this.#nativeHandlers.values()) {\n __AddEvent(fresh, eventType, eventName, {\n type: 'worklet',\n value: dispatch,\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.#activeAnimations.push(anim);\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. A DOM name Lynx calls\n * something else (see DOM_EVENT_ALIASES) listens for the Lynx event, so\n * `(click)`, and Angular's RouterLink with it, runs on a tap.\n * Other names (e.g. `mouseover`) are ignored: Lynx has no event for them.\n *\n * An element can have any number of listeners for one event, as on the\n * web: a template's `(bindtap)` next to a directive's host listener for\n * `click`, say. Native Lynx keeps one handler per event name, so each name\n * gets one native handler that runs all of them (see #syncNativeHandler).\n */\n addEventListener(name: string, cb: (event: any) => any) {\n const parsed = parseEventName(name);\n if (!parsed) {\n return () => {};\n }\n\n if (__WEB__ && parsed.eventName === 'longpress') {\n this.#listenForWebLongPress();\n }\n\n // Kept so #recreateSubtree() can register the handlers again on a rebuilt\n // native ref: native events don't survive a painting-node teardown and\n // 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: Listener = { ...parsed, listener: cb };\n this.#listeners.push(entry);\n this.#syncNativeHandler(entry);\n\n return () => this.#removeListener(entry);\n }\n\n /**\n * Removes a listener added with addEventListener, as the DOM method does,\n * for code that pairs the two on the element itself rather than going\n * through the renderer's cleanup function. Angular's `@defer` interaction\n * and hover triggers do, for their `click`, `keydown` and `mouseenter`\n * listeners; without it, their cleanup would throw. A name Lynx has no\n * event for was never added, so removing it does nothing.\n */\n removeEventListener(name: string, cb: (event: any) => any): void {\n const parsed = parseEventName(name);\n if (!parsed) return;\n const entry = this.#listeners.find(\n (other) =>\n other.listener === cb &&\n other.eventType === parsed.eventType &&\n other.eventName === parsed.eventName,\n );\n if (entry) this.#removeListener(entry);\n }\n\n /**\n * On Lynx for Web, which never fires `longpress` (see web-long-press.ts),\n * recognizes long presses from this element's touch and mouse events and\n * runs its `longpress` listeners, as native Lynx would. Once per element:\n * the listeners it adds stay, and do nothing once no `longpress` listener\n * is left.\n */\n #listenForWebLongPress(): void {\n if (this.#webLongPress) return;\n const press = new WebLongPress((detail) => {\n const entry = this.#listeners.find(\n (listener) => listener.eventName === 'longpress',\n );\n if (entry) this.#dispatch(entry, { type: 'longpress', detail });\n });\n this.#webLongPress = press;\n this.addEventListener('bindtouchstart', press.start);\n this.addEventListener('bindmousedown', press.start);\n this.addEventListener('bindtouchmove', press.move);\n this.addEventListener('bindmousemove', press.move);\n for (const end of ['touchend', 'touchcancel', 'mouseup', 'mouseleave']) {\n this.addEventListener(`bind${end}`, press.end);\n }\n }\n\n #removeListener(entry: Listener): void {\n const i = this.#listeners.indexOf(entry);\n // Removing a listener a second time does nothing, as on the DOM.\n if (i < 0) return;\n this.#listeners.splice(i, 1);\n this.#syncNativeHandler(entry);\n }\n\n /**\n * The listeners that share `entry`'s native handler, in the order added.\n */\n #listenersLike(entry: Listener): Listener[] {\n const key = nativeEventKey(entry.eventType, entry.eventName);\n return this.#listeners.filter(\n (other) => nativeEventKey(other.eventType, other.eventName) === key,\n );\n }\n\n /**\n * Brings the native handler for `entry`'s event in line with its listeners:\n * registers it for the first one, changes its type when a listener needs\n * another (see combinedEventType), and removes it after the last one.\n */\n #syncNativeHandler(entry: Listener): void {\n const key = nativeEventKey(entry.eventType, entry.eventName);\n const listeners = this.#listenersLike(entry);\n const current = this.#nativeHandlers.get(key);\n const eventType = listeners.length ? combinedEventType(listeners) : null;\n if (current?.eventType === eventType) return;\n if (current) {\n // Passing undefined as the listener tells the Lynx SDK to remove the\n // handler for this type+name combination.\n __AddEvent(this.element, current.eventType, entry.eventName, undefined);\n this.#nativeHandlers.delete(key);\n }\n if (!eventType) return;\n const handler = {\n eventType,\n eventName: entry.eventName,\n // The same dispatcher across a type change: it looks the listeners up\n // when the event fires, so it never needs registering again for them.\n dispatch:\n current?.dispatch ?? ((event: any) => this.#dispatch(entry, event)),\n };\n this.#nativeHandlers.set(key, handler);\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, entry.eventName, {\n type: 'worklet',\n value: handler.dispatch,\n });\n }\n\n /**\n * Runs every listener for the event `entry` belongs to.\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 the listeners (Angular's wrapper may call\n * preventDefault() during that call) and return the last one's result (the\n * return-false path relies on it). Mirrors React Lynx's\n * addEventMethodsIfNeeded.\n */\n #dispatch(entry: Listener, event: any): unknown {\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 // The browser's click after a long press on Lynx for Web, which native\n // Lynx doesn't follow with a tap (see web-long-press.ts).\n if (__WEB__ && entry.eventName === 'tap' && dropsTap()) return undefined;\n let result: unknown;\n // As a DOM event does: the listeners are those registered when the event\n // fires, so one that removes itself doesn't make the next one skip, and a\n // listener an earlier one removed (an @if hiding part of the element, say)\n // doesn't run.\n for (const other of this.#listenersLike(entry)) {\n if (this.#listeners.includes(other)) result = other.listener(event);\n }\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\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 * Commits this cycle's attribute removals (see LynxElement's\n * `#removedAttributes`). A free-function wrapper over\n * `LynxElement.commitPendingAttributeRemovals()` so\n * `LynxRendererFactory2.end()` can drain them (via the lynx-element barrel)\n * right after element removals and before `__FlushElementTree()`.\n */\nexport const processPendingAttributeRemovals = (): void => {\n LynxElement.commitPendingAttributeRemovals();\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 run on the main\n * thread (Angular doesn't run on the background thread), so no thread guard is\n * 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.commitPendingAttributeRemovals();\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 { 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 * * lynx-stack/packages/react/runtime/src/snapshot/list/list.ts,\n * * componentAtChildCtx's `!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 { ANDROID_BLUR_CAPTURE_TARGET, isAndroid } from './android-blur-capture';\nimport {\n __pageElementRef,\n setPageElementRef,\n takePageHandOver,\n} from './page-ref';\n\nimport { createNativeRefByTag } from './create-native-ref';\nimport {\n createCommentElement,\n createListElement,\n createPageElement,\n} from './element-creators';\nimport type { ElementRef } from '../types/lynx';\nimport type { LynxDocumentBase } from './types';\n\n/**\n * The page a previous app rendered into, emptied, when a hot update\n * bootstraps the app again (see `handOverPageToNextApp`). A Lynx page has one\n * page element, and the engine shows the first one created: a second\n * `__CreatePage()` gives the new app a page that's never shown, while the old\n * app's elements, whose views are gone, stay on screen. Angular's\n * `ApplicationRef.destroy()` doesn't remove a root component's elements (in a\n * browser they also stay in the page), so they're removed here.\n *\n * @returns The page element, or `null` when no re-bootstrap handed one over.\n */\nconst takeOverPage = (): ElementRef | null => {\n const page = __pageElementRef;\n if (!takePageHandOver() || !page) return null;\n for (const child of __GetChildren(page) ?? []) {\n __RemoveElement(page, child);\n }\n return page;\n};\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 = takeOverPage() ?? __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 if (isAndroid()) {\n // What every blur-view blurs on Android (see create-blur-view-element).\n __SetID(pageElement, ANDROID_BLUR_CAPTURE_TARGET);\n }\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 // Before any attribute is set: a blur-view with no attributes must still\n // set its (empty) material, or it inherits a parent blur-view's.\n if (tag === 'blur-view') {\n el.updateBlurMaterial();\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 type { BaseLynxElement } from '../lynx-element';\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 marks elements so the component's scoped CSS\n * matches only them.\n *\n * On the web, Angular's EmulatedEncapsulationDomRenderer2 gives every element\n * the component creates a `_ngcontent-<id>` attribute, and each host element a\n * `_nghost-<id>` attribute, and the compiler scopes the component's selectors\n * with them. Lynx's CSS engine can't match attribute selectors, so the build\n * plugin turns them into class selectors (toLynxScopedCss in the plugin's\n * component-styles.ts), and this renderer adds classes instead. The plugin\n * sets ɵcmp.id, which is `id` here, to the scope ID the CSS was compiled with.\n */\nexport class EmulatedLynxRenderer extends LynxRenderer {\n readonly #contentClass: string;\n readonly #hostClass: string;\n\n constructor(document: LynxDocumentBase, componentId: string) {\n super(document);\n this.#contentClass = `_ngcontent-${componentId}`;\n this.#hostClass = `_nghost-${componentId}`;\n }\n\n /**\n * Marks a host element of this component type, for `:host` selectors.\n * LynxRendererFactory2 calls it for each component instance, as Angular's\n * DomRendererFactory2 does.\n */\n applyToHost(element: BaseLynxElement): void {\n element.addScopeClass(this.#hostClass);\n }\n\n override createElement(\n name: string,\n namespace?: string | null,\n ): BaseLynxElement {\n const element = super.createElement(name, namespace);\n element.addScopeClass(this.#contentClass);\n return element;\n }\n\n override selectRootElement() {\n const el = super.selectRootElement();\n this.applyToHost(el);\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, endCdTiming, startCdTiming } from '../devtools/stats';\nimport type { LynxDocumentBase } from '../lynx-document';\nimport {\n processPendingAttributeRemovals,\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.Emulated) {\n // ShadowDom (and Angular's experimental isolated variant) needs a shadow\n // root, which Lynx elements don't have. Their styles compile unscoped,\n // so they apply app-wide, as with None.\n if (type && type.encapsulation !== ViewEncapsulation.None) {\n console.warn(\n 'ViewEncapsulation.ShadowDom is not supported in Lynx. Falling back to no encapsulation.',\n );\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 // Angular calls createRenderer for each component instance, with its host\n // element. The bootstrap root has none here; selectRootElement marks it.\n if (hostElement) {\n renderer.applyToHost(hostElement);\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 // Build-time `define` gate — false in the Vitest config, so this\n // profiling call is dead code from the test bundle's point of view.\n /* v8 ignore start */\n if (__PROFILE__) {\n startCdTiming();\n }\n /* v8 ignore stop */\n }\n /**\n * Called by Angular after every change detection cycle completes.\n * 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\"). The cycle's attribute removals follow, for the same\n * flush (see processPendingAttributeRemovals).\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 * In development builds, the cycle's duration, timed from begin(), is\n * recorded on every return path, the flush included: it's how long the\n * cycle kept the main thread busy.\n */\n end?(): void {\n try {\n // This change-detection cycle is finishing: clear the flag first, on\n // EVERY return path, so mutations after this point are correctly seen\n // as outside-a-cycle (see begin() / scheduleSettleFlush). The flush\n // below is unconditional, so clearing the flag now does not affect it.\n setInsideChangeDetection(false);\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).\n // Drained even while the first-render flush is skipped: the\n // __RemoveElement calls mutate native elements directly, and native\n // performs its own flush once renderPage returns.\n processPendingRemovals();\n // Then the attributes removed this cycle and not set again: Lynx would\n // apply a removal after a value set in the same flush (see\n // LynxElement's #removedAttributes), so they wait until now.\n processPendingAttributeRemovals();\n // Re-derive positional edge whitespace for texts mutated this cycle,\n // after removals (so torn-down subtrees are skipped) and before the\n // flush (so the corrected text is painted in the same pass). Runs even\n // while the first render's explicit flush is skipped: it only mutates\n // native `text` attributes directly, which native commits in its own\n // post-renderPage flush — same rationale as processPendingRemovals\n // above.\n processPendingTextNormalization();\n if (!isFirstRenderPending()) {\n __FlushElementTree();\n }\n processPendingListUpdates();\n } finally {\n // In `finally` so a cycle that returns early or throws still ends its\n // timing: the start times nest, so a missed end would pair every later\n // cycle's end with the wrong start. Gated like the counters above.\n /* v8 ignore start */\n if (__PROFILE__) {\n endCdTiming();\n }\n /* v8 ignore stop */\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 { 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. The document (LynxDocument, or LynxHydrateDocument for SSR)\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 // Angular runs on the main thread only (see bootstrapApplication), so\n // the document always creates native elements: through PAPI, or by\n // reusing the snapshot's while SSR hydrates.\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 },\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 bites the *web* runtime: ImagePerformanceWarning.start() early-\n // returns when `PerformanceObserver` is undefined, which is the case in\n // native Lynx's JS engines. On web, Lynx runs JavaScript in a browser realm\n // (first the background thread's Web Worker, now the main thread's iframe),\n // which *does* have PerformanceObserver, so it proceeded to getDocument()\n // 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, type Injector, signal } from '@angular/core';\n\ntype HistoryEntry = { state: unknown; url: string };\n\n/**\n * The history a hot update's re-bootstrap hands from the old app's strategy to\n * the new one's (see {@link carryOverLocation}). It lives at module level\n * because the runtime's module isn't re-run by a hot update, while the app's\n * injectors, and the strategy in them, are.\n */\nlet carriedOver: HistorySnapshot | undefined;\n\ntype HistorySnapshot = { history: HistoryEntry[]; index: number };\n\n/**\n * Reads a strategy's history. Assigned in the class's static block, the only\n * place outside its methods that can reach its private fields, which keeps the\n * snapshot out of the class's public API.\n */\nlet snapshotOf: (strategy: LynxLocationStrategy) => HistorySnapshot;\n\n/**\n * Keeps the app on the screen it was showing when a hot update re-bootstraps\n * it. Called with the old app's injector before it's destroyed, it saves the\n * old strategy's history, and the next strategy created starts from it. The\n * router's initial navigation then goes to the current URL instead of `/`,\n * and Back still has the screens before it.\n *\n * Does nothing for an app without the router, or with another strategy.\n *\n * @param injector - The injector of the app that's about to be destroyed.\n */\nexport const carryOverLocation = (injector: Injector | undefined): void => {\n const strategy = injector?.get(LocationStrategy, null);\n if (strategy instanceof LynxLocationStrategy) {\n carriedOver = snapshotOf(strategy);\n }\n};\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: HistoryEntry[] = [{ state: null, url: '/' }];\n #historyIndex = 0;\n #listeners: LocationChangeListener[] = [];\n readonly #canGoBack = signal(false);\n\n constructor() {\n super();\n if (carriedOver) {\n this.#history = carriedOver.history;\n this.#historyIndex = carriedOver.index;\n this.#path = this.#history[this.#historyIndex].url;\n this.#canGoBack.set(this.#historyIndex > 0);\n carriedOver = undefined;\n }\n }\n\n static {\n snapshotOf = (strategy) => ({\n history: strategy.#history.map((entry) => ({ ...entry })),\n index: strategy.#historyIndex,\n });\n }\n\n /**\n * Whether there's an entry before the current one, so `back()` goes\n * somewhere. The Android back button follows it (see lynx-back-button.ts):\n * while it's false, back leaves the app, as on any root screen.\n */\n readonly canGoBack = this.#canGoBack.asReadonly();\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.#canGoBack.set(true);\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.#canGoBack.set(target > 0);\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 * Opt-in: `provideRouter()` doesn't install it, so leaving a route destroys\n * its components, as Angular does on the web. Provide it yourself to keep\n * every visited route's component, and its state, alive:\n *\n * ```typescript\n * providers: [\n * provideRouter(routes),\n * { provide: RouteReuseStrategy, useClass: LynxRouteReuseStrategy },\n * ]\n * ```\n *\n * Nothing is ever evicted, and `ngOnDestroy()` doesn't run when you leave a\n * route.\n *\n * ## Why it exists\n *\n * `provideRouter()` used to install it. A crash investigation in May 2026\n * blamed a ~256-slot native element pool that `__RemoveElement` never freed,\n * and detaching views was meant to reuse their elements. Neither holds on\n * Lynx 4.1 (measured October 2026 on the iOS Simulator and an Android\n * emulator, issue #68): 400 navigations between two 300-element routes\n * created 121,527 native elements without a crash, with this strategy and\n * with Angular's default alike. A re-attached view's native elements were\n * destroyed when it was detached, so `LynxElement` rebuilds them from cache\n * (`#recreateSubtree`), and a revisit creates as many elements as a fresh\n * route.\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, so the component and its state live on.\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 { Location, LocationStrategy } from '@angular/common';\nimport { effect, inject, Injectable } from '@angular/core';\nimport { LynxNativeModule } from '../native-module/native-module';\nimport { LynxLocationStrategy } from './lynx-location-strategy';\n\n/**\n * The native module and global event of the Android app that\n * `ng build --platform android` makes (`ShellModule.kt` in\n * `packages/native/templates/android`).\n */\nconst SHELL_MODULE = 'AngularLynxShell';\nconst BACK_EVENT = 'angularLynxBack';\n\ntype ShellModule = {\n setBackHandlerEnabled(enabled: boolean): unknown;\n};\n\ntype GlobalEventEmitter = {\n addListener(name: string, listener: () => void): unknown;\n};\n\n/**\n * Connects the Android back button to the router, so that it goes back a\n * screen, as the browser's back button does in a web app, and leaves the app\n * from the first one.\n *\n * Android decides whether an app handles back when the gesture starts, before\n * JavaScript could answer, so the shell can't ask the app each time. Instead\n * back is Android's (it leaves the app) until the app enables the shell's\n * handler, and while it's enabled each press arrives as the `angularLynxBack`\n * global event. This keeps the handler enabled while the router has a screen to\n * go back to, and turns each press into `Location.back()`. The router then\n * navigates as for the browser's back button, running guards and resolvers.\n *\n * Other hosts (the iOS app, Lynx Explorer, the web preview) have no\n * `AngularLynxShell` module and never send the event, so this does nothing\n * there. An app with its own `LocationStrategy` keeps Android's back, because\n * only `LynxLocationStrategy` says whether there's somewhere to go back to.\n *\n * Created by `provideRouter()`.\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxBackButton {\n constructor() {\n const strategy = inject(LocationStrategy);\n if (!(strategy instanceof LynxLocationStrategy)) return;\n const location = inject(Location);\n const modules = inject(LynxNativeModule);\n\n // On the main thread, where Angular runs, both are proxies whose calls go\n // through the background thread and return promises. A host without the\n // module rejects the call, and then never gets another.\n const shell = modules.getNativeModule(SHELL_MODULE) as\n | ShellModule\n | undefined;\n let hasShell = true;\n effect(() => {\n const enabled = strategy.canGoBack();\n if (!hasShell) return;\n Promise.resolve()\n .then(() => shell?.setBackHandlerEnabled(enabled))\n .catch(() => (hasShell = false));\n });\n\n const emitter =\n modules.getJSModule<GlobalEventEmitter>('GlobalEventEmitter');\n Promise.resolve()\n .then(() => emitter?.addListener(BACK_EVENT, () => location.back()))\n .catch(() => {\n // Without a background thread there are no global events to hear.\n });\n }\n}\n","import { LocationStrategy, PlatformLocation } from '@angular/common';\nimport {\n type EnvironmentProviders,\n inject,\n makeEnvironmentProviders,\n provideEnvironmentInitializer,\n} from '@angular/core';\nimport {\n provideRouter as ngProvideRouter,\n RouterLinkActive,\n type RouterFeatures,\n type Routes,\n withRouterConfig,\n} from '@angular/router';\nimport { LynxBackButton } from './lynx-back-button';\nimport { LynxLocationStrategy } from './lynx-location-strategy';\nimport { LynxPlatformLocation } from './lynx-platform-location';\nimport { ROUTER_LINK_ACTIVE_CHANGE } from './lynx-router-link-active';\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 // No RouteReuseStrategy: leaving a route destroys it, as Angular does on\n // the web. This used to install LynxRouteReuseStrategy against a supposed\n // ~256-slot native element pool. Measured on Lynx 4.1 (iOS and Android,\n // October 2026), there's no such limit, and the strategy saved no\n // elements anyway: a re-attached route rebuilds them (#recreateSubtree in\n // lynx-element.ts). See lynx-route-reuse-strategy.ts.\n ngProvideRouter(\n routes,\n // Unhandled navigation promise rejections (e.g. from unmatched routes or\n // lazy chunk loading failures) left a blank 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 // The Android back button goes back through this router's history, like\n // the browser's back button on the web (see lynx-back-button.ts).\n provideEnvironmentInitializer(() => inject(LynxBackButton)),\n // Lets LYNX_ELEMENTS mark an active routerLinkActive element `selected`\n // for screen readers without importing the router itself (see\n // lynx-router-link-active.ts). Taps reach Angular's own RouterLink without\n // help: the renderer delivers a tap to its `click` listener.\n {\n provide: ROUTER_LINK_ACTIVE_CHANGE,\n useValue: () =>\n inject(RouterLinkActive, { self: true, optional: true })\n ?.isActiveChange ?? null,\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 * Legacy error codes of the DOMException names code here can raise, which\n * older code still checks (`error.code === 20` for an abort).\n */\nconst CODES: Record<string, number> = {\n NotSupportedError: 9,\n InvalidStateError: 11,\n SyntaxError: 12,\n InvalidAccessError: 15,\n NetworkError: 19,\n AbortError: 20,\n TimeoutError: 23,\n};\n\n/**\n * `DOMException` for Lynx's main thread, which has none. Angular's HTTP\n * backends create one when a request times out\n * (`new DOMException('signal timed out', 'TimeoutError')`); without the\n * global, that line threw a ReferenceError in a timer instead of failing the\n * request.\n */\nexport class LynxDOMException extends Error {\n readonly code: number;\n\n constructor(message = '', name = 'Error') {\n super(message);\n this.name = name;\n this.code = CODES[name] ?? 0;\n }\n}\n","/**\n * The Fetch Standard's `Headers` for Lynx's main thread, which has no Fetch\n * API. Angular's `FetchBackend` reads a response's headers through it\n * (`response.headers.get('content-type')`, and `new HttpHeaders(headers)`,\n * which iterates anything that is `instanceof Headers`).\n */\n\nexport type HeadersInit =\n | LynxHeaders\n | Iterable<readonly [string, string]>\n | Record<string, string>;\n\n/** RFC 9110's `token`: the characters a header name may use. */\nconst NAME = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\n\nconst normalizeValue = (value: unknown): string => {\n // Leading and trailing HTTP whitespace is dropped, as browsers do.\n const normalized = String(value).replace(/^[\\t\\n\\r ]+|[\\t\\n\\r ]+$/g, '');\n if (/[\\r\\n]/.test(normalized) || normalized.includes('\\0')) {\n throw new TypeError(`Invalid header value: ${JSON.stringify(value)}`);\n }\n return normalized;\n};\n\nconst normalizeName = (name: unknown): string => {\n const normalized = String(name);\n if (!NAME.test(normalized)) {\n throw new TypeError(`Invalid header name: ${JSON.stringify(name)}`);\n }\n return normalized.toLowerCase();\n};\n\nexport class LynxHeaders {\n /** Each header in the order it was added, with its name lowercased. */\n #list: [name: string, value: string][] = [];\n\n constructor(init?: HeadersInit | null) {\n if (init == null) return;\n if (init instanceof LynxHeaders) {\n this.#list = init.#list.map(([name, value]) => [name, value]);\n } else if (typeof (init as any)[Symbol.iterator] === 'function') {\n for (const pair of init as Iterable<readonly string[]>) {\n if (pair.length !== 2) {\n throw new TypeError(\n \"Failed to construct 'Headers': Invalid value: each header must be a [name, value] pair\",\n );\n }\n this.append(pair[0] as string, pair[1] as string);\n }\n } else {\n for (const name of Object.keys(init)) {\n this.append(name, (init as Record<string, string>)[name] as string);\n }\n }\n }\n\n append(name: string, value: string): void {\n this.#list.push([normalizeName(name), normalizeValue(value)]);\n }\n\n delete(name: string): void {\n const key = normalizeName(name);\n this.#list = this.#list.filter(([listed]) => listed !== key);\n }\n\n /**\n * The header's values joined with \", \", or null if it isn't set.\n */\n get(name: string): string | null {\n const key = normalizeName(name);\n const values = this.#list\n .filter(([listed]) => listed === key)\n .map(([, value]) => value);\n return values.length > 0 ? values.join(', ') : null;\n }\n\n /**\n * Each `Set-Cookie` value: the one header that can't be joined.\n */\n getSetCookie(): string[] {\n return this.#list\n .filter(([name]) => name === 'set-cookie')\n .map(([, value]) => value);\n }\n\n has(name: string): boolean {\n const key = normalizeName(name);\n return this.#list.some(([listed]) => listed === key);\n }\n\n set(name: string, value: string): void {\n const key = normalizeName(name);\n const index = this.#list.findIndex(([listed]) => listed === key);\n if (index === -1) {\n this.append(key, value);\n return;\n }\n // The first entry keeps its place and takes the value; the rest go.\n this.#list[index] = [key, normalizeValue(value)];\n this.#list = this.#list.filter(\n ([listed], i) => listed !== key || i === index,\n );\n }\n\n forEach(\n callback: (value: string, name: string, parent: LynxHeaders) => void,\n thisArg?: unknown,\n ): void {\n for (const [name, value] of this.entries()) {\n callback.call(thisArg, value, name, this);\n }\n }\n\n /**\n * The headers sorted by name, with each name's values joined, except\n * `Set-Cookie`, which is listed once per value, as the standard says.\n */\n *entries(): IterableIterator<[string, string]> {\n const names = [...new Set(this.#list.map(([name]) => name))].sort();\n for (const name of names) {\n if (name === 'set-cookie') {\n for (const value of this.getSetCookie()) yield [name, value];\n } else {\n yield [name, this.get(name) as string];\n }\n }\n }\n\n *keys(): IterableIterator<string> {\n for (const [name] of this.entries()) yield name;\n }\n\n *values(): IterableIterator<string> {\n for (const [, value] of this.entries()) yield value;\n }\n\n [Symbol.iterator](): IterableIterator<[string, string]> {\n return this.entries();\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 { utf8Encode } from '../url/percent-encoding';\n\n/**\n * `TextEncoder` and `TextDecoder` for Lynx's main thread, which has neither\n * (PrimJS implements only the JavaScript language). Angular's `FetchBackend`\n * decodes every `json` and `text` response with `new TextDecoder()`, so\n * `HttpClient` can't read a response without one. UTF-8 only: the Encoding\n * Standard's other encodings aren't needed for that, and an unknown label\n * throws a RangeError, as browsers do, which `FetchBackend` catches and falls\n * back to UTF-8.\n *\n * Lynx's background thread has `TextCodecHelper` instead (see the Lynx\n * networking guide), which the main thread lacks too.\n */\n\nconst UTF8_LABELS = new Set([\n 'unicode-1-1-utf-8',\n 'unicode11utf8',\n 'unicode20utf8',\n 'utf-8',\n 'utf8',\n 'x-unicode20utf8',\n]);\n\nconst REPLACEMENT_CHARACTER = 0xfffd;\nconst BYTE_ORDER_MARK = 0xfeff;\n\n/** See SLICE in base64.ts. */\nconst SLICE = 8192;\n\ntype BufferSource = ArrayBuffer | ArrayBufferView;\n\nconst toBytes = (input: BufferSource | undefined): Uint8Array => {\n if (input === undefined) return new Uint8Array(0);\n if (ArrayBuffer.isView(input)) {\n return new Uint8Array(input.buffer, input.byteOffset, input.byteLength);\n }\n if (input instanceof ArrayBuffer) return new Uint8Array(input);\n throw new TypeError(\n \"Failed to execute 'decode' on 'TextDecoder': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'.\",\n );\n};\n\n/**\n * The length of the UTF-8 sequence a lead byte starts, or 1 if it's invalid.\n */\nconst sequenceLength = (lead: number): number => {\n if (lead >= 0xc2 && lead <= 0xdf) return 2;\n if (lead >= 0xe0 && lead <= 0xef) return 3;\n if (lead >= 0xf0 && lead <= 0xf4) return 4;\n return 1;\n};\n\n/**\n * How many of `bytes` can be decoded now: all but a multi-byte sequence cut\n * off at the end, which a streaming decode keeps for the next call.\n */\nconst completeLength = (bytes: ArrayLike<number>): number => {\n for (let back = 1; back <= 3 && back <= bytes.length; back++) {\n const byte = bytes[bytes.length - back] as number;\n if ((byte & 0xc0) !== 0x80) {\n return sequenceLength(byte) > back ? bytes.length - back : bytes.length;\n }\n }\n return bytes.length;\n};\n\nexport class LynxTextEncoder {\n readonly encoding = 'utf-8';\n\n encode(input = ''): Uint8Array {\n return new Uint8Array(utf8Encode(String(input)));\n }\n\n encodeInto(\n source: string,\n destination: Uint8Array,\n ): { read: number; written: number } {\n let read = 0;\n let written = 0;\n for (const char of String(source)) {\n const bytes = utf8Encode(char);\n if (written + bytes.length > destination.length) break;\n destination.set(bytes, written);\n written += bytes.length;\n read += char.length;\n }\n return { read, written };\n }\n}\n\nexport class LynxTextDecoder {\n readonly encoding = 'utf-8';\n readonly fatal: boolean;\n readonly ignoreBOM: boolean;\n /** Bytes of a sequence a streaming decode cut off, kept for the next call. */\n #pending: number[] = [];\n /** Whether this stream has produced output yet, so a BOM can only lead it. */\n #started = false;\n\n constructor(\n label = 'utf-8',\n options: { fatal?: boolean; ignoreBOM?: boolean } = {},\n ) {\n if (!UTF8_LABELS.has(String(label).trim().toLowerCase())) {\n throw new RangeError(\n `The encoding label provided ('${label}') is invalid or isn't supported on Lynx, which only decodes UTF-8.`,\n );\n }\n this.fatal = !!options.fatal;\n this.ignoreBOM = !!options.ignoreBOM;\n }\n\n decode(input?: BufferSource, options: { stream?: boolean } = {}): string {\n let bytes: ArrayLike<number> = toBytes(input);\n if (this.#pending.length > 0) {\n bytes = [...this.#pending, ...Array.from(bytes)];\n }\n const end = options.stream ? completeLength(bytes) : bytes.length;\n this.#pending = Array.from({ length: bytes.length - end }, (_, i) =>\n Number(bytes[end + i]),\n );\n let output = this.#decode(bytes, end);\n if (\n !this.ignoreBOM &&\n !this.#started &&\n output.charCodeAt(0) === BYTE_ORDER_MARK\n ) {\n output = output.slice(1);\n }\n this.#started = options.stream ? this.#started || output !== '' : false;\n return output;\n }\n\n /**\n * The Encoding Standard's UTF-8 decoder: an invalid sequence becomes one\n * U+FFFD, or a TypeError when `fatal`. Unlike the URL polyfill's\n * utf8Decode(), which only sees short URL parts, it builds the string in\n * slices, since a response body can be megabytes long.\n */\n #decode(bytes: ArrayLike<number>, end: number): string {\n let output = '';\n const codes: number[] = [];\n const invalid = () => {\n if (this.fatal) {\n throw new TypeError(\n \"Failed to execute 'decode' on 'TextDecoder': The encoded data was not valid.\",\n );\n }\n codes.push(REPLACEMENT_CHARACTER);\n };\n let index = 0;\n while (index < end) {\n const lead = bytes[index] as number;\n if (lead < 0x80) {\n codes.push(lead);\n index++;\n } else {\n const needed = sequenceLength(lead) - 1;\n // The first continuation byte's valid range narrows for some leads,\n // which rules out overlong encodings and surrogates.\n let lower = lead === 0xe0 ? 0xa0 : lead === 0xf0 ? 0x90 : 0x80;\n let upper = lead === 0xed ? 0x9f : lead === 0xf4 ? 0x8f : 0xbf;\n let codePoint = lead & (0xff >> (needed + 2));\n let seen = 0;\n while (seen < needed && index + 1 + seen < end) {\n const next = bytes[index + 1 + seen] as number;\n if (next < lower || next > upper) break;\n lower = 0x80;\n upper = 0xbf;\n codePoint = (codePoint << 6) | (next & 0x3f);\n seen++;\n }\n if (needed === 0 || seen < needed) {\n // The byte that broke the sequence starts the next one.\n invalid();\n index += 1 + seen;\n } else {\n if (codePoint > 0xffff) {\n codePoint -= 0x10000;\n codes.push(\n 0xd800 | (codePoint >> 10),\n 0xdc00 | (codePoint & 0x3ff),\n );\n } else {\n codes.push(codePoint);\n }\n index += 1 + needed;\n }\n }\n if (codes.length >= SLICE) {\n output += String.fromCharCode(...codes);\n codes.length = 0;\n }\n }\n return output + String.fromCharCode(...codes);\n }\n}\n","import { callOnBackground } from '../background-call';\nimport type {\n RelayedBody,\n RelayedRequest,\n RelayedResponse,\n} from './background-fetch';\nimport { base64ToBytes, bytesToBase64 } from './base64';\nimport { LynxHeaders, type HeadersInit } from './headers';\nimport { LynxTextDecoder, LynxTextEncoder } from './text-codec';\n\n/**\n * `fetch`, `Request` and `Response` for Lynx's main thread.\n *\n * Lynx has `fetch` on the background thread only, and Angular runs on the\n * main thread, so `HttpClient` (whose default backend, `FetchBackend`, calls\n * `globalThis.fetch`), `httpResource` and any library that calls `fetch`\n * failed there. This `fetch` sends each request to the background thread\n * through callOnBackground() and builds the `Response` from what comes back\n * (background-fetch.ts has the other half).\n *\n * The whole body arrives at once: Lynx's own `fetch` doesn't stream unless\n * the page sets `enableFetchAPIStandardStreaming`, and the relay carries one\n * message per call. So `response.body` yields one chunk, and a download\n * reports its progress once, when it's done.\n *\n * Bodies can be strings, `URLSearchParams`, `ArrayBuffer`s and typed arrays.\n * A `Blob`, `FormData` or `ReadableStream` body throws a TypeError: Lynx has\n * no `Blob` or `FormData` and its `fetch` doesn't take them, and a stream\n * can't cross threads.\n */\n\n/** What a body holds: text, bytes, or nothing. */\ntype BodySource = string | Uint8Array | null;\n\nexport type RequestInit = {\n method?: string;\n headers?: HeadersInit;\n body?: unknown;\n signal?: AbortSignal | null;\n cache?: string;\n credentials?: string;\n integrity?: string;\n keepalive?: boolean;\n mode?: string;\n priority?: string;\n redirect?: string;\n referrer?: string;\n referrerPolicy?: string;\n};\n\nexport type ResponseInit = {\n status?: number;\n statusText?: string;\n headers?: HeadersInit;\n};\n\nconst toBytes = (source: BodySource): Uint8Array =>\n typeof source === 'string'\n ? new LynxTextEncoder().encode(source)\n : (source ?? new Uint8Array(0));\n\nconst unsupportedBody = (kind: string) =>\n new TypeError(\n `${kind} request bodies aren't supported on Lynx. Send a string, URLSearchParams, an ArrayBuffer or a typed array.`,\n );\n\n/**\n * Turns a `BodyInit` into text or bytes, and the `Content-Type` it implies.\n * Bytes are copied, so changing the caller's buffer later doesn't change the\n * request.\n */\nconst extractBody = (\n body: unknown,\n): { source: BodySource; type: string | null } => {\n if (body == null) return { source: null, type: null };\n if (typeof body === 'string') {\n return { source: body, type: 'text/plain;charset=UTF-8' };\n }\n if (body instanceof ArrayBuffer) {\n return { source: new Uint8Array(body.slice(0)), type: null };\n }\n if (ArrayBuffer.isView(body)) {\n return {\n source: new Uint8Array(\n body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength),\n ),\n type: null,\n };\n }\n if (\n typeof URLSearchParams !== 'undefined' &&\n body instanceof URLSearchParams\n ) {\n return {\n source: body.toString(),\n type: 'application/x-www-form-urlencoded;charset=UTF-8',\n };\n }\n for (const kind of ['Blob', 'FormData', 'ReadableStream']) {\n const type = (globalThis as any)[kind];\n if (typeof type === 'function' && body instanceof type) {\n throw unsupportedBody(kind);\n }\n }\n if (typeof (body as any).getReader === 'function') {\n throw unsupportedBody('ReadableStream');\n }\n return { source: String(body), type: 'text/plain;charset=UTF-8' };\n};\n\n/**\n * The single-chunk `ReadableStream` a body exposes as `body`: enough for\n * `getReader()` and `for await`, which is how Angular's `FetchBackend` and\n * most libraries read a stream.\n */\nclass LynxBodyStream {\n #chunk: Uint8Array | null;\n #onRead: () => void;\n locked = false;\n\n constructor(chunk: Uint8Array, onRead: () => void) {\n this.#chunk = chunk.length > 0 ? chunk : null;\n this.#onRead = onRead;\n }\n\n getReader() {\n if (this.locked) {\n throw new TypeError(\n \"Failed to execute 'getReader' on 'ReadableStream': ReadableStreamDefaultReader constructor can only accept readable streams that are not yet locked to a reader\",\n );\n }\n this.locked = true;\n this.#onRead();\n let released = false;\n return {\n read: async (): Promise<\n { done: false; value: Uint8Array } | { done: true; value: undefined }\n > => {\n if (released) {\n throw new TypeError('This reader has been released');\n }\n const chunk = this.#chunk;\n this.#chunk = null;\n return chunk\n ? { done: false, value: chunk }\n : { done: true, value: undefined };\n },\n cancel: async (): Promise<void> => {\n this.#chunk = null;\n },\n releaseLock: (): void => {\n released = true;\n this.locked = false;\n },\n closed: Promise.resolve(undefined),\n };\n }\n\n async cancel(): Promise<void> {\n this.#onRead();\n this.#chunk = null;\n }\n\n async *[Symbol.asyncIterator](): AsyncGenerator<Uint8Array> {\n const reader = this.getReader();\n for (;;) {\n const { done, value } = await reader.read();\n if (done) return;\n yield value;\n }\n }\n}\n\n/**\n * What `Request` and `Response` share: the body and the ways to read it.\n */\nabstract class LynxBody {\n #source: BodySource;\n #used = false;\n #stream: LynxBodyStream | undefined;\n\n abstract readonly headers: LynxHeaders;\n\n constructor(source: BodySource) {\n this.#source = source;\n }\n\n get body(): LynxBodyStream | null {\n if (this.#source === null) return null;\n this.#stream ??= new LynxBodyStream(toBytes(this.#source), () => {\n this.#used = true;\n });\n return this.#stream;\n }\n\n get bodyUsed(): boolean {\n return this.#used;\n }\n\n /**\n * The body for sending to the other thread, without consuming it.\n */\n protected relayedBody(): RelayedBody {\n const source = this.#source;\n if (source === null) return null;\n return typeof source === 'string'\n ? { text: source }\n : { base64: bytesToBase64(source) };\n }\n\n /**\n * The body for a clone, which must not share the original's stream.\n */\n protected cloneSource(): BodySource {\n if (this.#used) {\n throw new TypeError(\n \"Failed to execute 'clone': the body is already used\",\n );\n }\n return this.#source;\n }\n\n async #consume(): Promise<BodySource> {\n if (this.#used) {\n throw new TypeError(\n \"Failed to execute 'text' on 'Body': body stream already read\",\n );\n }\n this.#used = true;\n return this.#source;\n }\n\n async text(): Promise<string> {\n const source = await this.#consume();\n // `text()` always decodes UTF-8, whatever the Content-Type says.\n return typeof source === 'string'\n ? source\n : new LynxTextDecoder().decode(toBytes(source));\n }\n\n async json(): Promise<unknown> {\n return JSON.parse(await this.text());\n }\n\n async bytes(): Promise<Uint8Array> {\n return toBytes(await this.#consume());\n }\n\n async arrayBuffer(): Promise<ArrayBuffer> {\n const bytes = await this.bytes();\n return bytes.buffer.slice(\n bytes.byteOffset,\n bytes.byteOffset + bytes.byteLength,\n ) as ArrayBuffer;\n }\n\n async blob(): Promise<Blob> {\n const BlobType = (globalThis as any).Blob as typeof Blob | undefined;\n if (typeof BlobType !== 'function') {\n throw new TypeError('Lynx has no Blob. Use arrayBuffer() instead.');\n }\n return new BlobType([await this.arrayBuffer()], {\n type: this.headers.get('content-type') ?? '',\n });\n }\n\n async formData(): Promise<never> {\n throw new TypeError('Lynx has no FormData. Use text() or json() instead.');\n }\n}\n\n/** The methods the Fetch Standard uppercases. Others, such as PATCH, keep their case. */\nconst NORMALIZED_METHODS = new Set([\n 'DELETE',\n 'GET',\n 'HEAD',\n 'OPTIONS',\n 'POST',\n 'PUT',\n]);\n\n/**\n * Parses a request URL. There's no page URL on Lynx to resolve a relative\n * one against (Lynx's HTTP services reject it as \"unsupported URL\"), so it\n * must be absolute.\n */\nconst parseUrl = (input: string): string => {\n try {\n return new URL(input).href;\n } catch {\n throw new TypeError(\n `Failed to parse URL from ${input}. Lynx has no page URL to resolve a relative URL against, so requests need an absolute URL.`,\n );\n }\n};\n\n/** The Fetch Standard's defaults for a request's other options. */\nconst DEFAULT_OPTIONS: {\n cache: string;\n credentials: string;\n integrity: string;\n keepalive: boolean;\n mode: string;\n priority: string;\n redirect: string;\n referrer: string;\n referrerPolicy: string;\n} = {\n cache: 'default',\n credentials: 'same-origin',\n integrity: '',\n keepalive: false,\n mode: 'cors',\n priority: 'auto',\n redirect: 'follow',\n referrer: 'about:client',\n referrerPolicy: '',\n};\n\n/**\n * A signal that never aborts, for requests made without one.\n */\nconst neverAborts = (): AbortSignal => new AbortController().signal;\n\nexport class LynxRequest extends LynxBody {\n readonly url: string;\n readonly method: string;\n readonly headers: LynxHeaders;\n readonly signal: AbortSignal;\n readonly cache: string;\n readonly credentials: string;\n readonly integrity: string;\n readonly keepalive: boolean;\n readonly mode: string;\n readonly priority: string;\n readonly redirect: string;\n readonly referrer: string;\n readonly referrerPolicy: string;\n readonly destination = '';\n\n constructor(input: string | URL | LynxRequest, init: RequestInit = {}) {\n const base = input instanceof LynxRequest ? input : undefined;\n const method = init.method ?? base?.method ?? 'GET';\n const upper = method.toUpperCase();\n const normalizedMethod = NORMALIZED_METHODS.has(upper) ? upper : method;\n const { source, type } =\n init.body !== undefined\n ? extractBody(init.body)\n : { source: base ? base.cloneSource() : null, type: null };\n if (source !== null && (upper === 'GET' || upper === 'HEAD')) {\n throw new TypeError(\n \"Failed to construct 'Request': Request with GET/HEAD method cannot have body.\",\n );\n }\n super(source);\n this.url = base ? base.url : parseUrl(String(input));\n this.method = normalizedMethod;\n this.headers = new LynxHeaders(init.headers ?? base?.headers);\n if (type !== null && !this.headers.has('content-type')) {\n this.headers.set('content-type', type);\n }\n this.signal = init.signal ?? base?.signal ?? neverAborts();\n const options: typeof DEFAULT_OPTIONS = base ?? DEFAULT_OPTIONS;\n this.cache = init.cache ?? options.cache;\n this.credentials = init.credentials ?? options.credentials;\n this.integrity = init.integrity ?? options.integrity;\n this.keepalive = init.keepalive ?? options.keepalive;\n this.mode = init.mode ?? options.mode;\n this.priority = init.priority ?? options.priority;\n this.redirect = init.redirect ?? options.redirect;\n this.referrer = init.referrer ?? options.referrer;\n this.referrerPolicy = init.referrerPolicy ?? options.referrerPolicy;\n }\n\n clone(): LynxRequest {\n return new LynxRequest(this);\n }\n\n /**\n * The request as fetchForMainThread() takes it.\n */\n toRelayed(): RelayedRequest {\n return {\n url: this.url,\n method: this.method,\n headers: [...this.headers.entries()],\n body: this.relayedBody(),\n // Only what the caller set: Lynx ignores these, and Lynx for Web's\n // worker would apply them to a request it could make without them.\n options: Object.fromEntries(\n Object.entries(DEFAULT_OPTIONS)\n .filter(([name, value]) => (this as any)[name] !== value)\n .map(([name]) => [name, (this as any)[name]]),\n ),\n };\n }\n}\n\n/**\n * A body that's already text or bytes, which internal callers pass to the\n * constructors so it isn't converted again.\n */\nclass ExtractedBody {\n constructor(readonly source: BodySource) {}\n}\n\n/** Values only a response from the network has. */\ntype NetworkDetails = {\n url: string;\n redirected: boolean;\n type: string;\n};\n\nexport class LynxResponse extends LynxBody {\n readonly status: number;\n readonly statusText: string;\n readonly headers: LynxHeaders;\n readonly url: string;\n readonly redirected: boolean;\n /**\n * `basic` for a response from the network: Lynx's HTTP services have no\n * CORS, so there are no `cors` or `opaque` responses.\n */\n readonly type: string;\n\n constructor(\n body?: unknown,\n init: ResponseInit = {},\n details: NetworkDetails = { url: '', redirected: false, type: 'default' },\n ) {\n const status = init.status ?? 200;\n if (\n details.type === 'default' &&\n (!Number.isInteger(status) || status < 200 || status > 599)\n ) {\n throw new RangeError(\n `Failed to construct 'Response': The status provided (${status}) is outside the range [200, 599].`,\n );\n }\n const { source, type } =\n body instanceof ExtractedBody\n ? { source: body.source, type: null }\n : extractBody(body);\n super(source);\n this.status = status;\n this.statusText = init.statusText ?? '';\n this.headers = new LynxHeaders(init.headers);\n if (type !== null && !this.headers.has('content-type')) {\n this.headers.set('content-type', type);\n }\n this.url = details.url;\n this.redirected = details.redirected;\n this.type = details.type;\n }\n\n get ok(): boolean {\n return this.status >= 200 && this.status < 300;\n }\n\n clone(): LynxResponse {\n return new LynxResponse(\n new ExtractedBody(this.cloneSource()),\n {\n status: this.status,\n statusText: this.statusText,\n headers: this.headers,\n },\n { url: this.url, redirected: this.redirected, type: this.type },\n );\n }\n\n static error(): LynxResponse {\n return new LynxResponse(\n null,\n { status: 0 },\n { url: '', redirected: false, type: 'error' },\n );\n }\n\n static json(data: unknown, init: ResponseInit = {}): LynxResponse {\n const response = new LynxResponse(\n new ExtractedBody(JSON.stringify(data)),\n init,\n );\n if (!response.headers.has('content-type')) {\n response.headers.set('content-type', 'application/json');\n }\n return response;\n }\n\n static redirect(url: string, status = 302): LynxResponse {\n if (![301, 302, 303, 307, 308].includes(status)) {\n throw new RangeError(\n `Failed to execute 'redirect' on 'Response': Invalid status code ${status}`,\n );\n }\n return new LynxResponse(null, {\n status,\n headers: { location: parseUrl(url) },\n });\n }\n\n /**\n * Builds the response the background thread sent.\n *\n * @param relayed - The response from fetchForMainThread().\n * @returns The response.\n */\n static fromRelayed(relayed: RelayedResponse): LynxResponse {\n const body = relayed.body;\n const source: BodySource =\n body === null\n ? null\n : 'text' in body\n ? body.text\n : base64ToBytes(body.base64);\n return new LynxResponse(\n new ExtractedBody(source),\n {\n status: relayed.status,\n statusText: relayed.statusText,\n headers: relayed.headers,\n },\n { url: relayed.url, redirected: relayed.redirected, type: 'basic' },\n );\n }\n}\n\nlet nextFetchId = 0;\n\n/**\n * `fetch` for Lynx's main thread: runs the request on the background thread\n * and resolves with its response. It rejects with the signal's reason when\n * the signal aborts, which also aborts the background thread's request, and\n * with a TypeError when the request fails.\n *\n * @param input - The URL, or a Request.\n * @param init - The request's options.\n * @returns The response.\n */\nexport const relayFetch = (\n input: string | URL | LynxRequest,\n init?: RequestInit,\n): Promise<LynxResponse> =>\n new Promise((resolve, reject) => {\n const request = new LynxRequest(input, init);\n const { signal } = request;\n if (signal.aborted) {\n reject(signal.reason);\n return;\n }\n const id = nextFetchId++;\n let settled = false;\n /**\n * Removed once the request settles, so it only runs while in flight.\n */\n const onAbort = () => {\n settled = true;\n reject(signal.reason);\n callOnBackground('abortFetch', id).catch(() => {});\n };\n signal.addEventListener('abort', onAbort);\n const settle = (fn: () => void) => {\n signal.removeEventListener('abort', onAbort);\n if (settled) return;\n settled = true;\n fn();\n };\n callOnBackground('fetch', id, request.toRelayed()).then(\n (relayed) => settle(() => resolve(LynxResponse.fromRelayed(relayed))),\n (error: Error) => settle(() => reject(new TypeError(error.message))),\n );\n });\n","import { LynxDOMException } from './dom-exception';\nimport { LynxHeaders } from './headers';\n\n/**\n * `XMLHttpRequest` for Lynx, which has none on either thread, built on the\n * thread's `fetch` (on the main thread, fetch.ts's relay). Angular's\n * `HttpXhrBackend` (`provideHttpClient(withXhr())`) uses it, as do libraries\n * such as axios, which pick XHR whenever it exists.\n *\n * It's asynchronous only: a synchronous request would have to block the\n * thread until another thread answers. Like the relayed `fetch`, the body\n * arrives in one piece, so `progress` fires once, when it's done, and an\n * upload's `progress` fires once the response starts.\n */\n\ntype Listener = (event: XhrEvent) => void;\n\n/** The event objects XHR listeners get. */\nexport type XhrEvent = {\n type: string;\n target: unknown;\n currentTarget: unknown;\n lengthComputable: boolean;\n loaded: number;\n total: number;\n};\n\n/**\n * Listeners by type, plus the `on<type>` properties, for the request and `upload`.\n */\nclass XhrEventTarget {\n #listeners = new Map<string, Set<Listener>>();\n onloadstart: Listener | null = null;\n onprogress: Listener | null = null;\n onabort: Listener | null = null;\n onerror: Listener | null = null;\n onload: Listener | null = null;\n ontimeout: Listener | null = null;\n onloadend: Listener | null = null;\n\n addEventListener(type: string, listener: Listener | null): void {\n if (!listener) return;\n let listeners = this.#listeners.get(type);\n if (!listeners) {\n listeners = new Set();\n this.#listeners.set(type, listeners);\n }\n listeners.add(listener);\n }\n\n removeEventListener(type: string, listener: Listener | null): void {\n if (listener) this.#listeners.get(type)?.delete(listener);\n }\n\n dispatchEvent(event: { type: string }): boolean {\n const full: XhrEvent = {\n lengthComputable: false,\n loaded: 0,\n total: 0,\n ...event,\n target: this,\n currentTarget: this,\n };\n const handler = (this as any)[`on${event.type}`];\n if (typeof handler === 'function') handler.call(this, full);\n // A copy, so a listener that adds or removes listeners doesn't change\n // who this event reaches, as with EventTarget.\n for (const listener of Array.from(this.#listeners.get(event.type) ?? [])) {\n listener.call(this, full);\n }\n return true;\n }\n\n /**\n * Fires a progress-style event with byte counts.\n */\n protected fire(type: string, loaded = 0, total = 0): void {\n this.dispatchEvent({\n type,\n lengthComputable: total > 0,\n loaded,\n total,\n } as XhrEvent);\n }\n}\n\nclass XhrUpload extends XhrEventTarget {\n /**\n * Lets the request fire the upload's events.\n */\n emit(type: string, loaded?: number, total?: number): void {\n this.fire(type, loaded, total);\n }\n}\n\nconst UNSENT = 0;\nconst OPENED = 1;\nconst HEADERS_RECEIVED = 2;\nconst LOADING = 3;\nconst DONE = 4;\n\n/**\n * The size of a body for upload progress, as far as it can be known.\n */\nconst bodySize = (body: unknown): number => {\n if (typeof body === 'string') return body.length;\n if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n return body.byteLength;\n }\n return 0;\n};\n\nexport class LynxXMLHttpRequest extends XhrEventTarget {\n static readonly UNSENT = UNSENT;\n static readonly OPENED = OPENED;\n static readonly HEADERS_RECEIVED = HEADERS_RECEIVED;\n static readonly LOADING = LOADING;\n static readonly DONE = DONE;\n readonly UNSENT = UNSENT;\n readonly OPENED = OPENED;\n readonly HEADERS_RECEIVED = HEADERS_RECEIVED;\n readonly LOADING = LOADING;\n readonly DONE = DONE;\n\n readonly upload = new XhrUpload();\n onreadystatechange: Listener | null = null;\n readyState = UNSENT;\n status = 0;\n statusText = '';\n responseURL = '';\n responseType: XMLHttpRequestResponseType = '';\n response: unknown = '';\n timeout = 0;\n withCredentials = false;\n\n #method = 'GET';\n #url = '';\n #requestHeaders = new LynxHeaders();\n #responseHeaders = new LynxHeaders();\n #responseText = '';\n #controller: AbortController | undefined;\n /** Counts sends, so a request that was aborted or reopened ignores its old fetch. */\n #generation = 0;\n #timer: ReturnType<typeof setTimeout> | undefined;\n /** Whether the upload's events are still to come. */\n #uploading = false;\n\n get responseText(): string {\n if (this.responseType !== '' && this.responseType !== 'text') {\n throw new LynxDOMException(\n `Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'text' (was '${this.responseType}').`,\n 'InvalidStateError',\n );\n }\n return this.#responseText;\n }\n\n open(method: string, url: string | URL, async = true): void {\n if (!async) {\n throw new LynxDOMException(\n \"Failed to execute 'open' on 'XMLHttpRequest': Synchronous requests aren't supported on Lynx, where the request runs on another thread.\",\n 'InvalidAccessError',\n );\n }\n this.#cancel();\n this.#method = method;\n this.#url = String(url);\n this.#requestHeaders = new LynxHeaders();\n this.#reset();\n this.#setReadyState(OPENED);\n }\n\n setRequestHeader(name: string, value: string): void {\n this.#assertOpened('setRequestHeader');\n this.#requestHeaders.append(name, value);\n }\n\n send(body: unknown = null): void {\n this.#assertOpened('send');\n const generation = ++this.#generation;\n const controller = new AbortController();\n this.#controller = controller;\n const method = this.#method.toUpperCase();\n const sendsBody = method !== 'GET' && method !== 'HEAD' && body != null;\n const uploadSize = sendsBody ? bodySize(body) : 0;\n this.#uploading = sendsBody;\n this.fire('loadstart');\n if (sendsBody) this.upload.emit('loadstart', 0, uploadSize);\n if (this.timeout > 0) {\n this.#timer = setTimeout(() => {\n if (generation !== this.#generation) return;\n this.#fail('timeout');\n }, this.timeout);\n }\n const current = () => generation === this.#generation;\n Promise.resolve()\n .then(() =>\n globalThis.fetch(this.#url, {\n method: this.#method,\n headers: this.#requestHeaders as unknown as HeadersInit,\n body: sendsBody ? (body as BodyInit) : undefined,\n credentials: this.withCredentials ? 'include' : 'same-origin',\n signal: controller.signal,\n }),\n )\n .then(async (response) => {\n if (!current()) return;\n this.#uploadDone(uploadSize);\n this.status = response.status;\n this.statusText = response.statusText;\n this.responseURL = response.url;\n this.#responseHeaders = new LynxHeaders(\n response.headers as unknown as Iterable<[string, string]>,\n );\n this.#setReadyState(HEADERS_RECEIVED);\n this.#setReadyState(LOADING);\n const size = await this.#readResponse(response);\n if (!current()) return;\n this.#finish();\n this.fire('progress', size, size);\n this.#setReadyState(DONE);\n this.fire('load', size, size);\n this.fire('loadend', size, size);\n })\n .catch(() => {\n // An abort or a timeout has already ended the request.\n if (current()) this.#fail('error');\n });\n }\n\n abort(): void {\n if (this.#controller && this.readyState !== DONE) {\n this.#fail('abort');\n }\n if (this.readyState === DONE) {\n this.readyState = UNSENT;\n }\n }\n\n getResponseHeader(name: string): string | null {\n return this.readyState >= HEADERS_RECEIVED\n ? this.#responseHeaders.get(name)\n : null;\n }\n\n /**\n * Each header as `name: value`, one per line, the way browsers list them.\n */\n getAllResponseHeaders(): string {\n if (this.readyState < HEADERS_RECEIVED) return '';\n let headers = '';\n for (const [name, value] of this.#responseHeaders) {\n headers += `${name}: ${value}\\r\\n`;\n }\n return headers;\n }\n\n overrideMimeType(_mime: string): void {\n // Only UTF-8 text is decoded, so there's no charset to override.\n }\n\n /**\n * Reads the body into `response` for `responseType`, and returns its size\n * for the progress events. Text is read as text, so the relayed `fetch`\n * doesn't turn it into bytes only for this to decode them again.\n */\n async #readResponse(response: Response): Promise<number> {\n const type = this.responseType;\n if (type === 'arraybuffer' || type === 'blob') {\n const buffer = await response.arrayBuffer();\n const BlobType = (globalThis as any).Blob as typeof Blob | undefined;\n this.response =\n type === 'arraybuffer'\n ? buffer\n : typeof BlobType === 'function'\n ? new BlobType([buffer], {\n type: this.#responseHeaders.get('content-type') ?? '',\n })\n : // Lynx has no Blob, so there's nothing to return.\n null;\n return buffer.byteLength;\n }\n const text = await response.text();\n if (type === 'json') {\n try {\n this.response = text === '' ? null : JSON.parse(text);\n } catch {\n this.response = null;\n }\n } else if (type === 'document') {\n // There's no DOM to parse into.\n this.response = null;\n } else {\n this.#responseText = text;\n this.response = text;\n }\n const length = Number(this.#responseHeaders.get('content-length'));\n return Number.isFinite(length) && length > 0 ? length : text.length;\n }\n\n /**\n * Fires the upload's closing events, once the response starts.\n */\n #uploadDone(size: number): void {\n if (!this.#uploading) return;\n this.#uploading = false;\n this.upload.emit('progress', size, size);\n this.upload.emit('load', size, size);\n this.upload.emit('loadend', size, size);\n }\n\n /**\n * Ends a request that didn't load: a network error, an abort or a timeout.\n */\n #fail(type: 'error' | 'abort' | 'timeout'): void {\n this.#cancel();\n this.#reset();\n this.#setReadyState(DONE);\n if (this.#uploading) {\n this.#uploading = false;\n this.upload.emit(type);\n this.upload.emit('loadend');\n }\n this.fire(type);\n this.fire('loadend');\n }\n\n /**\n * Stops the request in flight, if any, so its result is ignored.\n */\n #cancel(): void {\n this.#generation++;\n this.#finish();\n this.#controller?.abort();\n this.#controller = undefined;\n }\n\n #finish(): void {\n if (this.#timer !== undefined) clearTimeout(this.#timer);\n this.#timer = undefined;\n }\n\n #reset(): void {\n this.status = 0;\n this.statusText = '';\n this.responseURL = '';\n this.response =\n this.responseType === '' || this.responseType === 'text' ? '' : null;\n this.#responseText = '';\n this.#responseHeaders = new LynxHeaders();\n }\n\n #assertOpened(method: string): void {\n if (this.readyState !== OPENED || this.#controller) {\n throw new LynxDOMException(\n `Failed to execute '${method}' on 'XMLHttpRequest': The object's state must be OPENED.`,\n 'InvalidStateError',\n );\n }\n }\n\n #setReadyState(state: number): void {\n this.readyState = state;\n this.dispatchEvent({ type: 'readystatechange' });\n }\n}\n","import { LynxDOMException } from './dom-exception';\nimport { LynxRequest, LynxResponse, relayFetch } from './fetch';\nimport { LynxHeaders } from './headers';\nimport { LynxTextDecoder, LynxTextEncoder } from './text-codec';\nimport { LynxXMLHttpRequest } from './xhr';\n\nexport {\n LynxDOMException,\n LynxHeaders,\n LynxRequest,\n LynxResponse,\n LynxTextDecoder,\n LynxTextEncoder,\n LynxXMLHttpRequest,\n relayFetch,\n};\n\n/**\n * Installs the web's network APIs on `target`, Lynx's main thread, where\n * they're missing: `fetch` (relayed to the background thread's), `Headers`,\n * `Request`, `Response`, `XMLHttpRequest`, `TextEncoder`, `TextDecoder` and\n * `DOMException`. With them, `provideHttpClient()` works as it does in a\n * browser, whichever backend it uses (`FetchBackend` by default, or\n * `HttpXhrBackend` with `withXhr()`), and so do `httpResource` and libraries\n * that call `fetch` or XHR.\n *\n * Each is installed only where it's missing, so the web preview, whose main\n * thread is a browser frame, keeps its own. Takes the global as a parameter\n * so tests can pass a stand-in, as installUrl() does.\n *\n * @param target - The global object.\n */\nexport const installNetworkGlobals = (\n target: Record<string, unknown>,\n): void => {\n const install = (name: string, value: unknown) => {\n if (typeof target[name] === 'undefined') target[name] = value;\n };\n install('TextEncoder', LynxTextEncoder);\n install('TextDecoder', LynxTextDecoder);\n install('DOMException', LynxDOMException);\n // The classes go together: the relayed fetch builds a LynxResponse, and\n // Angular checks `headers instanceof Headers`.\n if (typeof target['fetch'] === 'undefined') {\n install('fetch', relayFetch);\n install('Headers', LynxHeaders);\n install('Request', LynxRequest);\n install('Response', LynxResponse);\n }\n install('XMLHttpRequest', LynxXMLHttpRequest);\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 { isMainThread } from './background-call';\nimport { installNetworkGlobals } from './network';\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// Lynx's main thread has no fetch, XMLHttpRequest, Headers, TextDecoder or\n// DOMException, and the background thread, which has fetch, runs no Angular.\n// So HttpClient, httpResource and fetch-based libraries failed wherever they\n// ran. These versions send each request to the background thread's fetch.\n// The background thread keeps its own globals: its fetch is passed into the\n// bundle's wrapper function, so it isn't on globalThis and would look missing.\nif (isMainThread()) {\n installNetworkGlobals(globalThis as unknown as Record<string, unknown>);\n}\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 { ReplaySubject } from 'rxjs';\nimport {\n applyGlobalDataUpdate,\n applyInitDataUpdate,\n} from './data-flow/host-updates';\nimport { ssrEncode, ssrHydrate } from './ssr/ssr-callbacks';\nimport {\n __mainThreadRefMap,\n __pendingResolvers,\n __workletMap,\n answerCall,\n nextResolveId,\n restoreRefs,\n transformParams,\n} from './worklet-bridge';\n\n/**\n * Calls the worklet registered as `id` on this thread. A missing one throws,\n * which a cross-thread call sends back as its error: resolving `undefined`\n * would hide an ID that differs between the threads, such as a worklet\n * defined inside a function instead of at module level.\n */\nconst callWorklet = (id: string, args: unknown[], kind: string): unknown => {\n const fn = __workletMap[id];\n if (!fn) {\n throw new Error(`[angular-lynx] ${kind} not found: ${id}`);\n }\n return fn(...args);\n};\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 *\n * It replays, because the engine calls renderPage once per page, and a hot\n * update can bootstrap the app again after that. That includes after a first\n * bootstrap that failed, which leaves no app to tell a re-bootstrap from a\n * first boot by.\n */\nexport const pageReady = new ReplaySubject<void>(1);\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, with the page's\n * InitData. On the main thread, bootstrapApplication() awaits this before\n * calling Angular's bootstrap.\n * - updatePage: called when the host app sends updated InitData.\n * - updateGlobalProps: called when the host app changes the GlobalData.\n * - processData: called before data delivery for transformation. Overridden by\n * registerDataProcessors() if the app needs custom data processing.\n *\n * The engine calls renderPage, updatePage and updateGlobalProps on the main\n * thread only. The background thread hears about host updates through hooks\n * on lynx.getApp() instead (further down).\n *\n * Lynx stores InitData nowhere the app can read it, so the runtime keeps it as\n * `lynx.__initData`, where React Lynx keeps it and LynxInitData seeds from.\n * Each thread receives it differently: the main thread through renderPage(data)\n * (below), the background thread through the loadCard params (further down).\n */\n// @ts-expect-error\nglobalThis.renderPage = (data?: Record<string, unknown>) => {\n if (typeof lynx !== 'undefined') {\n (lynx as any).__initData = data ?? {};\n }\n pageReady.next();\n};\n\n// The main thread is where the UI is drawn, so its copy of LynxInitData must\n// hear about updates. `resetPageData` is set when the host resets the data\n// instead of updating it. React Lynx's updatePage merges the same way.\n// @ts-expect-error\nglobalThis.updatePage = (\n data?: Record<string, unknown>,\n options?: { resetPageData?: boolean },\n) => {\n if (typeof lynx !== 'undefined') {\n applyInitDataUpdate(data, !!options?.resetPageData);\n }\n};\n\n// Native Lynx calls this global unless an engine listener (below) is\n// registered for the same event. Native has already set lynx.__globalProps\n// to `data` by then; applyGlobalDataUpdate() sets it too, for the web.\n(globalThis as any).updateGlobalProps = (data?: Record<string, unknown>) => {\n if (typeof lynx !== 'undefined') {\n applyGlobalDataUpdate(data);\n }\n};\n\n// @lynx-js/web-core never calls the updateGlobalProps global. It only\n// dispatches `__UpdateGlobalProps` to listeners on lynx.getEngine(), with the\n// call's arguments as `data`. Newer native engines do the same once a listener\n// exists, instead of calling the global. Either way the update arrives once.\nif (\n __MAIN_THREAD__ &&\n typeof lynx !== 'undefined' &&\n typeof (lynx as any).getEngine === 'function'\n) {\n (lynx as any)\n .getEngine()\n .addEventListener('__UpdateGlobalProps', (event: { data?: unknown[] }) =>\n applyGlobalDataUpdate(event.data?.[0]),\n );\n}\n\n// The engine hands processData's return value to renderPage and to the\n// background thread, so the default must pass the data through unchanged, as\n// React Lynx's default processor does. Native Lynx falls back to the original\n// data when the result isn't an object, but @lynx-js/web-core doesn't, so a\n// no-op that returned undefined dropped every app's InitData on the web.\n// @ts-expect-error\nglobalThis.processData = (data?: Record<string, unknown>) => data;\n\n// The background thread gets no renderPage call. lynx-core keeps the params it\n// loaded the page with on the app instead: `initData`, plus any `updateData`\n// the host sent before the page loaded, which wins. React Lynx merges them the\n// same way. `getApp` is checked because it's missing outside a real Lynx\n// host, such as in unit tests.\nif (\n !__MAIN_THREAD__ &&\n typeof lynx !== 'undefined' &&\n typeof (lynx as any).getApp === 'function'\n) {\n const app = (lynx as any).getApp();\n const params = app._params;\n (lynx as any).__initData = { ...params?.initData, ...params?.updateData };\n\n /**\n * Host updates reach the background thread through the updateCardData and\n * updateGlobalProps hooks below, which lynx-core leaves for the framework to\n * define, as React Lynx does. Lynx emits no GlobalEventEmitter event for\n * them itself, so the hooks emit React Lynx's `onDataChanged` and\n * `onGlobalPropsChanged` through this, for app code that listens for them.\n */\n const emit = (eventName: string, args: unknown[]): void =>\n lynx.getJSModule?.('GlobalEventEmitter')?.emit?.(eventName, args);\n\n app.updateCardData = (\n data?: Record<string, unknown>,\n options?: { type?: number },\n ) => {\n // `__lynx_timing_flag` only marks the update for performance timing; it\n // isn't page data. React Lynx drops it too.\n const { __lynx_timing_flag: _timingFlag, ...patch } = data ?? {};\n // Type 1 is a reset (NativeUpdateDataType.RESET in React Lynx).\n applyInitDataUpdate(patch, options?.type === 1);\n emit('onDataChanged', [patch]);\n };\n app.updateGlobalProps = (data?: Record<string, unknown>) => {\n emit('onGlobalPropsChanged', [applyGlobalDataUpdate(data)]);\n };\n}\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: the main thread calls background functions with\n// 'Lynx.Worklet.runOnBackground', and the background thread replies with\n// 'Lynx.Worklet.BgFunctionCallRet'. resolveId ties each reply to its Promise.\n// There's no call the other way: Angular runs on the main thread only, so\n// LynxMainThread.runOnMainThread() runs its function in place (issue #81).\nif (__MAIN_THREAD__) {\n try {\n if (typeof lynx !== 'undefined' && (lynx as any).getJSContext) {\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: the background thread runs the main thread's\n// runOnBackground requests.\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 // 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 // answerCall awaits an async function, such as one that fetches,\n // before replying.\n answerCall(\n resolveId,\n () =>\n callWorklet(\n worklet._wkltId,\n params.map(restoreRefs),\n 'Background function',\n ),\n (data) =>\n (lynx as any).getCoreContext().dispatchEvent({\n type: 'Lynx.Worklet.BgFunctionCallRet',\n data,\n }),\n );\n },\n );\n }\n } catch {\n // lynx.getCoreContext() may not be available in all environments\n }\n}\n\n/**\n * Synchronously invoke a registered worklet by its _wkltId with raw,\n * already-in-process args. Used by LynxMainThread.runOnMainThread(): Angular\n * code runs on the main thread, where the worklets are, so the call needs no\n * thread hop. The args never go through JSON, so refs and element handles are\n * still the real objects. Exposed as a global (rather than imported) because\n * the __workletMap is a module-load side-effect while LynxMainThread is\n * DI-instantiated later.\n */\nglobalThis.__lynxRunMainThreadWorklet = (\n wkltId: string,\n args: unknown[],\n): unknown => callWorklet(wkltId, args, 'Main-thread worklet');\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, the global exposure bridge, the background call relay and the log\n// relay. They are all the background thread runs of the runtime, since Angular\n// boots on the main thread only. `pageReady` is the only value bootstrap itself\n// needs from them (renderPage readiness).\nimport './error-reporting';\nimport './polyfills';\nimport { pageReady } from './global-callbacks';\nimport './exposure/global-exposure-bridge';\nimport './background-call';\nimport './lynx-logger/lynx-logger';\nimport { installLazyBundleLoader } from './lazy-bundle/chunk-loader';\nimport { handOverPageToNextApp } from './lynx-document/page-ref';\nimport { carryOverLocation } from './router/lynx-location-strategy';\n\n/**\n * Starts the background thread. The build calls it from the background\n * thread's entry, a module it generates in place of the app's `main.ts`\n * (background-entry.ts in the build plugin): Angular runs on the main thread\n * only, so the background thread loads just this runtime and the modules that\n * define a background function or a `MainThreadRef`.\n *\n * Loading the runtime installs the background half of each bridge (the imports\n * above). This installs `lynx.loadLazyBundle`, for an `import()` in a\n * background function. Importing it is also what keeps the runtime in the\n * background bundle: the package is marked `\"sideEffects\": false`, so a bare\n * `import '@blotch/angular-lynx'` would be dropped.\n */\nexport const ɵstartBackgroundThread = (): void => {\n installLazyBundleLoader();\n};\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 *\n * Angular runs on the main thread only. The background thread starts from an\n * entry the build generates instead of `main.ts` (see\n * {@link ɵstartBackgroundThread}), so it doesn't reach this function, unless a\n * module it loads also bootstraps, such as a `main.ts` that defines a\n * `backgroundFn()` itself. Then it gets no app: the returned promise never\n * settles on that thread. Booting a second copy there ran every constructor,\n * `ngOnInit` and `effect()` twice, and its views went nowhere (issue #81).\n */\nexport const bootstrapApplication = async (\n rootComponent: Type<unknown>,\n options?: ApplicationConfig,\n): Promise<ApplicationRef> => {\n if (!__MAIN_THREAD__) {\n // A pending promise rather than a rejected one: main.ts usually ends in\n // `.catch(console.error)`, which would log an error on every launch.\n // Nothing that needs an ApplicationRef can run here anyway.\n return new Promise<ApplicationRef>(() => {});\n }\n\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 // before Angular can trigger any dynamic import. Placed before the hot\n // update 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 const bootstrap = bootstrapOnMainThread(rootComponent, options);\n // A hot update that re-runs the app's entry calls this again (see\n // `ɵhmrAccept`). The plugin's main-thread hot update client waits for this\n // promise after applying an update, and reloads the page if it rejects:\n // the old app is already gone by then, so a failed re-bootstrap would\n // otherwise leave a blank screen.\n (globalThis as any).__LYNX_ANGULAR_BOOTSTRAP__ = bootstrap;\n return bootstrap;\n};\n\nconst bootstrapOnMainThread = async (\n rootComponent: Type<unknown>,\n options: ApplicationConfig | undefined,\n): Promise<ApplicationRef> => {\n // Hot update re-bootstrap: destroy the previous app so Angular's platform\n // accepts a new one. A hot update whose changes no component could take in\n // place re-runs the app's entry, which calls this again. The old app is\n // destroyed (which removes its Lynx elements) and a fresh one is created\n // from the updated modules.\n const prev = (globalThis as any).__LYNX_ANGULAR_APP_REF__ as\n | ApplicationRef\n | undefined;\n if (prev) {\n // The new app opens on the screen the old one was showing, with the same\n // Back history, instead of on the initial route.\n carryOverLocation(prev.injector);\n // ...in the page the old app rendered into (see createRootElement).\n handOverPageToNextApp();\n prev.destroy();\n (globalThis as any).__LYNX_ANGULAR_APP_REF__ = undefined;\n // The main-thread worklet registry is deliberately left alone. A hot\n // update re-runs only the changed modules and the ones that import them,\n // so a module-level `mainThreadFn()` elsewhere is never registered again,\n // and clearing the registry (as an earlier version did) broke it. The\n // re-run modules register new functions under new IDs (the IDs come from\n // a counter), and the old app's per-instance functions were released by\n // its DestroyRefs in destroy() above.\n }\n\n // Wait for Lynx's renderPage callback. After the first boot, pageReady has\n // already fired, and replays it.\n await firstValueFrom(pageReady);\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__ && !wasHydrating) {\n setTimeout(() => __FlushElementTree(), 0);\n }\n\n return appRef;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"blotch-angular-lynx.mjs","names":[],"sources":["../../src/lib/network/base64.ts","../../src/lib/network/background-fetch.ts","../../src/lib/background-call.ts","../../src/lib/animation/animation.ts","../../src/lib/main-thread/main-thread-element.ts","../../src/lib/accessibility/accessibility.ts","../../src/lib/data-flow/host-updates.ts","../../src/lib/data-flow/global-data.ts","../../src/lib/accessibility/accessibility-settings.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/init-data.ts","../../src/lib/error-handler/lynx-error-handler.ts","../../src/lib/exposure/exposure.ts","../../src/lib/exposure/global-exposure-bridge.ts","../../src/lib/exposure/global-exposure.ts","../../src/lib/font/font.ts","../../src/lib/lazy-bundle/lazy-bundle.ts","../../src/lib/hmr/hmr-accept.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/fling-gesture.ts","../../src/lib/lynx-document/element-creators/create-block-element.ts","../../src/lib/lynx-document/android-blur-capture.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/web-textarea.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/android-blur-material.ts","../../src/lib/lynx-document/page-ref.ts","../../src/lib/lynx-render-lifecycle.ts","../../src/lib/lynx-element/svg-content.ts","../../src/lib/lynx-element/web-long-press.ts","../../src/lib/lynx-element/types.ts","../../src/lib/lynx-element/lynx-element.ts","../../src/lib/lynx-element/lynx-list-element.ts","../../src/lib/gesture/gesture-papi.ts","../../src/lib/gesture/event.ts","../../src/lib/gesture/state-manager.ts","../../src/lib/gesture/gesture-detector.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/router/lynx-router-link-active.ts","../../src/lib/accessibility/accessibility-traits.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/worklet-bridge.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-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/storage/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/web-auth-session/web-auth-session.ts","../../src/lib/lynx-document/host-elements.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-back-button.ts","../../src/lib/router/lynx-router.ts","../../src/lib/error-reporting.ts","../../src/lib/network/dom-exception.ts","../../src/lib/network/headers.ts","../../src/lib/url/percent-encoding.ts","../../src/lib/network/text-codec.ts","../../src/lib/network/fetch.ts","../../src/lib/network/xhr.ts","../../src/lib/network/index.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/global-callbacks.ts","../../src/lib/lazy-bundle/chunk-loader.ts","../../src/lib/runtime.ts"],"sourcesContent":["/**\n * Base64 for the bytes of request and response bodies, which cross between\n * Lynx's threads as JSON. Hand-written because neither thread has `btoa` or\n * `atob`, and the main thread has no other way to turn bytes into a string.\n */\n\nconst ALPHABET =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\nconst VALUES = new Map(Array.from(ALPHABET, (char, index) => [char, index]));\n\n/**\n * Builds the string in slices: one `String.fromCharCode` call per slice keeps\n * the work linear, where adding a character at a time can copy the whole\n * string on every step in an engine without rope strings.\n */\nconst SLICE = 8192;\n\n/**\n * Encodes bytes as standard base64, with padding.\n *\n * @param bytes - The bytes to encode.\n * @returns The base64 text.\n */\nexport const bytesToBase64 = (bytes: Uint8Array): string => {\n const codes: number[] = [];\n let output = '';\n for (let index = 0; index < bytes.length; index += 3) {\n const a = bytes[index] as number;\n const b = bytes[index + 1];\n const c = bytes[index + 2];\n codes.push(\n ALPHABET.charCodeAt(a >> 2),\n ALPHABET.charCodeAt(((a & 0x3) << 4) | ((b ?? 0) >> 4)),\n b === undefined\n ? 0x3d\n : ALPHABET.charCodeAt(((b & 0xf) << 2) | ((c ?? 0) >> 6)),\n c === undefined ? 0x3d : ALPHABET.charCodeAt(c & 0x3f),\n );\n if (codes.length >= SLICE) {\n output += String.fromCharCode(...codes);\n codes.length = 0;\n }\n }\n return output + String.fromCharCode(...codes);\n};\n\n/**\n * Decodes standard base64. Padding is optional, and characters outside the\n * alphabet, such as line breaks, are skipped.\n *\n * @param base64 - The base64 text.\n * @returns The bytes.\n */\nexport const base64ToBytes = (base64: string): Uint8Array<ArrayBuffer> => {\n const values: number[] = [];\n for (const char of base64) {\n const value = VALUES.get(char);\n if (value !== undefined) values.push(value);\n }\n const bytes = new Uint8Array(Math.floor((values.length * 3) / 4));\n let byteIndex = 0;\n for (let index = 0; index < values.length; index += 4) {\n const a = values[index] as number;\n const b = values[index + 1] ?? 0;\n const c = values[index + 2];\n const d = values[index + 3];\n bytes[byteIndex++] = (a << 2) | (b >> 4);\n if (c !== undefined) bytes[byteIndex++] = ((b & 0xf) << 4) | (c >> 2);\n if (d !== undefined) bytes[byteIndex++] = ((c! & 0x3) << 6) | d;\n }\n return bytes;\n};\n","import { base64ToBytes, bytesToBase64 } from './base64';\n\n/**\n * The background thread's half of the main thread's `fetch` (see fetch.ts).\n * Lynx has `fetch` on the background thread only, and Angular runs on the\n * main thread, so the main thread's `fetch` sends each request here, where\n * background-call.ts's relay runs it, and this sends the response back.\n *\n * Everything crosses as JSON. A body is text when it can be, and base64\n * otherwise, since JSON can't carry bytes.\n */\n\n/** A request or response body as it crosses threads. */\nexport type RelayedBody = { text: string } | { base64: string } | null;\n\n/** A request as the main thread sends it. */\nexport type RelayedRequest = {\n url: string;\n method: string;\n /** Unique names, since the main thread's Headers joins repeated ones. */\n headers: [string, string][];\n body: RelayedBody;\n /** The rest of `RequestInit`, for hosts that use it (Lynx for Web's worker). */\n options: {\n cache?: string;\n credentials?: string;\n integrity?: string;\n keepalive?: boolean;\n mode?: string;\n priority?: string;\n redirect?: string;\n referrer?: string;\n referrerPolicy?: string;\n };\n};\n\n/** A response as the background thread sends it back. */\nexport type RelayedResponse = {\n status: number;\n statusText: string;\n url: string;\n redirected: boolean;\n headers: [string, string][];\n body: RelayedBody;\n};\n\n/**\n * Lynx's HTTP services don't reject when a request fails: they resolve with\n * status 499, the failure as its status text, and no headers\n * (`SDK_ERROR_STATUS_CODE` in LynxHttpService.m, `CODE_FAILED_INTERNALLY` in\n * LynxHttpService.kt). That covers a refused connection, a bad host, a\n * relative URL (\"unsupported URL\") and Android's cleartext block.\n */\nconst LYNX_FAILURE_STATUS = 499;\n\n/** Statuses whose responses have no body (the Fetch Standard's null body statuses). */\nconst NULL_BODY_STATUSES = new Set([101, 103, 204, 205, 304]);\n\n/**\n * Media types sent as text. Others go as base64, since text would lose bytes\n * that aren't valid UTF-8.\n */\nconst TEXT_TYPE =\n /^(text\\/|application\\/([\\w.+-]*\\+)?(json|xml|javascript|ecmascript|x-www-form-urlencoded|graphql)\\b)/;\n\n/**\n * Whether a body of this `Content-Type` is safe to send as text: a textual\n * type in UTF-8. Lynx decodes `response.text()` as UTF-8 whatever the\n * charset, so another charset goes as bytes, for the main thread to decode.\n */\nconst isUtf8Text = (contentType: string | null): boolean => {\n if (!contentType) return false;\n const type = contentType.toLowerCase();\n const charset = /;\\s*charset=\"?([^\";]+)/.exec(type)?.[1];\n return (\n TEXT_TYPE.test(type) && (charset === undefined || /^utf-?8$/.test(charset))\n );\n};\n\n/**\n * A header name in the case HTTP/1.1 clients send it: `content-type` →\n * `Content-Type`, `x-api-key` → `X-Api-Key`.\n *\n * The main thread's Headers lowercases names, as the standard's does, but\n * Lynx's background `Headers` (through 4.2) matches them by exact spelling.\n * Its `Request` looks for `Content-Type`, and when that misses it adds\n * `Content-Type: text/plain;charset=UTF-8` beside the request's own. iOS\n * then sends whichever of the two it sets last (dictionary order), and\n * Android sends both. HTTP names are case-insensitive, so every name goes\n * in this case, not only that one, for a host's own HTTP service that looks\n * others up by their usual spelling.\n */\nconst canonicalName = (name: string): string =>\n name\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('-');\n\nconst decodeBody = (body: RelayedBody): string | ArrayBuffer | undefined => {\n if (body === null) return undefined;\n if ('text' in body) return body.text;\n const bytes = base64ToBytes(body.base64);\n // Lynx's Request copies `body.buffer` whole, so it must hold only the body.\n return bytes.buffer;\n};\n\n/**\n * The thread's own `fetch`, by name rather than from `globalThis`: Lynx's\n * background thread passes it into the bundle's wrapper function as a\n * parameter, so `globalThis.fetch` is undefined there.\n */\nconst backgroundFetch = (): typeof fetch | undefined =>\n typeof fetch === 'function' ? fetch : undefined;\n\n/** The controller for each request in flight, by the main thread's ID. */\nconst controllers = new Map<number, AbortController>();\n\n/**\n * Runs a request for the main thread and resolves with the response, body\n * included. It rejects with a TypeError when the request fails, as `fetch`\n * does.\n *\n * @param id - The main thread's ID for the request, to abort it by.\n * @param request - The request.\n * @returns The response.\n */\nexport const fetchForMainThread = async (\n id: number,\n request: RelayedRequest,\n): Promise<RelayedResponse> => {\n const fetchImpl = backgroundFetch();\n if (!fetchImpl) {\n throw new TypeError(\n \"fetch isn't available on the background thread in this environment\",\n );\n }\n const controller = new AbortController();\n controllers.set(id, controller);\n try {\n const response = await fetchImpl(request.url, {\n ...(request.options as RequestInit),\n method: request.method,\n headers: Object.fromEntries(\n request.headers.map(([name, value]) => [canonicalName(name), value]),\n ),\n body: decodeBody(request.body),\n signal: controller.signal,\n });\n const headers: [string, string][] = [];\n response.headers.forEach((value, name) => headers.push([name, value]));\n if (response.status === LYNX_FAILURE_STATUS && headers.length === 0) {\n throw new TypeError(response.statusText || 'Network request failed');\n }\n // Looked up by hand, since Lynx's `get()` matches names by exact spelling,\n // and a response's names come lowercase on Android but capitalized on\n // iOS (`Content-Type`).\n const contentType =\n headers.find(([name]) => name.toLowerCase() === 'content-type')?.[1] ??\n null;\n let body: RelayedBody = null;\n if (!NULL_BODY_STATUSES.has(response.status)) {\n body = isUtf8Text(contentType)\n ? { text: await response.text() }\n : {\n base64: bytesToBase64(new Uint8Array(await response.arrayBuffer())),\n };\n }\n return {\n status: response.status,\n statusText: response.statusText,\n // Lynx leaves out `redirected`, and on Android `url` is the request's.\n url: response.url || request.url,\n redirected: response.redirected === true,\n headers,\n body,\n };\n } finally {\n controllers.delete(id);\n }\n};\n\n/**\n * Aborts a request the main thread sent, when its signal aborts. The main\n * thread has already rejected its own promise; this stops the work here.\n *\n * @param id - The main thread's ID for the request.\n */\nexport const abortFetchForMainThread = (id: number): void => {\n controllers.get(id)?.abort();\n};\n","import type { ObserverFrameRateOptions } from './exposure/exposure.types';\nimport {\n abortFetchForMainThread,\n fetchForMainThread,\n type RelayedRequest,\n type RelayedResponse,\n} from './network/background-fetch';\n\n/**\n * Some Lynx APIs exist only on the background thread's `lynx` object. The main\n * thread's (`Utils::CreateLynx` in Lynx core's renderer_ng.cc) has no\n * `accessibilityAnnounce`, `addFont`, `setObserverFrameRate`,\n * `subscribeSessionStorage`, `requestResourcePrefetch` or `getJSModule`, and\n * web-core's has no `stopExposure` or `resumeExposure` either. `NativeModules`\n * exists only on the background thread too, as does `fetch`. Angular runs on\n * the main thread, so no service can reach them directly. callOnBackground() runs the call on\n * the background thread and resolves with its result, from either thread.\n *\n * The relay uses the same cross-thread event channel as the worklet RPC in\n * global-callbacks.ts: the main thread dispatches on getJSContext(), and the\n * background thread listens and replies on getCoreContext(). Results travel as\n * JSON, and an error arrives as its message.\n *\n * The handlers live here rather than in the services, and the listeners are\n * installed at module load, because the background thread might never construct\n * a service that only a main-thread code path injects.\n */\n\nconst CALL_EVENT = 'AngularLynx.BackgroundCall';\nconst RESULT_EVENT = 'AngularLynx.BackgroundCallResult';\nconst SESSION_STORAGE_EVENT = 'AngularLynx.SessionStorageChange';\nconst CALLBACK_EVENT = 'AngularLynx.Callback';\n\n/**\n * `__MAIN_THREAD__` is a build-time define. Unit tests don't define it, and run\n * as the background thread unless they stub it.\n *\n * @returns Whether this code runs on the main thread.\n */\nexport const isMainThread = (): boolean =>\n typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__;\n\n/**\n * Returns a background-only `lynx` method, or throws the error the services\n * have always thrown where it's missing, such as in the web preview.\n */\nconst lynxApi = (name: string): ((...args: any[]) => any) => {\n const fn = typeof lynx !== 'undefined' ? (lynx as any)[name] : undefined;\n if (typeof fn !== 'function') {\n throw new Error(`lynx.${name} is not available in this environment`);\n }\n return fn.bind(lynx);\n};\n\n/** Native session storage subscriptions made for the main thread, by relay ID. */\nconst relayedSubscriptions = new Map<\n number,\n { key: string; listenerId: number }\n>();\n\n/** A function argument as it crosses threads: the ID to call it back by. */\ntype FunctionMarker = { __angularLynxCallback: number };\n\n/** Main thread: each function sent with a relayed call, by ID. */\nconst relayedFunctions = new Map<number, (...args: unknown[]) => unknown>();\n/** Main thread: the ID each function was sent with, so it keeps one. */\nconst relayedFunctionIds = new WeakMap<object, number>();\nlet nextFunctionId = 0;\n/** Background thread: the stand-in for each of the main thread's functions. */\nconst standIns = new Map<number, (...args: unknown[]) => void>();\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (typeof value !== 'object' || value === null) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n};\n\nconst isFunctionMarker = (value: unknown): value is FunctionMarker =>\n isPlainObject(value) && typeof value['__angularLynxCallback'] === 'number';\n\n/**\n * Main thread: the marker for a function, registered so the background\n * thread's stand-in can call it. A function keeps its ID, so passing the same\n * listener again, to remove it, reaches the same stand-in there. `owner` is the\n * object a method came from, which it's called on.\n */\nconst markFunction = (fn: Function, owner?: object): FunctionMarker => {\n let id = relayedFunctionIds.get(fn);\n if (id === undefined) {\n id = nextFunctionId++;\n relayedFunctionIds.set(fn, id);\n relayedFunctions.set(id, (...args) => fn.apply(owner, args));\n }\n return { __angularLynxCallback: id };\n};\n\n/**\n * Prepares a relayed call's arguments: on the main thread, each function in\n * them, or in a plain object or array in them, becomes a marker that the\n * background thread calls back. Elsewhere the call runs in place, so the\n * arguments are left alone.\n *\n * @param value - The arguments, or one of them.\n * @returns The value to send.\n */\nexport const relayFunctions = (value: unknown): unknown => {\n if (!isMainThread()) return value;\n const relay = (item: unknown, owner?: object): unknown => {\n if (typeof item === 'function') return markFunction(item, owner);\n if (Array.isArray(item)) return item.map((entry) => relay(entry));\n if (isPlainObject(item)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(item)) {\n result[key] = relay(item[key], item);\n }\n return result;\n }\n return item;\n };\n return relay(value);\n};\n\n/**\n * Prepares a JS module for registering from the main thread: its methods,\n * including ones on its prototype such as a class's, become markers bound to\n * it, and its other fields are copied.\n *\n * @param module - The module to register.\n * @returns The value to send.\n */\nexport const relayModuleObject = (module: object): unknown => {\n if (!isMainThread()) return module;\n const result: Record<string, unknown> = {};\n for (\n let source: object | null = module;\n source !== null && source !== Object.prototype;\n source = Object.getPrototypeOf(source)\n ) {\n for (const key of Object.getOwnPropertyNames(source)) {\n if (key === 'constructor' || key in result) continue;\n const value = (module as Record<string, unknown>)[key];\n result[key] =\n typeof value === 'function'\n ? markFunction(value, module)\n : relayFunctions(value);\n }\n }\n return result;\n};\n\n/**\n * Background thread: swaps each function marker for a stand-in that calls\n * the main thread's function, with its arguments copied as JSON. A value\n * without markers comes back as the same object, so a module registered on\n * this thread keeps its identity.\n */\nconst restoreFunctions = (value: unknown): unknown => {\n if (isFunctionMarker(value)) {\n const id = value.__angularLynxCallback;\n let standIn = standIns.get(id);\n if (!standIn) {\n standIn = (...args: unknown[]) => {\n try {\n (lynx as any).getCoreContext().dispatchEvent({\n type: CALLBACK_EVENT,\n data: JSON.stringify({ id, args }),\n });\n } catch {\n // Arguments JSON can't copy, such as a circular object, can't reach\n // the main thread. Native code calling back has nobody to tell.\n }\n };\n standIns.set(id, standIn);\n }\n return standIn;\n }\n if (Array.isArray(value)) {\n const items = value.map(restoreFunctions);\n return items.some((item, i) => item !== value[i]) ? items : value;\n }\n if (isPlainObject(value)) {\n let changed = false;\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(value)) {\n result[key] = restoreFunctions(value[key]);\n changed ||= result[key] !== value[key];\n }\n return changed ? result : value;\n }\n return value;\n};\n\n/**\n * The host's `NativeModules.bridge`, if it has one.\n */\nconst nativeBridge = ():\n | {\n call(\n name: string,\n params: unknown,\n callback: (...args: unknown[]) => void,\n ): void;\n on(name: string, callback: (...args: unknown[]) => void): void;\n }\n | undefined => {\n const bridge =\n typeof NativeModules !== 'undefined' && NativeModules != null\n ? (NativeModules as any).bridge\n : undefined;\n return typeof bridge?.call === 'function' ? bridge : undefined;\n};\n\n/**\n * A native module or JS module by name, or undefined.\n */\nconst findModule = (kind: ModuleKind, name: string): any => {\n if (kind === 'native') {\n return typeof NativeModules !== 'undefined' && NativeModules != null\n ? (NativeModules as any)[name]\n : undefined;\n }\n return typeof lynx !== 'undefined' &&\n typeof (lynx as any).getJSModule === 'function'\n ? (lynx as any).getJSModule(name)\n : undefined;\n};\n\n/** Which registry a relayed module comes from. */\nexport type ModuleKind = 'native' | 'js';\n\nconst handlers = {\n accessibilityAnnounce: (content: string): Promise<void> =>\n new Promise((resolve) =>\n lynxApi('accessibilityAnnounce')({ content }, () => resolve()),\n ),\n\n addFont: (fontFamily: string, src: string): Promise<void> =>\n new Promise((resolve, reject) =>\n lynxApi('addFont')({ 'font-family': fontFamily, src }, (err?: unknown) =>\n err ? reject(err) : resolve(),\n ),\n ),\n\n setObserverFrameRate: (options?: ObserverFrameRateOptions): void =>\n lynxApi('setObserverFrameRate')(options),\n\n // Native Lynx has these on both threads, but web-core only on the background\n // thread, where its exposure module reads `sendEvent` off the argument.\n stopExposure: (options?: { sendEvent: boolean }): void =>\n lynxApi('stopExposure')(options ?? {}),\n\n resumeExposure: (): void => lynxApi('resumeExposure')(),\n\n /**\n * Subscribes on the background thread and sends each change to the main\n * thread, where subscribeSessionStorageFromMainThread() delivers it.\n */\n subscribeSessionStorage: (key: string, relayId: number): void => {\n const listenerId: number = lynxApi('subscribeSessionStorage')(\n key,\n (value: unknown) =>\n (lynx as any).getCoreContext().dispatchEvent({\n type: SESSION_STORAGE_EVENT,\n data: JSON.stringify({ relayId, value }),\n }),\n );\n relayedSubscriptions.set(relayId, { key, listenerId });\n },\n\n unsubscribeSessionStorage: (relayId: number): void => {\n const subscription = relayedSubscriptions.get(relayId);\n if (!subscription) return;\n relayedSubscriptions.delete(relayId);\n lynxApi('unsubscribeSessionStorage')(\n subscription.key,\n subscription.listenerId,\n );\n },\n\n requestResourcePrefetch: (data: unknown): Promise<unknown> =>\n new Promise((resolve) => lynxApi('requestResourcePrefetch')(data, resolve)),\n\n cancelResourcePrefetch: (data: unknown): Promise<unknown> =>\n new Promise((resolve) => lynxApi('cancelResourcePrefetch')(data, resolve)),\n\n /**\n * Calls the host's bridge method and resolves with the first value it\n * passes back. Without a bridge, such as in the web preview, it resolves\n * `undefined`, as LynxNativeModule.call() always has.\n */\n nativeBridgeCall: (name: string, params: unknown): Promise<unknown> => {\n const bridge = nativeBridge();\n if (!bridge) return Promise.resolve(undefined);\n return new Promise((resolve) =>\n bridge.call(name, params, (...args: unknown[]) => resolve(args[0])),\n );\n },\n\n nativeBridgeOn: (name: string, callback: unknown): void => {\n nativeBridge()?.on(\n name,\n restoreFunctions(callback) as (...args: unknown[]) => void,\n );\n },\n\n /**\n * Calls a method of a native module or a JS module. The main thread's\n * module proxies (relayedModule() below) send their calls here.\n */\n callModule: (\n kind: ModuleKind,\n name: string,\n method: string,\n args: unknown[],\n ): unknown => {\n const module = findModule(kind, name);\n const fn = module?.[method];\n if (typeof fn !== 'function') {\n throw new Error(\n `${kind === 'native' ? 'NativeModules' : 'lynx.getJSModule'}: ${name}.${method} is not available`,\n );\n }\n return fn.apply(module, restoreFunctions(args) as unknown[]);\n },\n\n /**\n * Calls a native module method that answers through a callback, passed\n * after `args`, and resolves with the first value it passes back. Unlike a\n * function sent through callModule, the callback stays on this thread, so\n * the call leaves nothing registered on either thread: the storage\n * services make one of these per read and write.\n */\n callNativeModuleAsync: (\n name: string,\n method: string,\n args: unknown[],\n ): Promise<unknown> =>\n new Promise((resolve) => {\n const module = findModule('native', name);\n const fn = module?.[method];\n if (typeof fn !== 'function') {\n throw new Error(`NativeModules: ${name}.${method} is not available`);\n }\n fn.call(module, ...args, (result: unknown) => resolve(result));\n }),\n\n registerJSModule: (name: string, module: unknown): void => {\n lynxApi('registerModule')(name, restoreFunctions(module));\n },\n\n /**\n * The OS version, for LynxSystemInfo on the main thread: native Lynx builds\n * that thread's SystemInfo without one, and the background thread's global\n * has it.\n */\n osVersion: (): string | undefined =>\n typeof SystemInfo !== 'undefined' ? SystemInfo.osVersion : undefined,\n\n /** The main thread's `fetch` (network/fetch.ts) sends its requests here. */\n fetch: (id: number, request: RelayedRequest): Promise<RelayedResponse> =>\n fetchForMainThread(id, request),\n\n abortFetch: (id: number): void => abortFetchForMainThread(id),\n};\n\ntype Handlers = typeof handlers;\ntype HandlerName = keyof Handlers;\n\nconst pending = new Map<\n number,\n { resolve: (value: any) => void; reject: (error: Error) => void }\n>();\nlet nextCallId = 0;\n\n/**\n * Runs a background-only Lynx API, directly on the background thread or relayed\n * from the main thread.\n */\nexport const callOnBackground = <N extends HandlerName>(\n name: N,\n ...args: Parameters<Handlers[N]>\n): Promise<Awaited<ReturnType<Handlers[N]>>> => {\n if (!isMainThread()) {\n try {\n return Promise.resolve(\n (handlers[name] as (...a: unknown[]) => any)(...args),\n );\n } catch (error) {\n return Promise.reject(error);\n }\n }\n return new Promise((resolve, reject) => {\n const id = nextCallId++;\n pending.set(id, { resolve, reject });\n try {\n (lynx as any).getJSContext().dispatchEvent({\n type: CALL_EVENT,\n data: JSON.stringify({ id, name, args }),\n });\n } catch {\n pending.delete(id);\n reject(\n new Error(\n `Can't reach the background thread to call lynx.${name} in this environment`,\n ),\n );\n }\n });\n};\n\n/** Main thread: one proxy per module, so repeated lookups return the same one. */\nconst moduleProxies = new Map<string, object>();\n\n/**\n * Main thread: a stand-in for a native module or JS module, which only the\n * background thread can reach. Each method call runs there and returns a\n * promise of its result, and function arguments are called back here. Reading\n * `then` gives `undefined`, so the proxy isn't mistaken for a promise.\n *\n * @param kind - `'native'` for `NativeModules`, `'js'` for `lynx.getJSModule`.\n * @param name - The module's name.\n * @returns The proxy.\n */\nexport const relayedModule = (kind: ModuleKind, name: string): object => {\n const cacheKey = `${kind}:${name}`;\n let proxy = moduleProxies.get(cacheKey);\n if (!proxy) {\n const methods = new Map<string, (...args: unknown[]) => Promise<unknown>>();\n proxy = new Proxy(\n {},\n {\n get: (_target, method) => {\n if (typeof method !== 'string' || method === 'then') {\n return undefined;\n }\n let call = methods.get(method);\n if (!call) {\n call = (...args: unknown[]) =>\n callOnBackground(\n 'callModule',\n kind,\n name,\n method,\n relayFunctions(args) as unknown[],\n );\n methods.set(method, call);\n }\n return call;\n },\n },\n );\n moduleProxies.set(cacheKey, proxy);\n }\n return proxy;\n};\n\nconst sessionStorageListeners = new Map<number, (value: unknown) => void>();\nlet nextRelayId = 0;\n\n/**\n * Main thread only. Subscribes to a session storage key through the background\n * thread, the only thread that can, and returns the ID to unsubscribe with.\n */\nexport const subscribeSessionStorageFromMainThread = (\n key: string,\n listener: (value: unknown) => void,\n): number => {\n const relayId = nextRelayId++;\n sessionStorageListeners.set(relayId, listener);\n callOnBackground('subscribeSessionStorage', key, relayId).catch(() => {\n // Without a background thread there's nothing to subscribe to. The\n // caller's local listeners still see this thread's own writes.\n sessionStorageListeners.delete(relayId);\n });\n return relayId;\n};\n\nexport const unsubscribeSessionStorageFromMainThread = (\n relayId: number,\n): void => {\n if (!sessionStorageListeners.delete(relayId)) return;\n callOnBackground('unsubscribeSessionStorage', relayId).catch(() => {});\n};\n\nconst installRelay = (): void => {\n if (typeof lynx === 'undefined') return;\n try {\n if (isMainThread()) {\n const context = (lynx as any).getJSContext();\n context.addEventListener(RESULT_EVENT, (event: { data: string }) => {\n const { id, value, error } = JSON.parse(event.data);\n const call = pending.get(id);\n if (!call) return;\n pending.delete(id);\n if (error !== undefined) {\n call.reject(new Error(error));\n } else {\n call.resolve(value);\n }\n });\n context.addEventListener(\n SESSION_STORAGE_EVENT,\n (event: { data: string }) => {\n const { relayId, value } = JSON.parse(event.data);\n sessionStorageListeners.get(relayId)?.(value);\n },\n );\n context.addEventListener(CALLBACK_EVENT, (event: { data: string }) => {\n const { id, args } = JSON.parse(event.data);\n relayedFunctions.get(id)?.(...args);\n });\n return;\n }\n const context = (lynx as any).getCoreContext();\n context.addEventListener(CALL_EVENT, async (event: { data: string }) => {\n const { id, name, args } = JSON.parse(event.data);\n let reply: { id: number; value?: unknown; error?: string };\n try {\n const handler = handlers[name as HandlerName] as\n | ((...a: unknown[]) => unknown)\n | undefined;\n if (!handler) throw new Error(`Unknown background call: ${name}`);\n reply = { id, value: await handler(...args) };\n } catch (error) {\n reply = {\n id,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n let data: string;\n try {\n data = JSON.stringify(reply);\n } catch (error) {\n // A result JSON can't copy, such as a circular object from a native\n // module, would otherwise leave the caller waiting forever.\n // JSON.stringify only throws TypeErrors.\n data = JSON.stringify({\n id,\n error: `The result of ${name} can't be sent to the main thread: ${(error as Error).message}`,\n });\n }\n context.dispatchEvent({ type: RESULT_EVENT, data });\n });\n } catch {\n // The thread contexts may be missing outside a real Lynx host. Calls from\n // the main thread then reject in callOnBackground().\n }\n};\n\ninstallRelay();\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 * The public API of an animation, which `BaseLynxElement.animate()` returns.\n * LynxAnimation uses ES private fields (#element, #count), which brand the\n * class, so a structural type lets other implementations, such as a test\n * double, satisfy it.\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, except for\n * the key a named animation is controlled by (see the constructor).\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 // The string __ElementAnimate knows this animation by (see the constructor).\n readonly #key: string;\n // The DOM Animation web-core started, on web only (see the constructor).\n readonly #webAnimation?: Animation;\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 // __ElementAnimate finds an animation by the string after the operation,\n // and native Lynx and web-core need different strings for a named one\n // (issue #57):\n // - Native starts it under `options.name`, which its animation events\n // report, and PLAY/PAUSE write their string into the element's\n // `animation-name`. So play() and pause() have to pass the name: given\n // the generated id they left a named animation running on iOS and\n // Android. React Lynx always passes the id, so its named animations\n // can't be paused either.\n // - web-core ignores `options.name` and keys one map, shared by every\n // element on the page, by that string. Starting an animation cancels\n // whatever is already under its key, so two elements animating under\n // the same name would cancel each other. The unique id avoids that.\n this.#key = __WEB__ ? this.id : (options.name ?? this.id);\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 this.#key,\n keyframes,\n wireOptions,\n ]);\n\n // web-core's __ElementAnimate forgets an animation the moment it finishes\n // (its `onfinish` drops it from the map it looks names up in), so a later\n // ANIMATION_CANCEL finds nothing and does nothing. On native, cancel still\n // clears a finished animation. The difference shows with fill:'forwards':\n // on web the final frame then pins the property for good, and every\n // inline style set on it afterwards is hidden (a bottom sheet's drag\n // transform, for one). On web the element is a real DOM element and\n // web-core starts the animation with element.animate(), so keep that\n // Animation and cancel it directly. getAnimations() lists an element's\n // script animations in the order they were created, so the last one is\n // the animation just started.\n if (__WEB__) {\n this.#webAnimation = (\n this.#element as unknown as Partial<Pick<Element, 'getAnimations'>>\n )\n .getAnimations?.()\n .at(-1);\n }\n }\n\n play(): void {\n __ElementAnimate(this.#element, [ANIMATION_PLAY, this.#key]);\n }\n\n pause(): void {\n __ElementAnimate(this.#element, [ANIMATION_PAUSE, this.#key]);\n }\n\n cancel(): void {\n __ElementAnimate(this.#element, [ANIMATION_CANCEL, this.#key]);\n // Reaches the animation even after it finished (see the constructor).\n // Canceling an animation web-core already canceled is a no-op.\n this.#webAnimation?.cancel();\n }\n}\n","import type { ElementRef } from '../types/lynx';\nimport {\n LynxAnimation,\n type LynxAnimationOptions,\n} from '../animation/animation';\nimport type { MainThread } from './types';\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 * Measures the element's layout box, by default from the top-left corner of\n * the LynxView. `relativeTo` takes 'screen', or another element's `id`.\n *\n * Not part of the official @lynx-js/types Element interface, but useful for\n * touch tracking. Unlike the DOM's, it's asynchronous: native Lynx gives a\n * main-thread script the layout position only through the\n * `boundingClientRect` UI method. The computed `left` and `top` styles are\n * CSS offsets, often 0, not where the element is.\n */\n getBoundingClientRect(options?: {\n relativeTo?: string;\n }): Promise<MainThread.BoundingClientRect> {\n return this.invoke('boundingClientRect', options).then((rect) => {\n // The UI method also returns the element's id and dataset.\n const { left, top, right, bottom, width, height } =\n rect as MainThread.BoundingClientRect;\n return { left, top, right, bottom, width, height };\n });\n }\n}\n","import { Injectable } from '@angular/core';\nimport { callOnBackground } from '../background-call';\nimport { MainThreadElement } from '../main-thread/main-thread-element';\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()`. Only the background thread's `lynx`\n * has it, and event handlers run on the main thread, so the call goes\n * through the background thread (see background-call.ts).\n */\n announce(content: string): Promise<void> {\n return callOnBackground('accessibilityAnnounce', content);\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 * The main thread's `lynx` has no createSelectorQuery, but it's where event\n * handlers run and where the native elements live, so there the element is\n * found and called directly.\n */\n requestFocus(selector: string): Promise<void> {\n if (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__) {\n const element = new MainThreadElement(__GetPageElement()).querySelector(\n selector,\n );\n if (!element) {\n return Promise.reject(\n new Error(\n `requestAccessibilityFocus: no element matches ${selector}`,\n ),\n );\n }\n return element.invoke('requestAccessibilityFocus').then(() => undefined);\n }\n\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 { Subject } from 'rxjs';\nimport type { GlobalData, InitData } from './data-flow.types';\n\n/**\n * Host data that changes after the page has started. The engine reports each\n * change through a callback it calls by name (see global-callbacks.ts), outside\n * Angular's DI, so the callback stores the new value on `lynx` and publishes it\n * here, and LynxInitData and LynxGlobalData subscribe. Each thread runs its own\n * copy of this module, fed by that thread's callbacks: the main thread's copy\n * is the one that reaches the screen.\n */\nexport const initDataUpdates = new Subject<InitData>();\nexport const globalDataUpdates = new Subject<GlobalData>();\n\nconst asRecord = (data: unknown): Record<string, unknown> =>\n typeof data === 'object' && data !== null\n ? (data as Record<string, unknown>)\n : {};\n\n/**\n * Merges an InitData update into `lynx.__initData`, as React Lynx does, and\n * publishes the result. `reset` starts from an empty object, for a host that\n * resets the data instead of updating it. Always builds a new object, because\n * a signal given the same object again doesn't notify its readers.\n */\nexport const applyInitDataUpdate = (\n data: unknown,\n reset: boolean,\n): InitData => {\n const host = lynx as any;\n const next = {\n ...(reset ? {} : host.__initData),\n ...asRecord(data),\n } as InitData;\n host.__initData = next;\n initDataUpdates.next(next);\n return next;\n};\n\n/**\n * Merges a GlobalData update into `lynx.__globalProps`, as React Lynx does, and\n * publishes the result. The host sends the whole object, so the merge only\n * matters if it ever sends part of one. Builds a new object for the same reason\n * as applyInitDataUpdate().\n */\nexport const applyGlobalDataUpdate = (data: unknown): GlobalData => {\n const next = { ...lynx.__globalProps, ...asRecord(data) } as GlobalData;\n lynx.__globalProps = next as typeof lynx.__globalProps;\n globalDataUpdates.next(next);\n return next;\n};\n","import { DestroyRef, inject, Injectable, signal } from '@angular/core';\nimport type { GlobalData } from './data-flow.types';\nimport { globalDataUpdates } from './host-updates';\n\n@Injectable({ providedIn: 'root' })\nexport class LynxGlobalData {\n // Seeded from lynx.__globalProps at construction time; updated when the host\n // changes it. A host that never sets global props leaves __globalProps\n // undefined, so fall back to an empty object: readers like LynxTheme index\n // into it.\n readonly globalData = signal<GlobalData>(\n ((typeof lynx !== 'undefined' && lynx.__globalProps) || {}) as GlobalData,\n );\n\n constructor() {\n // The engine's update callbacks publish the merged data on each thread\n // (see host-updates.ts), so this works on the main thread, which draws\n // the UI, as well as on the background thread. Unsubscribe when the app\n // is destroyed, so an HMR re-bootstrap doesn't leave the old app listening.\n const subscription = globalDataUpdates.subscribe((data) =>\n this.globalData.set(data),\n );\n inject(DestroyRef).onDestroy(() => subscription.unsubscribe());\n }\n}\n","import {\n computed,\n DestroyRef,\n inject,\n Injectable,\n signal,\n type Signal,\n} from '@angular/core';\nimport { LynxGlobalData } from '../data-flow/global-data';\n\n/**\n * Each setting, by the name of the global prop a host app sends it as, with\n * the media query a browser reports it through.\n */\nconst MEDIA_QUERIES = {\n reduceMotion: '(prefers-reduced-motion: reduce)',\n reduceTransparency: '(prefers-reduced-transparency: reduce)',\n increaseContrast: '(prefers-contrast: more)',\n} as const;\n\ntype Setting = keyof typeof MEDIA_QUERIES;\n\n/**\n * Whether the host app turned a setting on: `true`, or `'true'`, the string\n * Lynx Explorer passes for a query parameter of the bundle URL\n * (`?reduceMotion=true`), which makes the settings easy to try out there.\n */\nconst isOn = (data: Record<string, unknown>, setting: Setting): boolean =>\n data[setting] === true || data[setting] === 'true';\n\n/**\n * The window the page is drawn in, on Lynx for Web: its main thread runs in an\n * iframe while its elements belong to the page, so the user's preferences\n * have to come from the page element's window, not this realm's. Native Lynx\n * has no media queries at all.\n */\nconst pageWindow = (): Window | undefined => {\n if (!__WEB__ || typeof __GetPageElement !== 'function') return undefined;\n const page = __GetPageElement() as unknown as\n | { ownerDocument?: Document }\n | undefined;\n return page?.ownerDocument?.defaultView ?? undefined;\n};\n\n/**\n * One signal per setting that follows the page's media query on the web, and\n * stays `false` elsewhere.\n */\nconst watchMediaQueries = (\n destroyRef: DestroyRef,\n): Record<Setting, Signal<boolean>> => {\n const win = pageWindow();\n const signals = {} as Record<Setting, Signal<boolean>>;\n for (const setting of Object.keys(MEDIA_QUERIES) as Setting[]) {\n const query =\n typeof win?.matchMedia === 'function'\n ? win.matchMedia(MEDIA_QUERIES[setting])\n : undefined;\n const matches = signal(query?.matches ?? false);\n if (query) {\n const update = () => matches.set(query.matches);\n query.addEventListener('change', update);\n destroyRef.onDestroy(() => query.removeEventListener('change', update));\n }\n signals[setting] = matches.asReadonly();\n }\n return signals;\n};\n\n/**\n * The user's accessibility display settings, as signals: Reduce Motion,\n * Reduce Transparency and Increase Contrast.\n *\n * Lynx has no API for them on any platform, so they come from the host app,\n * in its global props, like the theme does: `reduceMotion`,\n * `reduceTransparency` and `increaseContrast`, each `true` when on. The apps\n * `ng build --platform` makes send them, and send them again when the user\n * changes one:\n *\n * - **iOS:** `UIAccessibility.isReduceMotionEnabled`,\n * `isReduceTransparencyEnabled` and `isDarkerSystemColorsEnabled`\n * (Increase Contrast).\n * - **Android:** Remove animations (an animator duration scale of 0) for\n * Reduce Motion, and contrast above standard (Android 14) or high contrast\n * text (Android 16) for Increase Contrast. Android has no Reduce\n * Transparency setting.\n *\n * In the web preview they follow the browser's `prefers-reduced-motion`,\n * `prefers-reduced-transparency` and `prefers-contrast: more` too. Lynx\n * Explorer sends none of them, so they're off there, unless you add them to\n * the bundle URL: `?reduceMotion=true`.\n *\n * iOS 27's Liquid Glass appearance setting (clear or tinted glass) has no\n * public API, so it isn't here. UIKit's glass follows it, and Reduce\n * Transparency and Increase Contrast, by itself.\n *\n * @usageNotes\n * ```typescript\n * const settings = inject(LynxAccessibilitySettings);\n *\n * // Jump instead of sliding when the user asked for less motion.\n * const duration = computed(() => (settings.reduceMotion() ? 0 : 250));\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxAccessibilitySettings {\n readonly #globalData = inject(LynxGlobalData);\n readonly #media = watchMediaQueries(inject(DestroyRef));\n\n /**\n * The user asked for less motion. Replace movement, such as a slide or a\n * bounce, with a fade or an instant change.\n */\n readonly reduceMotion = this.#setting('reduceMotion');\n\n /**\n * The user asked for less transparency. Draw blurred and translucent\n * surfaces opaque.\n */\n readonly reduceTransparency = this.#setting('reduceTransparency');\n\n /**\n * The user asked for more contrast: iOS's Increase Contrast. Strengthen\n * borders and use full-strength text colors.\n */\n readonly increaseContrast = this.#setting('increaseContrast');\n\n #setting(setting: Setting): Signal<boolean> {\n return computed(\n () =>\n isOn(\n this.#globalData.globalData() as Record<string, unknown>,\n setting,\n ) || this.#media[setting](),\n );\n }\n}\n","import { Injectable } from '@angular/core';\nimport type { CommonPerformance } from '@lynx-js/types';\nimport type { LynxTraceOptions } from './devtools.types';\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 * Unlike the `LynxDevTools` counters, the calls aren't gated by `__PROFILE__`,\n * so they stay in production builds. A trace is worth recording from the build\n * you ship, without development mode's extra work in it. They cost little\n * there: release builds of the Lynx engine compile tracing out, so each call\n * returns at once.\n *\n * @usageNotes\n * ```typescript\n * const perf = inject(LynxPerformance);\n *\n * perf.profileStart('MyComponent::render', { args: { itemCount: '42' } });\n * // ... do work ...\n * perf.profileEnd();\n *\n * perf.profileMark('dataLoaded', { args: { source: 'cache' } });\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxPerformance {\n // Partial: each method is checked before it's called, in case an engine\n // lacks it.\n #perf: Partial<CommonPerformance> | null = this.#resolve();\n\n #resolve(): Partial<CommonPerformance> | 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(name: string, options?: LynxTraceOptions): 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(name: string, options?: LynxTraceOptions): 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","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\n/**\n * The current time in ms. Native Lynx has no `performance` global on either\n * thread; the web preview has one, and it times below a millisecond.\n * `Date.now()` is everywhere.\n */\nconst now = (): number =>\n typeof performance !== 'undefined' && typeof performance.now === 'function'\n ? performance.now()\n : Date.now();\n\n// One start time per change-detection cycle in progress. A stack rather than a\n// single value because cycles nest: a `detectChanges()` call during a tick\n// runs its own begin()/end() pair inside the tick's, and the tick's duration\n// must not start at the inner one's start.\nconst cdStartTimes: number[] = [];\n\n/**\n * Starts timing a change-detection cycle. The renderer factory calls it from\n * `begin()`, and `endCdTiming()` from `end()`.\n */\nexport const startCdTiming = (): void => {\n cdStartTimes.push(now());\n};\n\n/**\n * Stops timing the innermost change-detection cycle in progress, and records\n * its duration in `devStats.lastCdDurationMs`.\n */\nexport const endCdTiming = (): void => {\n const start = cdStartTimes.pop();\n if (start !== undefined) {\n devStats.lastCdDurationMs = now() - start;\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 in development builds, where the build plugin sets\n * `__PROFILE__` to true. In production builds, counters are never incremented\n * (the instrumentation code is dead-code-eliminated), so all values remain\n * 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. The engine runs the default processor\n * on the InitData before passing it to renderPage, so its result is what\n * LynxInitData starts with.\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 { DestroyRef, inject, Injectable, signal } from '@angular/core';\nimport type { InitData } from './data-flow.types';\nimport { initDataUpdates } from './host-updates';\n\n@Injectable({ providedIn: 'root' })\nexport class LynxInitData {\n // Seeded from lynx.__initData at construction time; updated when the host sends new data.\n // The runtime sets __initData from renderPage on the main thread and from the\n // loadCard params on the background thread (see global-callbacks.ts). Outside\n // Lynx, or before either has run, fall back to an empty object so reads like\n // initData().userId don't throw. __initData is not declared in @lynx-js/types,\n // so we access it via any.\n readonly initData = signal<InitData>(\n ((typeof lynx !== 'undefined' && (lynx as any).__initData) ||\n {}) as InitData,\n );\n\n constructor() {\n // The engine's update callbacks publish the merged data on each thread\n // (see host-updates.ts), so this works on the main thread, which draws\n // the UI, as well as on the background thread. Unsubscribe when the app\n // is destroyed, so an HMR re-bootstrap doesn't leave the old app listening.\n const subscription = initDataUpdates.subscribe((data) =>\n this.initData.set(data),\n );\n inject(DestroyRef).onDestroy(() => subscription.unsubscribe());\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 { Subject } from 'rxjs';\nimport type { GlobalExposureEvent } from './exposure.types';\n\nexport type GlobalExposureBatch = {\n type: 'exposure' | 'disexposure';\n events: GlobalExposureEvent;\n};\n\n/**\n * Every batch of global exposure events, on whichever thread this module runs.\n * LynxGlobalExposure subscribes.\n */\nexport const globalExposureBatches = new Subject<GlobalExposureBatch>();\n\nconst FORWARD_EVENT = 'AngularLynx.GlobalExposure';\n\n/**\n * Lynx reports global exposure (elements with an `exposure-id` entering or\n * leaving the screen) only on the background thread, through\n * GlobalEventEmitter. The main thread draws the UI, so its LynxGlobalExposure\n * signals never changed. The background thread now publishes each batch locally\n * and forwards it to the main thread, through the same cross-thread event\n * channel as the worklet RPC in global-callbacks.ts: the background thread\n * dispatches on getCoreContext(), and the main thread listens on getJSContext().\n *\n * Installed once at module load rather than by LynxGlobalExposure, because a\n * component the router creates after a tap exists only on the main thread, so\n * the background thread might never construct the service.\n */\nconst installGlobalExposureBridge = (): void => {\n if (typeof lynx === 'undefined') return;\n try {\n if (__MAIN_THREAD__) {\n (lynx as any)\n .getJSContext?.()\n ?.addEventListener(FORWARD_EVENT, (event: { data: string }) =>\n globalExposureBatches.next(JSON.parse(event.data)),\n );\n return;\n }\n const emitter = lynx.getJSModule?.('GlobalEventEmitter');\n if (!emitter?.addListener) return;\n for (const type of ['exposure', 'disexposure'] as const) {\n emitter.addListener(type, (...args: unknown[]) => {\n const batch = { type, events: args[0] as GlobalExposureEvent };\n globalExposureBatches.next(batch);\n (lynx as any).getCoreContext?.()?.dispatchEvent({\n type: FORWARD_EVENT,\n data: JSON.stringify(batch),\n });\n });\n }\n } catch {\n // The thread contexts and GlobalEventEmitter may be missing outside a real\n // Lynx host. Global exposure then simply never fires.\n }\n};\n\ninstallGlobalExposureBridge();\n","import { DestroyRef, inject, Injectable, signal } from '@angular/core';\nimport { callOnBackground } from '../background-call';\nimport { globalExposureBatches } from './global-exposure-bridge';\nimport type {\n GlobalExposureEvent,\n ObserverFrameRateOptions,\n} from './exposure.types';\n\n@Injectable({ providedIn: 'root' })\nexport class LynxGlobalExposure {\n // The most recent batch of elements that came on screen. Lynx batches them\n // and reports them through GlobalEventEmitter's 'exposure' event.\n readonly exposures = signal<GlobalExposureEvent>([]);\n\n // The most recent batch of elements that left the screen ('disexposure').\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 // Lynx reports these events only on the background thread. The bridge\n // forwards them to the main thread, which draws the UI, and publishes them\n // on both (see global-exposure-bridge.ts). Unsubscribe when the app is\n // destroyed, so an HMR re-bootstrap doesn't leave the old app listening.\n const subscription = globalExposureBatches.subscribe(({ type, events }) =>\n (type === 'exposure' ? this.exposures : this.disexposures).set(events),\n );\n inject(DestroyRef).onDestroy(() => subscription.unsubscribe());\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 if (typeof lynx.stopExposure === 'function') {\n lynx.stopExposure(options);\n } else {\n this.#relay(callOnBackground('stopExposure', options));\n }\n this.active.set(false);\n }\n\n resumeExposure(): void {\n if (typeof lynx === 'undefined') return;\n if (typeof lynx.resumeExposure === 'function') {\n lynx.resumeExposure();\n } else {\n this.#relay(callOnBackground('resumeExposure'));\n }\n this.active.set(true);\n }\n\n /**\n * Sets how often Lynx checks for exposure. Only the background thread's\n * `lynx` has setObserverFrameRate, so a call from an event handler, which\n * runs on the main thread, goes through the background thread (see\n * background-call.ts). Resolves once it's applied.\n */\n setObserverFrameRate(options?: ObserverFrameRateOptions): Promise<void> {\n if (typeof lynx === 'undefined') return Promise.resolve();\n return callOnBackground('setObserverFrameRate', options);\n }\n\n /**\n * Web-core's main thread has no stopExposure or resumeExposure, so there the\n * call goes through the background thread (see background-call.ts). These\n * methods return nothing, so report a failed relay rather than leave an\n * unhandled rejection.\n */\n #relay(call: Promise<void>): void {\n call.catch((error: unknown) => console.error(error));\n }\n}\n","import { computed, Injectable, signal } from '@angular/core';\nimport { callOnBackground } from '../background-call';\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 * Only the background thread's `lynx` has addFont, so a call from an event\n * handler, which runs on the main thread, goes through the background thread\n * (see background-call.ts).\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 // Any failure, including addFont itself being missing, must leave the\n // 'loading' state and the pending cache, so a later call can try again.\n const promise = callOnBackground('addFont', fontFamily, src).then(\n () => {\n this.#updateEntry(fontFamily, { fontFamily, src, status: 'loaded' });\n this.#pending.delete(fontFamily);\n },\n (err: unknown) => {\n const error = err instanceof Error ? err : new Error(String(err));\n this.#updateEntry(fontFamily, {\n fontFamily,\n src,\n status: 'error',\n error,\n });\n this.#pending.delete(fontFamily);\n throw error;\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 { type Type, ɵɵreplaceMetadata } from '@angular/core';\nimport { isMainThread } from '../background-call';\n\n/**\n * The parts of webpack's `module.hot` API that {@link ɵhmrAccept} uses.\n */\nexport type HotModule = {\n accept(): void;\n dispose(callback: (data: Record<string, unknown>) => void): void;\n invalidate(): void;\n /** What the module's previous version passed to its dispose handlers. */\n data?: Record<string, unknown>;\n};\n\n/**\n * What one version of a module hands the next through `hot.data`.\n */\ntype ModuleVersion = {\n /** The component classes the app renders, in declaration order. */\n components: Type<unknown>[];\n signature: string;\n code: string;\n /**\n * Set when this version passed the update on to the modules that import it.\n * The update then re-runs the module once more, as part of re-running\n * them, and that run must not pass it on again.\n */\n invalidated: boolean;\n};\n\nconst DATA_KEY = 'angularLynx';\n\n/**\n * Takes a hot update of a module that defines components. The build plugin\n * adds a call to the end of each such module in a development build, which\n * reassigns the module's component classes to what it returns.\n *\n * On the main thread, where the app runs, a new version of the module either\n * updates the running app in place or passes the update on:\n *\n * - **Only a template or stylesheet changed** (the source `signature`, which\n * leaves those out, is the same, and the compiled `code` isn't): each\n * component's new definition replaces the old one with Angular's\n * `ɵɵreplaceMetadata()`, which Angular's own dev server uses for the same\n * edits. It re-renders every view of the component in place and keeps the\n * component instances, so their state survives. The module's bindings are\n * pointed back at the old classes, so every module keeps using the one\n * class the app's instances and injectors know.\n * - **Anything else changed**, such as the class, an import, or a module this\n * one imports: the update can't be applied to the running instances, so\n * `hot.invalidate()` passes it on to the modules that import this one, up\n * to the app's entry, which bootstraps the app again (see\n * `bootstrapApplication`).\n *\n * The background thread runs no Angular, only the module-level code that\n * registers background functions. It accepts every version, which re-runs\n * the module and registers them again.\n *\n * @param hot - The module's `import.meta.webpackHot`.\n * @param components - The component classes this version of the module defines.\n * @param signature - A hash of the module's source without its components'\n * templates and styles.\n * @param code - A hash of the module's compiled code.\n * @returns The classes the module should use from now on.\n */\nexport const ɵhmrAccept = (\n hot: HotModule,\n components: Type<unknown>[],\n signature: string,\n code: string,\n): Type<unknown>[] => {\n hot.accept();\n if (!isMainThread()) return components;\n\n const previous = hot.data?.[DATA_KEY] as ModuleVersion | undefined;\n let live = components;\n let invalidated = false;\n if (previous && !previous.invalidated) {\n if (\n previous.code !== code &&\n previous.signature === signature &&\n previous.components.length === components.length\n ) {\n try {\n previous.components.forEach((type, index) =>\n replaceComponent(type, components[index]),\n );\n live = previous.components;\n } catch (error) {\n // A template that throws when it renders, for example. Re-bootstrapping\n // from the entry recovers, or reports the error in the app's own way.\n console.error('[HMR] Could not update the component in place:', error);\n invalidated = true;\n }\n } else {\n invalidated = true;\n }\n }\n\n hot.dispose((data) => {\n data[DATA_KEY] = {\n components: live,\n signature,\n code,\n invalidated,\n } satisfies ModuleVersion;\n });\n if (invalidated) hot.invalidate();\n return live;\n};\n\n/**\n * Swaps the component definition of `current` for `next`'s, and re-renders\n * every view of the component. `ɵɵreplaceMetadata()` merges the definitions\n * in place, keeping the old one's `type`, so the views it creates from now on\n * still instantiate `current`.\n */\nconst replaceComponent = (\n current: Type<unknown>,\n next: Type<unknown>,\n): void => {\n // The merge also keeps the old definition's dependencies, because Angular's\n // own update modules can't import them. Here the new definition comes from\n // the module's new version, whose dependencies are current: a component it\n // uses may have been re-run by the same update, as a new class. Copying them\n // onto the old definition first makes the merge keep the new ones.\n const currentDef = (current as any).ɵcmp;\n const nextDef = (next as any).ɵcmp;\n currentDef.directiveDefs = nextDef.directiveDefs;\n currentDef.pipeDefs = nextDef.pipeDefs;\n ɵɵreplaceMetadata(\n current,\n (type) => {\n (type as any).ɵcmp = (next as any).ɵcmp;\n },\n [],\n [],\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 * The app's own locale: `sourceLocale` from angular.json, which the build\n * injects as `__LYNX_SOURCE_LOCALE__`, or `'en-US'` without one.\n */\nexport const getSourceLocale = (): string =>\n typeof __LYNX_SOURCE_LOCALE__ !== 'undefined'\n ? __LYNX_SOURCE_LOCALE__\n : 'en-US';\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 return value ?? getSourceLocale();\n });\n}\n","import { getLocaleId } from '@angular/common';\nimport {\n type EnvironmentProviders,\n inject,\n LOCALE_ID,\n makeEnvironmentProviders,\n} from '@angular/core';\nimport { getSourceLocale, LynxLocale } from './lynx-locale';\n\n/**\n * Whether Angular has locale data for `locale`, or for its language (`fr`\n * for `fr-CA`). Its pipes and plural rules throw without it.\n */\nconst hasLocaleData = (locale: string): boolean => {\n try {\n // Throws NG0701 when there's none. Deprecated in favor of Intl, which\n // Lynx's JavaScript engine doesn't have; Angular's pipes still use it.\n getLocaleId(locale);\n return true;\n } catch {\n return false;\n }\n};\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 * The apps that `ng build --platform` makes send the phone's language, which\n * the app may not support. When Angular has no locale data for it (see\n * `registerLocaleData()`), `LOCALE_ID` is the app's source locale instead, as\n * a native app shows its own language on a phone set to one it lacks.\n * Otherwise Angular's date and number pipes would throw.\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: () => {\n const locale = inject(LynxLocale).locale();\n const source = getSourceLocale();\n if (locale === source || hasLocaleData(locale)) {\n return locale;\n }\n console.warn(\n `provideLocale(): Angular has no locale data for \"${locale}\", so LOCALE_ID is \"${source}\". Register it with registerLocaleData() to format dates and numbers for it.`,\n );\n return source;\n },\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 * Starts as `{ enabled: true }`, like React Lynx's gesture-runtime, so every\n * gesture sends a config, even one with no options of its own (Fling, Pinch,\n * Rotation). Gestures whose native handler reads options seed the rest of\n * their defaults too: once a config is present, iOS reads each key it leaves\n * out as `0` (see ./const).\n */\n _config: Record<string, unknown> = { enabled: true };\n /**\n * @internal\n */\n _waitFor: BaseGesture[] = [];\n /**\n * @internal\n */\n _simultaneousWith: BaseGesture[] = [];\n /**\n * @internal\n */\n _continueWith: BaseGesture[] = [];\n\n /**\n * Fires when the gesture starts tracking a touch, before it's recognized:\n * at touch-down for most gestures, and when the finger lifts for a fling.\n *\n * A continuous gesture doesn't need one for its `onStart` and `onEnd` to\n * fire. LynxGestureDetector registers an empty `onBegin` when you don't, since\n * Lynx's native handlers skip those callbacks without it. See\n * gesture-detector.ts.\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 /**\n * ⚠️ Not read by Lynx's native gesture handlers yet (as of Lynx 4.1, no\n * handler looks up `enabled`), so a disabled gesture still fires on a\n * device. Unbind the gesture from `[lynxGesture]` to turn it off. Kept for\n * API parity with Lynx's gesture-runtime.\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","import { ContinuousGesture } from './base-gesture';\nimport {\n type FlingGestureEvent,\n type FlingDirection,\n GestureType,\n} from './types';\n\n/**\n * Lynx's fling follows the momentum of a drag after the finger lifts: `onBegin`\n * fires on release, `onUpdate` on every frame (with `deltaX`/`deltaY` in the\n * params), and `onEnd` when it stops. Lynx starts that fling in its BEGAN\n * state and never activates it, so `onStart` doesn't fire\n * (LynxFlingGestureHandler.m / FlingGestureHandler.java). Lynx also flings only\n * the element that won the touch, and a fling ignores the touch until the\n * finger lifts, so it needs a pan on the same element (`Gesture.Simultaneous`).\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 * ⚠️ Not read by Lynx's native fling handlers yet: as of Lynx 4.1, iOS's\n * `handleConfigMap` is a TODO and Android's is empty, so every fling fires,\n * in any direction. Kept for API parity with Lynx's gesture-runtime.\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 * ⚠️ Not read by Lynx's native fling handlers yet (see `direction`).\n */\n numberOfPointers(count: number): this {\n this._config['numberOfPointers'] = count;\n return this;\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","/**\n * The id the page gets on Android, so that every `blur-view` can name the\n * page as the view it blurs (`android-capture-target`).\n *\n * Android's blur-view isn't a real backdrop blur. It redraws one ancestor view\n * into a bitmap and blurs that, and while it redraws, every blur-view in that\n * ancestor skips drawing itself (so it doesn't blur its own output). Left to\n * itself, it picks the nearest ancestor that is `overflow: hidden` or contains\n * it. For a blur-view inside another blur-view, such as a glass shape in a\n * `glass-container` or a button on a frosted panel, that ancestor is the outer\n * blur-view: the redraw holds nothing, and the inner blur-view shows nothing.\n * Redrawing the page instead blurs what is on screen behind the blur-view,\n * which is what iOS does. Only the blur-view's own area is redrawn.\n */\nexport const ANDROID_BLUR_CAPTURE_TARGET = 'angular-lynx-page';\n\n/**\n * Whether this is Lynx's Android renderer. On the native main thread, where\n * elements are created, there is no global `SystemInfo`, only\n * `lynx.SystemInfo`; the background thread and web have the global.\n */\nexport const isAndroid = (): boolean => {\n const info =\n (typeof lynx !== 'undefined'\n ? (lynx as { SystemInfo?: { platform?: string } }).SystemInfo\n : undefined) ??\n (typeof SystemInfo !== 'undefined' ? SystemInfo : undefined);\n return info?.platform === 'Android';\n};\n","import type { ElementRef } from '../../types/lynx';\nimport {\n ANDROID_BLUR_CAPTURE_TARGET,\n isAndroid,\n} from '../android-blur-capture';\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 *\n * Lynx for Web's `blur-view` only implements `blur-radius` and doesn't lay its\n * children out like a view, so on web `attachWebGlass` adds both.\n *\n * On Android it blurs the page (see ANDROID_BLUR_CAPTURE_TARGET), so a\n * blur-view inside another one still shows its backdrop. An app's own\n * `android-capture-target` replaces this, and an empty one restores Android's\n * own choice.\n */\nexport const createBlurViewElement = (pageId: number): ElementRef => {\n const element = __CreateElement('blur-view', pageId);\n if (!__WEB__ && isAndroid()) {\n __SetAttribute(\n element,\n 'android-capture-target',\n ANDROID_BLUR_CAPTURE_TARGET,\n );\n }\n // `__WEB__` is a compile-time define: on native the bundler drops this\n // branch before it follows the import, so none of the WebGL code ships\n // there. A static import wouldn't do: the minifier can't prove the glass\n // classes side-effect free once they're compiled for the main thread, so it\n // would keep them. On web the build inlines the import, and the glass\n // attaches a microtask after the element is created, before it's on screen.\n // Only the main thread draws; web's background thread never gets here with\n // a real element, but `__MAIN_THREAD__` keeps it from loading the module.\n if (__WEB__ && __MAIN_THREAD__) {\n import('../../web-glass/web-glass')\n .then(({ attachWebGlass }) => attachWebGlass(element))\n .catch(() => {\n // Glass is decoration: without its module the blur fallback stays.\n });\n }\n return element;\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\n/**\n * No defaults to set: like React Lynx, an `<image>` starts with Lynx's own\n * `mode`, `scaleToFill`, which iOS, Android and the web all share (and which\n * matches the web's `object-fit: fill`). Setting a different one would have to\n * go through `__SetAttribute`: `__SetConfig` only stores a table for\n * `__GetConfig`, and never reaches the native image or `x-image`.\n */\nexport const createImageElement = (pageId: number): ElementRef => {\n return __CreateImage(pageId);\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 * Lets a `<textarea>` on Lynx for Web take a `z-index`, as an `<input>` does.\n *\n * web-elements draws both as a host with `display: contents` (`<x-input>`,\n * `<x-textarea>`) around the browser's own field, inside a `<form>` that's\n * `display: contents` too. A host without a box ignores `z-index`, so\n * web-elements passes it down: its `x-input` rule makes both the form and the\n * field inherit `z-index`, and the field, a flex item of the element's\n * parent, stacks by it. Its `x-textarea` rules leave `z-index` out (still in\n * web-elements 0.12.16). So a textarea's `z-index`\n * did nothing on the web, and a positioned sibling drawn after it covered it:\n * ui-textarea's transparent focus ring took every click, and no textarea in\n * the Dolan docs could be typed in.\n *\n * Like the blur view's layout fix (web-glass/blur-view-layout.ts), the rule\n * goes in a `<style>` in the element's own shadow root: Lynx owns its `class`\n * and `style` attributes. It only inherits, so a textarea without a\n * `z-index` stacks as before.\n */\nexport const TEXTAREA_STACKING_CSS = 'form,textarea{z-index:inherit}';\n\n/**\n * Applies {@link TEXTAREA_STACKING_CSS} to a `<textarea>` web-core just\n * created. web-elements attaches the shadow root in the constructor, so it's\n * already there.\n */\nexport const stackWebTextarea = (element: ElementRef): void => {\n const node = element as Partial<HTMLElement>;\n const root = node.shadowRoot;\n if (!root) return;\n const style = root.ownerDocument.createElement('style');\n style.textContent = TEXTAREA_STACKING_CSS;\n root.appendChild(style);\n};\n","import type { ElementRef } from '../../types/lynx';\nimport { stackWebTextarea } from '../web-textarea';\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 *\n * No default styles, as in React Lynx: a field is one line of text tall on\n * every platform (iOS and Android measure it from the font), and it has no\n * border. Inline defaults would beat the app's classes, so `h-[120px]` or\n * `border-zinc-200` on an `<input>` would never apply.\n *\n * On Lynx for Web a textarea also needs web-elements' `z-index` handling for\n * inputs (see web-textarea.ts). `__WEB__` is a compile-time define, so native\n * bundles drop the call; only the main thread creates real elements.\n */\nexport const createInputElement = (\n tag: 'input' | 'textarea',\n pageId: number,\n): ElementRef => {\n const element = __CreateElement(tag, pageId);\n if (__WEB__ && __MAIN_THREAD__ && tag === 'textarea') {\n stackWebTextarea(element);\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 { isAndroid } from './android-blur-capture';\n\n/**\n * The CSS variables that the build plugin's `blur-view` rule reads (its\n * `blur-view.css`, which only the native bundle gets):\n *\n * blur-view {\n * background-color: var(--angular-lynx-blur-background, transparent);\n * background-image: var(--angular-lynx-blur-background-image, none);\n * box-shadow: var(--angular-lynx-blur-box-shadow, none);\n * }\n *\n * Lynx implements `blur-effect` and the `glass-*` attributes on iOS only, so\n * on Android every blur-view is a plain Gaussian blur. Android's BlurView draws\n * the blurred backdrop first and then the view's own background and children,\n * so a translucent background on top approximates iOS's materials, as the web\n * build does in glass-host-style.ts.\n *\n * The runtime can't set that background inline: an inline style beats the\n * app's classes (`bg-white/30`), and the runtime can't tell which classes set\n * one. So it sets only these variables inline, and the rule above uses them.\n * A type selector loses to any class, id or inline style the app sets, so the\n * app's own background or shadow still wins.\n *\n * Every Android blur-view sets all three variables, `transparent` and `none`\n * when it has no material. CSS variables inherit, so a blur-view inside a `dark`\n * panel would otherwise take the panel's tint.\n */\nexport const BLUR_BACKGROUND_VARIABLE = '--angular-lynx-blur-background';\nexport const BLUR_BACKGROUND_IMAGE_VARIABLE =\n '--angular-lynx-blur-background-image';\nexport const BLUR_BOX_SHADOW_VARIABLE = '--angular-lynx-blur-box-shadow';\n\n/** The attributes the approximation depends on. */\nexport const BLUR_MATERIAL_ATTRIBUTES: ReadonlySet<string> = new Set([\n 'blur-effect',\n 'blur-radius',\n 'glass-style',\n 'glass-tint-color',\n]);\n\n/**\n * The tint each material puts over the blur. Fitted to the iOS Simulator's\n * pixels in the element-blur-view example: `extra-light` washes the backdrop\n * with white and `dark` with black, the same values as on web. iOS's `light`\n * brightens and saturates the backdrop. Web does that with `brightness()`,\n * which Android's blur-view can't apply to the backdrop, so here a white\n * gives it the same lightness, though paler.\n */\nconst MATERIAL_BACKGROUNDS: Readonly<Record<string, string>> = {\n light: 'rgba(255, 255, 255, 0.3)',\n 'extra-light': 'rgba(255, 255, 255, 0.75)',\n dark: 'rgba(0, 0, 0, 0.6)',\n};\n\n/**\n * A glass shape's frosted look: a white sheen with `glass-tint-color` over\n * it, and a rim, like iOS's glass without the refraction. iOS lightens what's\n * behind the glass before it tints it, so the tint goes on the sheen, as a\n * background image, rather than replacing it. `clear` glass is barely\n * lightened. Fitted to the same example as the materials.\n *\n * The rim is a bright top edge and a faint dark outline, which is what keeps\n * iOS's glass visible over white. Inset shadows draw it without changing the\n * layout, as a border would.\n */\nconst GLASS_SHEEN = 'rgba(255, 255, 255, 0.3)';\nconst CLEAR_GLASS_SHEEN = 'rgba(255, 255, 255, 0.1)';\nconst GLASS_RIM =\n 'inset 0 1px 0 rgba(255, 255, 255, 0.5), inset 0 0 0 1px rgba(0, 0, 0, 0.12)';\n\n/**\n * Whether blur-views get the approximation: only on Android's native\n * renderer. iOS draws the real materials, and web has its own (see web-glass).\n */\nexport const usesAndroidBlurMaterials = (): boolean => !__WEB__ && isAndroid();\n\nconst declarations = (\n background: string,\n { image = 'none', boxShadow = 'none' } = {},\n): string =>\n `${BLUR_BACKGROUND_VARIABLE}: ${background}; ` +\n `${BLUR_BACKGROUND_IMAGE_VARIABLE}: ${image}; ` +\n `${BLUR_BOX_SHADOW_VARIABLE}: ${boxShadow}`;\n\n/**\n * The inline declarations that give a blur-view with `attrs` its material on\n * Android. Like on iOS, a material needs a blur radius, while glass doesn't,\n * and a `glass-container` draws nothing of its own.\n */\nexport const androidBlurMaterialStyle = (\n attrs: ReadonlyMap<string, unknown>,\n): string => {\n const effect = attrs.get('blur-effect') ?? 'light';\n if (effect === 'glass') {\n const tint = attrs.get('glass-tint-color');\n return declarations(\n attrs.get('glass-style') === 'clear' ? CLEAR_GLASS_SHEEN : GLASS_SHEEN,\n {\n // A one-color gradient is how CSS layers a color over a background\n // color.\n image:\n typeof tint === 'string' && tint !== '' && tint !== 'transparent'\n ? `linear-gradient(${tint}, ${tint})`\n : 'none',\n boxShadow: GLASS_RIM,\n },\n );\n }\n if (\n effect === 'glass-container' ||\n !parseFloat(String(attrs.get('blur-radius') ?? ''))\n ) {\n return declarations('transparent');\n }\n // iOS falls back to `light` for an effect it doesn't know.\n return declarations(\n MATERIAL_BACKGROUNDS[String(effect)] ?? MATERIAL_BACKGROUNDS['light'],\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\n/**\n * Set by a hot update's re-bootstrap (see `bootstrapApplication`), so the next\n * root element takes over the page the old app rendered into rather than\n * creating one (see `LynxDocument.createRootElement`). Only a re-bootstrap\n * may: anything else that creates a new app, such as each test's `render()`,\n * runs in a fresh Lynx environment, where the page this module remembers is\n * gone.\n */\nlet handingOverPage = false;\n\nexport const handOverPageToNextApp = (): void => {\n handingOverPage = true;\n};\n\n/**\n * Whether the next app takes over the current page. Reading it clears it.\n */\nexport const takePageHandOver = (): boolean => {\n const handing = handingOverPage;\n handingOverPage = false;\n return handing;\n};\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","/**\n * Keeps `<svg content>` strings parseable by Lynx's native SVG engine.\n *\n * ServalSVG, which draws `<svg>` on iOS (and in Lynx's C++ SVG core generally),\n * parses `stroke-dasharray` with a loop that only advances while it's reading a\n * number. Any other token, such as `none`, a unit like `4px`, or `inherit`,\n * leaves it stuck on the same character forever. Worse, the parse runs on one\n * serial queue shared by every `<svg>` in the process, so a single such\n * attribute (TanStack Charts writes `stroke-dasharray=\"none\"` on its bars)\n * blanks every icon and chart in the app until it's killed, with no error.\n *\n * The rewrite keeps what ServalSVG can draw: bare numbers, and `px` lengths,\n * which equal user units in SVG. Anything else is dropped, which on native is\n * the only way to get a drawing at all. `none` is the default anyway; a value\n * that can't be resolved here (`%`, `em`) would have hung the engine.\n */\n\nconst DASHARRAY_ATTRIBUTE =\n /(\\s)stroke-dasharray\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)')/g;\n// A declaration inside an inline `style=\"…\"` (ServalSVG reads those too).\nconst DASHARRAY_DECLARATION = /(^|[;\"'\\s])stroke-dasharray\\s*:\\s*([^;\"']*);?/g;\nconst DASH_LENGTH = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:e[+-]?\\d+)?(?:px)?$/i;\n\n/**\n * Returns the dash lengths as a space-separated list of bare numbers, or\n * `null` when any part of the value isn't a plain length.\n */\nexport const normalizeDashArray = (value: string): string | null => {\n const tokens = value\n .trim()\n .split(/[\\s,]+/)\n .filter((token) => token.length > 0);\n if (tokens.length === 0 || !tokens.every((t) => DASH_LENGTH.test(t))) {\n return null;\n }\n return tokens.map((token) => token.replace(/px$/i, '')).join(' ');\n};\n\nexport const sanitizeSvgContent = (content: string): string => {\n // Most SVG (icons) has no dash arrays: skip the regex work entirely.\n if (!content.includes('stroke-dasharray')) return content;\n return content\n .replace(\n DASHARRAY_ATTRIBUTE,\n (_match, space: string, double?: string, single?: string) => {\n // The pattern matches one quote style or the other, so one is set.\n const normalized = normalizeDashArray((double ?? single)!);\n return normalized === null\n ? ''\n : `${space}stroke-dasharray=\"${normalized}\"`;\n },\n )\n .replace(DASHARRAY_DECLARATION, (_match, before: string, value: string) => {\n const normalized = normalizeDashArray(value);\n return normalized === null\n ? before\n : `${before}stroke-dasharray:${normalized};`;\n });\n};\n","/**\n * Long presses on Lynx for Web, which never fires `longpress`.\n *\n * Native Lynx recognizes a long press itself and fires `longpress` instead\n * of `tap` when a finger stays down. Lynx for Web's event handling has no\n * recognizer for it (`@lynx-js/web-core` passes DOM events through and maps\n * `click` to `tap`, and nothing else), so `(bindlongpress)` never ran in the\n * web preview: a long press was a tap. LynxElement recognizes one from the\n * element's touch and mouse events instead (see #listenForWebLongPress).\n */\n\n/**\n * How long a press is held before it's a long press, in ms: iOS's default\n * (`UILongPressGestureRecognizer.minimumPressDuration`), close to Android's.\n */\nexport const LONG_PRESS_DURATION = 500;\n\n/**\n * How far a press can move, in px, and still become a long press. Further,\n * it's a drag or a scroll.\n */\nconst LONG_PRESS_SLOP = 10;\n\n/**\n * How long after a long press ends the tap that follows is dropped, in ms.\n * The browser sends `click`, which web-core turns into `tap`, right after the\n * finger or the mouse button comes up, where native Lynx sends no tap at all.\n */\nconst TAP_GRACE = 300;\n\n/** Whether taps are dropped now (see dropsTap). */\nlet tapsDropped = false;\n\n/**\n * Counts long presses, so that the end of an earlier one can't let taps\n * through again during a later one.\n */\nlet longPresses = 0;\n\n/**\n * Whether a tap now ends a long press, and so shouldn't run: from the moment\n * a long press fires until just after it ends. The browser's `click` goes to\n * whatever was under the pointer, so it's dropped wherever it lands.\n */\nexport const dropsTap = (): boolean => tapsDropped;\n\n/** Where a press is, in the `<lynx-view>`'s pixels. */\nexport type LongPressPoint = { readonly x: number; readonly y: number };\n\n/**\n * Where a web-core touch or mouse event happened. A touch event has the\n * first touch's position in `detail`; a mouse event has it on the event, and\n * its `detail` is the DOM's click count.\n */\nconst pointOf = (event: {\n readonly detail?: unknown;\n readonly x?: number;\n readonly y?: number;\n}): LongPressPoint => {\n const { x = 0, y = 0 } =\n typeof event.detail === 'object' && event.detail !== null\n ? (event.detail as LongPressPoint)\n : event;\n return { x, y };\n};\n\n/**\n * Recognizes long presses from one element's touch and mouse events, and\n * calls `fire` with where the press is when one has lasted\n * LONG_PRESS_DURATION without moving away.\n */\nexport class WebLongPress {\n readonly #fire: (point: LongPressPoint) => void;\n #timer: ReturnType<typeof setTimeout> | undefined;\n #start: LongPressPoint | null = null;\n #fired = false;\n\n constructor(fire: (point: LongPressPoint) => void) {\n this.#fire = fire;\n }\n\n /** `touchstart` and `mousedown`: a press starts. */\n readonly start = (event: {\n readonly detail?: unknown;\n readonly x?: number;\n readonly y?: number;\n readonly button?: number;\n }): void => {\n // A right click opens the browser's own menu; only the main button\n // presses. A touch has no button.\n if (event.button !== undefined && event.button !== 0) return;\n this.#stop();\n this.#fired = false;\n const point = pointOf(event);\n this.#start = point;\n this.#timer = setTimeout(() => {\n this.#timer = undefined;\n this.#fired = true;\n longPresses++;\n tapsDropped = true;\n this.#fire(point);\n }, LONG_PRESS_DURATION);\n };\n\n /** `touchmove` and `mousemove`: a press that moves too far is no long press. */\n readonly move = (event: {\n readonly detail?: unknown;\n readonly x?: number;\n readonly y?: number;\n }): void => {\n if (!this.#start) return;\n const { x, y } = pointOf(event);\n if (Math.hypot(x - this.#start.x, y - this.#start.y) > LONG_PRESS_SLOP) {\n this.#stop();\n }\n };\n\n /**\n * `touchend`, `touchcancel`, `mouseup` and `mouseleave`: the press is over.\n * The tap that ends a long press is dropped (see dropsTap).\n */\n readonly end = (): void => {\n this.#stop();\n this.#start = null;\n if (this.#fired) {\n this.#fired = false;\n const longPress = longPresses;\n setTimeout(() => {\n if (longPress === longPresses) tapsDropped = false;\n }, TAP_GRACE);\n }\n };\n\n #stop(): void {\n // The main thread's clearTimeout throws for undefined.\n if (this.#timer !== undefined) clearTimeout(this.#timer);\n this.#timer = undefined;\n }\n}\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\n/**\n * DOM event names whose Lynx event has another name. A listener for one of\n * them hears the Lynx event, bubbling, as if it were bound with `bind`: a\n * `(click)` listener runs on a tap. This is the mapping Lynx for Web makes\n * between the two (web-core's `W3cEventNameToLynx` turns a DOM `click` into\n * `tap`), and it's what lets Angular's own directives that listen for\n * `click`, such as `RouterLink`, work on Lynx elements.\n */\nexport const DOM_EVENT_ALIASES: ReadonlyMap<string, string> = new Map([\n ['click', 'tap'],\n]);\n\nimport type { Element as LynxJsElement } from '@lynx-js/types/main-thread';\n\n/**\n * Uses BaseLynxAnimation (not LynxAnimation), the animation's public API,\n * because LynxAnimation's ES private fields brand the class.\n */\nimport type {\n BaseLynxAnimation,\n LynxAnimationOptions,\n} from '../animation/animation';\n\n/**\n * The `nativeElement` of a Lynx element's `ElementRef`: AngularLynx's\n * wrapper around the native element, not a DOM element. Type an\n * `ElementRef` with it to call its methods, such as `animate()`, `invoke()`\n * or `setAccessibilityTrait()`.\n *\n * @usageNotes\n * ```ts\n * readonly option = viewChild.required<ElementRef<BaseLynxElement>>('option');\n * ```\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 /**\n * Adds a class that stays when the whole class list is replaced, for\n * ViewEncapsulation.Emulated's scope classes (see EmulatedLynxRenderer).\n */\n addScopeClass(name: string): void;\n removeClass(name: string): void;\n /**\n * Adds a trait to the element's own `accessibility-traits`, or takes it\n * away, keeping the traits the app sets. For state that changes, such as\n * `selected` on an active router link (see LynxRouterLinkActive). In a\n * template, LynxAccessibilityTraits does it from a binding.\n */\n setAccessibilityTrait(trait: string, on: boolean): 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 * LynxElement implements it via __InvokeUIMethod.\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 { isAndroid } from '../lynx-document/android-blur-capture';\nimport {\n androidBlurMaterialStyle,\n BLUR_MATERIAL_ATTRIBUTES,\n usesAndroidBlurMaterials,\n} from '../lynx-document/android-blur-material';\nimport { getPageId } from '../lynx-document/page-ref';\nimport {\n isFirstRenderPending,\n isInsideChangeDetection,\n} from '../lynx-render-lifecycle';\nimport type { ElementRef } from '../types/lynx';\nimport { sanitizeSvgContent } from './svg-content';\nimport { dropsTap, WebLongPress } from './web-long-press';\nimport {\n type BaseLynxElement,\n DOM_EVENT_ALIASES,\n EVENT_PREFIXES,\n type LynxEventType,\n} from './types';\n\ntype Listener = {\n eventType: LynxEventType;\n eventName: string;\n listener: (event: any) => any;\n};\n\n/**\n * The key native Lynx stores an element's event handler under. It keeps ONE\n * handler per event name (`AttributeHolder::SetStaticEvent` assigns into a map\n * keyed by name), whatever its bind/catch/capture type, so a second\n * `__AddEvent` for `tap` replaces the first. Global events have a map of\n * their own.\n */\nconst nativeEventKey = (type: LynxEventType, name: string): string =>\n type === 'global-bindEvent' ? `global:${name}` : name;\n\n/**\n * The one type an element's listeners for an event name can be registered\n * with natively (see nativeEventKey). `catch` wins over `bind`: every listener\n * on the element still runs, and the event stops there, as a `catch` listener\n * asked. A capture listener alongside a bubbling one is registered bubbling,\n * since the two phases can't share one native handler.\n */\nconst combinedEventType = (listeners: Listener[]): LynxEventType => {\n if (listeners[0].eventType === 'global-bindEvent') return 'global-bindEvent';\n const capture = listeners.every((l) => l.eventType.startsWith('capture-'));\n const stops = listeners.some((l) => l.eventType.endsWith('catchEvent'));\n if (capture) return stops ? 'capture-catchEvent' : 'capture-bindEvent';\n return stops ? 'catchEvent' : 'bindEvent';\n};\n\n/**\n * Parses a listener name from Angular (`bindtap`, `catchscroll`, `click`, …)\n * into the Lynx event type and name `__AddEvent` takes, or undefined for a\n * name Lynx has no event for.\n */\nconst parseEventName = (\n name: string,\n): Pick<Listener, 'eventType' | 'eventName'> | undefined => {\n const alias = DOM_EVENT_ALIASES.get(name);\n if (alias) return { eventType: 'bindEvent', eventName: alias };\n for (const [prefix, eventType] of EVENT_PREFIXES) {\n if (name.startsWith(prefix)) {\n return { eventType, eventName: name.slice(prefix.length) };\n }\n }\n return undefined;\n};\n\n/**\n * The `accessibility-traits` value to give an element: the app's own traits\n * plus the ones the runtime adds (see LynxElement.setAccessibilityTrait).\n *\n * iOS reads a comma-separated list with no spaces (`LynxConverter\n * toAccessibilityTraits:` splits on \",\" and compares each part exactly), so\n * that's what this writes. Android reads a single trait by exact match (none,\n * image or button), so a list would read as none there and drop the app's\n * own `button`; and it has no selected trait to add. So on Android the app's\n * traits are left as they are.\n */\nconst withAddedTraits = (own: unknown, added: readonly string[]): unknown => {\n if (added.length === 0 || isAndroid()) return own;\n const traits =\n own == null\n ? []\n : String(own)\n .split(',')\n .map((trait) => trait.trim())\n .filter((trait) => trait !== '' && trait !== 'none');\n for (const trait of added) {\n if (!traits.includes(trait)) traits.push(trait);\n }\n return traits.join(',');\n};\n\n/**\n * Whether a `setStyle` name is a CSS variable (`--x`), which only\n * `__SetInlineStyles` can set: `__AddInlineStyle` looks the name up as a CSS\n * property and drops it.\n */\nconst isCustomProperty = (name: string): boolean => name.startsWith('--');\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 * `element` and its ancestors, nearest first, up to the root of its tree.\n */\nconst ancestry = (element: ElementRef): ElementRef[] => {\n const path: ElementRef[] = [];\n for (let cur: ElementRef | null = element; cur; cur = __GetParent(cur)) {\n path.push(cur);\n }\n return path;\n};\n\n/**\n * True if a flush handles `first`'s child insertions and removals before\n * `second`'s. Lynx's flush (`Element::FlushActions` in\n * `core/renderer/dom/fiber/fiber_element.cc`) walks the element tree in\n * pre-order: an element's own child actions, then each child's subtree in\n * order. So an ancestor goes first, and otherwise the element whose branch\n * comes earlier under the two's nearest common ancestor. Elements in\n * different trees (one not attached yet) have no order, and count as not.\n *\n * Compares by unique ID for the same reason wouldFormCycle does.\n */\nconst flushesBefore = (first: ElementRef, second: ElementRef): boolean => {\n const firstPath = ancestry(first);\n const secondPath = ancestry(second);\n const secondDepth = new Map(\n secondPath.map((element, depth) => [__GetElementUniqueID(element), depth]),\n );\n for (let depth = 0; depth < firstPath.length; depth++) {\n const shared = secondDepth.get(__GetElementUniqueID(firstPath[depth]!));\n if (shared === undefined) continue;\n // firstPath[depth] is the nearest common ancestor. If it's `first` itself,\n // `first` is the ancestor; if it's `second`, `second` is.\n if (depth === 0) return true;\n if (shared === 0) return false;\n // The common ancestor has both branches among its children.\n const order = __GetChildren(firstPath[depth]!).map((child) =>\n __GetElementUniqueID(child),\n );\n return (\n order.indexOf(__GetElementUniqueID(firstPath[depth - 1]!)) <\n order.indexOf(__GetElementUniqueID(secondPath[shared - 1]!))\n );\n }\n return false;\n};\n\n/**\n * Whether this is Lynx's iOS renderer. On the native main thread there is no\n * global `SystemInfo`, only `lynx.SystemInfo` (see isAndroid).\n */\nconst isIOS = (): boolean => {\n const info =\n (typeof lynx !== 'undefined'\n ? (lynx as { SystemInfo?: { platform?: string } }).SystemInfo\n : undefined) ??\n (typeof SystemInfo !== 'undefined' ? SystemInfo : undefined);\n return info?.platform === 'iOS';\n};\n\n/**\n * Whether inserting `child` into `parent` before a sibling would leave it\n * drawing nothing: on iOS, a `<blur-view>` (a UIVisualEffectView) put among a plain\n * element's children anywhere but at the end shows nothing, nor do its\n * children, though the layout keeps its space. That's every blur-view at the\n * top of an `@if`, `@switch` or `@for` block, which Angular inserts before the\n * block's anchor. Appended, it draws, and so it does inside another\n * blur-view, whose native view inserts children its own way.\n */\nconst insertHidesBlurView = (\n parent: LynxElement,\n child: LynxElement,\n): boolean =>\n !__WEB__ &&\n child.tagName === 'blur-view' &&\n parent.tagName !== 'blur-view' &&\n isIOS();\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 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 #activeAnimations: LynxAnimation[] = [];\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 /**\n * ViewEncapsulation.Emulated's scope classes (see EmulatedLynxRenderer).\n * Angular writes static and bound classes as one whole class string through\n * setAttribute('class'), which would drop them, so they're added back each\n * time.\n */\n #scopeClasses: string[] = [];\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 /**\n * Inline declarations the runtime adds ahead of the app's own style=\"...\":\n * the CSS variables of a blur-view's material on Android (see\n * android-blur-material). Only `__SetInlineStyles` can set a CSS variable;\n * `__AddInlineStyle` drops any name that isn't a CSS property.\n */\n #runtimeStyle = '';\n /**\n * The CSS variables `[style.--x]` bindings set, which go into the inline\n * style string after the app's style=\"...\", for the same reason as\n * #runtimeStyle.\n */\n #customProperties = new Map<string, string>();\n /**\n * The app's own `accessibility-traits`, and the traits the runtime adds to\n * them (see setAccessibilityTrait). They're kept apart so that the app\n * setting its traits keeps the runtime's, and the runtime taking one away\n * restores the app's.\n */\n #ownTraits: unknown = null;\n #addedTraits: string[] = [];\n /** Every listener Angular added, in the order it added them. */\n #listeners: Listener[] = [];\n /** Recognizes long presses on Lynx for Web (see #listenForWebLongPress). */\n #webLongPress: WebLongPress | null = null;\n /**\n * The handler registered natively for each event (see nativeEventKey). It\n * runs every listener for that event, since native Lynx keeps only one.\n */\n #nativeHandlers = new Map<\n string,\n {\n eventType: LynxEventType;\n eventName: string;\n dispatch: (event: any) => unknown;\n }\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 * Elements with attributes removed this cycle, which reach Lynx only when\n * the cycle flushes (see #removedAttributes).\n */\n static #pendingAttributeRemovals = new Set<LynxElement>();\n\n /**\n * The attributes removed (set to null) since the last flush, which haven't\n * reached Lynx yet. Lynx queues a removal apart from the values set in the\n * same flush and applies it after them (`Element::SetAttribute` puts an\n * empty value in `reset_attr_vec_`, and `ConsumeAllAttributes` resets those\n * after setting `updated_attr_map_`), so an attribute removed and then set\n * again before a flush stayed removed on native. A glass button that a\n * sheet pairs with its glass in the same change detection as the button's\n * first render, for one, kept no `glass-effect-id`. So a removal waits here\n * for the flush, and a value set meanwhile takes it back.\n */\n readonly #removedAttributes = new Set<string>();\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 const classes = [\n ...new Set([\n ...String(value ?? '')\n .split(/\\s+/)\n .filter(Boolean),\n ...this.#scopeClasses,\n ]),\n ].join(' ');\n __SetClasses(this.element, classes);\n this.#classes = classes;\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 // A stroke-dasharray the engine can't parse hangs Lynx's native SVG engine and\n // blanks every <svg> in the app (see svg-content.ts), so it's rewritten\n // before it leaves JS. The cleaned value is also what's mirrored below,\n // so a recreated element gets it too.\n if (\n this.tagName === 'svg' &&\n name === 'content' &&\n typeof value === 'string'\n ) {\n value = sanitizeSvgContent(value);\n }\n if (name === 'accessibility-traits') {\n this.#ownTraits = value ?? null;\n value = withAddedTraits(this.#ownTraits, this.#addedTraits);\n }\n if (value == null) {\n // At the flush, unless it's set again first: see #removedAttributes.\n this.#removedAttributes.add(name);\n LynxElement.#pendingAttributeRemovals.add(this);\n scheduleSettleFlush();\n } else {\n this.#removedAttributes.delete(name);\n __SetAttribute(this.element, name, value);\n }\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 if (this.tagName === 'blur-view' && BLUR_MATERIAL_ATTRIBUTES.has(name)) {\n this.updateBlurMaterial();\n }\n }\n }\n\n /**\n * On Android, gives a blur-view the CSS variables that approximate its iOS\n * material (see android-blur-material). LynxDocument calls it when it\n * creates one, and setAttribute whenever an attribute it depends on changes.\n */\n updateBlurMaterial(): void {\n if (usesAndroidBlurMaterials()) {\n this.#setRuntimeStyle(androidBlurMaterialStyle(this.#attrs));\n }\n }\n\n /**\n * Adds `trait` to the app's own `accessibility-traits`, or takes it away.\n * The app can still set its traits at any time: setAttribute merges the two\n * (see withAddedTraits), so neither undoes the other.\n */\n setAccessibilityTrait(trait: string, on: boolean): void {\n if (this.#addedTraits.includes(trait) === on) return;\n this.#addedTraits = on\n ? [...this.#addedTraits, trait]\n : this.#addedTraits.filter((added) => added !== trait);\n this.setAttribute('accessibility-traits', this.#ownTraits);\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 if (isCustomProperty(key)) {\n // Angular removes a binding's style with an empty or null value too.\n if (value == null || value === '') {\n this.removeStyle(key);\n return;\n }\n const text = String(value);\n if (this.#customProperties.get(key) === text) return;\n this.#customProperties.set(key, text);\n this.#rewriteInlineStyle();\n return;\n }\n __AddInlineStyle(this.element, key, value);\n this.#inlineStyleKeys.set(key, value);\n }\n removeStyle(key: string): void {\n if (isCustomProperty(key)) {\n if (this.#customProperties.delete(key)) this.#rewriteInlineStyle();\n return;\n }\n __AddInlineStyle(this.element, key, null);\n this.#inlineStyleKeys.delete(key);\n }\n setInlineStyles(inlineStyle: string): void {\n __SetInlineStyles(this.element, this.#withRuntimeStyle(inlineStyle));\n this.#inlineStyleWhole = inlineStyle;\n }\n\n /**\n * The whole inline style to give the native element: the runtime's\n * declarations first, so the app's own wins where both set the same name,\n * then the app's style=\"...\", then its `[style.--x]` variables, which win\n * over the attribute as bindings do on the web. Without runtime\n * declarations or variables it's the app's value as is.\n */\n #withRuntimeStyle(inlineStyle: string | null): string | null {\n if (!this.#runtimeStyle && this.#customProperties.size === 0) {\n return inlineStyle;\n }\n const variables = [...this.#customProperties]\n .map(([name, value]) => `${name}: ${value}`)\n .join('; ');\n return [this.#runtimeStyle, inlineStyle?.replace(/[\\s;]+$/, ''), variables]\n .filter(Boolean)\n .join('; ');\n }\n\n #setRuntimeStyle(style: string): void {\n if (style === this.#runtimeStyle) return;\n this.#runtimeStyle = style;\n this.#rewriteInlineStyle();\n }\n\n /**\n * Gives the native element its whole inline style again.\n */\n #rewriteInlineStyle(): void {\n __SetInlineStyles(\n this.element,\n this.#withRuntimeStyle(this.#inlineStyleWhole),\n );\n // __SetInlineStyles replaces every inline style, including the [style.x]\n // ones __AddInlineStyle set, which the app didn't ask to drop.\n for (const [key, value] of this.#inlineStyleKeys) {\n __AddInlineStyle(this.element, key, value);\n }\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 newChild.#removeIfMoveWouldBeLost(this);\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 if (insertHidesBlurView(this, newChild)) {\n this.#appendBefore(newChild, refChild);\n } else {\n __InsertElementBefore(this.element, newChild.element, refChild.element);\n }\n this.#adoptChild(newChild, refChild);\n if (isTextish(this) || isTextish(newChild)) {\n LynxElement.#enqueueTextNormalization(newChild);\n }\n }\n }\n\n /**\n * Puts `newChild` before `refChild` by appending it, then moving `refChild`\n * and every native sibling after it to the end behind it, in order: the\n * same order as `__InsertElementBefore`, reached only by appends (see\n * insertHidesBlurView). The moves are in the same flush as the insert, so\n * the siblings keep their painting nodes, as any Angular move does.\n */\n #appendBefore(newChild: LynxElement, refChild: LynxElement): void {\n const childId = __GetElementUniqueID(newChild.element);\n const following: ElementRef[] = [];\n for (\n let sibling: ElementRef | null = refChild.element;\n sibling;\n sibling = __NextElement(sibling)\n ) {\n if (__GetElementUniqueID(sibling) !== childId) following.push(sibling);\n }\n __AppendElement(this.element, newChild.element);\n for (const sibling of following) {\n __AppendElement(this.element, sibling);\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.#removeIfMoveWouldBeLost(this);\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 addScopeClass(name: string): void {\n if (this.#scopeClasses.includes(name)) return;\n this.#scopeClasses.push(name);\n this.addClass(name);\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 /**\n * Sends Lynx the attribute removals that weren't taken back this cycle\n * (see #removedAttributes). Called by `LynxRendererFactory2.end()` and the\n * settle flush, after removals and before `__FlushElementTree()`, so the\n * removals land in the same flush as the cycle's other mutations.\n */\n static commitPendingAttributeRemovals(): void {\n if (LynxElement.#pendingAttributeRemovals.size === 0) return;\n const elements = [...LynxElement.#pendingAttributeRemovals];\n LynxElement.#pendingAttributeRemovals.clear();\n for (const el of elements) {\n for (const name of el.#removedAttributes) {\n __SetAttribute(el.element, name, null);\n }\n el.#removedAttributes.clear();\n }\n }\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 * Before this element moves under `newParent`: removes it for good if Lynx\n * would lose the move, so the insert that follows rebuilds it (see\n * #recreateIfDead) instead.\n *\n * Native Lynx (4.1) loses a move to another parent when the flush reaches\n * the new parent first. `__AppendElement` and `__InsertElementBefore` queue\n * the removal on the old parent and the insertion on the new one, and the\n * flush handles each parent's queue in tree order (see flushesBefore). When\n * the insertion runs first, the element is still in its old parent's\n * layout; the removal then finds a different parent and does nothing\n * (`HandleRemoveChildAction` in `fiber_element.cc`). The element ends up in\n * neither: the new parent lays out empty and the element sits unattached\n * at the top-left of the screen. Moving out of an `<overlay>` back to the\n * page it came from, which follows the page in the tree, always hit this\n * (CDK's DomPortal and the context menu's lifted element do it). Lynx's\n * develop branch fixes it (`FixFiberReinsertDetachFromOldRenderParent`),\n * after 4.1.\n *\n * A removal and a rebuild in the same flush don't depend on the order:\n * the old element leaves its parent, and a fresh one with the same state\n * goes into the new one. Moves the flush does handle in order (the old\n * parent first, or the same parent, as for an `@for` reorder) stay native\n * moves. Lynx for Web moves DOM nodes and doesn't have the problem.\n */\n #removeIfMoveWouldBeLost(newParent: LynxElement): void {\n if (__WEB__ || this.#paintingDead || this._virtualParent) return;\n const oldParent = __GetParent(this.element);\n if (\n !oldParent ||\n __GetElementUniqueID(oldParent) ===\n __GetElementUniqueID(newParent.element)\n ) {\n return;\n }\n if (flushesBefore(newParent.element, oldParent)) this.#doRemove();\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 // Each animation cancels itself, because only it knows the key it was\n // started under (its id, or a name it was given; see LynxAnimation).\n // Canceling a completed animation is harmless — a no-op at the native level.\n for (const anim of this.#activeAnimations) {\n anim.cancel();\n }\n if (this.#activeAnimations.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.#activeAnimations.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 const inlineStyle = this.#withRuntimeStyle(this.#inlineStyleWhole);\n if (inlineStyle != null) {\n __SetInlineStyles(fresh, inlineStyle);\n }\n for (const [key, value] of this.#inlineStyleKeys) {\n __AddInlineStyle(fresh, key, value);\n }\n for (const {\n eventType,\n eventName,\n dispatch,\n } of this.#nativeHandlers.values()) {\n __AddEvent(fresh, eventType, eventName, {\n type: 'worklet',\n value: dispatch,\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.#activeAnimations.push(anim);\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. A DOM name Lynx calls\n * something else (see DOM_EVENT_ALIASES) listens for the Lynx event, so\n * `(click)`, and Angular's RouterLink with it, runs on a tap.\n * Other names (e.g. `mouseover`) are ignored: Lynx has no event for them.\n *\n * An element can have any number of listeners for one event, as on the\n * web: a template's `(bindtap)` next to a directive's host listener for\n * `click`, say. Native Lynx keeps one handler per event name, so each name\n * gets one native handler that runs all of them (see #syncNativeHandler).\n */\n addEventListener(name: string, cb: (event: any) => any) {\n const parsed = parseEventName(name);\n if (!parsed) {\n return () => {};\n }\n\n if (__WEB__ && parsed.eventName === 'longpress') {\n this.#listenForWebLongPress();\n }\n\n // Kept so #recreateSubtree() can register the handlers again on a rebuilt\n // native ref: native events don't survive a painting-node teardown and\n // 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: Listener = { ...parsed, listener: cb };\n this.#listeners.push(entry);\n this.#syncNativeHandler(entry);\n\n return () => this.#removeListener(entry);\n }\n\n /**\n * Removes a listener added with addEventListener, as the DOM method does,\n * for code that pairs the two on the element itself rather than going\n * through the renderer's cleanup function. Angular's `@defer` interaction\n * and hover triggers do, for their `click`, `keydown` and `mouseenter`\n * listeners; without it, their cleanup would throw. A name Lynx has no\n * event for was never added, so removing it does nothing.\n */\n removeEventListener(name: string, cb: (event: any) => any): void {\n const parsed = parseEventName(name);\n if (!parsed) return;\n const entry = this.#listeners.find(\n (other) =>\n other.listener === cb &&\n other.eventType === parsed.eventType &&\n other.eventName === parsed.eventName,\n );\n if (entry) this.#removeListener(entry);\n }\n\n /**\n * On Lynx for Web, which never fires `longpress` (see web-long-press.ts),\n * recognizes long presses from this element's touch and mouse events and\n * runs its `longpress` listeners, as native Lynx would. Once per element:\n * the listeners it adds stay, and do nothing once no `longpress` listener\n * is left.\n */\n #listenForWebLongPress(): void {\n if (this.#webLongPress) return;\n const press = new WebLongPress((detail) => {\n const entry = this.#listeners.find(\n (listener) => listener.eventName === 'longpress',\n );\n if (entry) this.#dispatch(entry, { type: 'longpress', detail });\n });\n this.#webLongPress = press;\n this.addEventListener('bindtouchstart', press.start);\n this.addEventListener('bindmousedown', press.start);\n this.addEventListener('bindtouchmove', press.move);\n this.addEventListener('bindmousemove', press.move);\n for (const end of ['touchend', 'touchcancel', 'mouseup', 'mouseleave']) {\n this.addEventListener(`bind${end}`, press.end);\n }\n }\n\n #removeListener(entry: Listener): void {\n const i = this.#listeners.indexOf(entry);\n // Removing a listener a second time does nothing, as on the DOM.\n if (i < 0) return;\n this.#listeners.splice(i, 1);\n this.#syncNativeHandler(entry);\n }\n\n /**\n * The listeners that share `entry`'s native handler, in the order added.\n */\n #listenersLike(entry: Listener): Listener[] {\n const key = nativeEventKey(entry.eventType, entry.eventName);\n return this.#listeners.filter(\n (other) => nativeEventKey(other.eventType, other.eventName) === key,\n );\n }\n\n /**\n * Brings the native handler for `entry`'s event in line with its listeners:\n * registers it for the first one, changes its type when a listener needs\n * another (see combinedEventType), and removes it after the last one.\n */\n #syncNativeHandler(entry: Listener): void {\n const key = nativeEventKey(entry.eventType, entry.eventName);\n const listeners = this.#listenersLike(entry);\n const current = this.#nativeHandlers.get(key);\n const eventType = listeners.length ? combinedEventType(listeners) : null;\n if (current?.eventType === eventType) return;\n if (current) {\n // Passing undefined as the listener tells the Lynx SDK to remove the\n // handler for this type+name combination.\n __AddEvent(this.element, current.eventType, entry.eventName, undefined);\n this.#nativeHandlers.delete(key);\n }\n if (!eventType) return;\n const handler = {\n eventType,\n eventName: entry.eventName,\n // The same dispatcher across a type change: it looks the listeners up\n // when the event fires, so it never needs registering again for them.\n dispatch:\n current?.dispatch ?? ((event: any) => this.#dispatch(entry, event)),\n };\n this.#nativeHandlers.set(key, handler);\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, entry.eventName, {\n type: 'worklet',\n value: handler.dispatch,\n });\n }\n\n /**\n * Runs every listener for the event `entry` belongs to.\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 the listeners (Angular's wrapper may call\n * preventDefault() during that call) and return the last one's result (the\n * return-false path relies on it). Mirrors React Lynx's\n * addEventMethodsIfNeeded.\n */\n #dispatch(entry: Listener, event: any): unknown {\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 // The browser's click after a long press on Lynx for Web, which native\n // Lynx doesn't follow with a tap (see web-long-press.ts).\n if (__WEB__ && entry.eventName === 'tap' && dropsTap()) return undefined;\n let result: unknown;\n // As a DOM event does: the listeners are those registered when the event\n // fires, so one that removes itself doesn't make the next one skip, and a\n // listener an earlier one removed (an @if hiding part of the element, say)\n // doesn't run.\n for (const other of this.#listenersLike(entry)) {\n if (this.#listeners.includes(other)) result = other.listener(event);\n }\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\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 * Commits this cycle's attribute removals (see LynxElement's\n * `#removedAttributes`). A free-function wrapper over\n * `LynxElement.commitPendingAttributeRemovals()` so\n * `LynxRendererFactory2.end()` can drain them (via the lynx-element barrel)\n * right after element removals and before `__FlushElementTree()`.\n */\nexport const processPendingAttributeRemovals = (): void => {\n LynxElement.commitPendingAttributeRemovals();\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 run on the main\n * thread (Angular doesn't run on the background thread), so no thread guard is\n * 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.commitPendingAttributeRemovals();\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 { scheduleSettleFlush } from '../lynx-element';\nimport type { ElementRef } from '../types/lynx';\nimport type { WebGestureArena } from './web/arena';\n\n/**\n * The gesture PAPIs LynxGestureDetector and GestureStateManager call: Lynx's\n * own on iOS and Android, and on Lynx for Web, whose web-core recognizes no\n * gestures, the runtime's port of Lynx's gesture arena (see web/arena.ts).\n */\n\ntype DetectorConfig = {\n callbacks: Array<{ name: string; callback: unknown }>;\n config?: Record<string, unknown>;\n};\n\nlet arena: WebGestureArena | undefined;\nlet loading: Promise<WebGestureArena> | undefined;\n\n/**\n * Runs `use` with the page's arena (each `<lynx-view>` has its own main\n * thread), loading it first if this is the first gesture. Calls made while\n * it loads run in order once it has; after that, at once, so that a\n * callback's `fail()` takes effect before the next handler sees the event.\n *\n * `__WEB__` is a compile-time define, and the import sits in a branch it\n * kills on native, so native bundles don't include the arena. A static\n * import wouldn't do: the minifier can't prove the arena's classes side\n * effect free once they're compiled for the main thread, and keeps them (as\n * create-blur-view-element.ts found for the web glass). Only the main thread\n * runs Angular, so only it needs the arena.\n */\nconst withArena = (use: (arena: WebGestureArena) => void): void => {\n if (arena) {\n use(arena);\n return;\n }\n if (__WEB__ && __MAIN_THREAD__) {\n loading ??= import('./web/arena').then(\n ({ WebGestureArena }) =>\n (arena = new WebGestureArena(scheduleSettleFlush)),\n );\n void loading.then(use);\n }\n};\n\nexport const setGestureDetector = (\n node: ElementRef,\n id: number,\n type: number,\n config: DetectorConfig,\n relations: Record<string, number[]>,\n): void => {\n if (__WEB__) {\n withArena((web) => web.setDetector(node, id, type, config, relations));\n } else {\n __SetGestureDetector(node, id, type, config, relations);\n }\n};\n\nexport const removeGestureDetector = (node: ElementRef, id: number): void => {\n if (__WEB__) withArena((web) => web.removeDetector(node, id));\n else __RemoveGestureDetector(node, id);\n};\n\nexport const setGestureState = (\n node: ElementRef,\n id: number,\n state: number,\n): void => {\n if (__WEB__) withArena((web) => web.setState(node, id, state));\n else __SetGestureState(node, id, state);\n};\n\n/**\n * On the web, does nothing: consuming and intercepting decide whether a\n * gesture shares the touch with native scroll views and ancestors' native\n * gestures, and the arena has none to share it with.\n */\nexport const consumeGesture = (\n node: ElementRef,\n id: number,\n options: Record<string, boolean>,\n): void => {\n if (!__WEB__) __ConsumeGesture(node, id, options);\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/…): `onBegin`\n * seeds the origin where the touch began, and `onEnd` clears it.\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 where the touch began, then report translation\n // relative to it, like react-native-gesture-handler: a pan that activates\n // after `minDistance` reports the distance moved before activating too.\n // The directive registers an `onBegin` on every continuous gesture, so\n // each touch re-anchors even when the previous one sent no `onEnd`. Any\n // other gesture anchors on its first event, and resets at `onEnd`.\n if (name === 'onBegin' || 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';\nimport { consumeGesture, setGestureState } from './gesture-papi';\n\n/**\n * Controls gesture state from within a callback.\n * Wraps the __SetGestureState and __ConsumeGesture PAPI calls (see\n * gesture-papi.ts for Lynx for Web, which has neither).\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, ContinuousGesture } from './base-gesture';\nimport { ComposedGesture } from './composition';\nimport { removeGestureDetector, setGestureDetector } from './gesture-papi';\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, or on Lynx for Web,\n * which has none, the runtime's port of it: see gesture-papi.ts). 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 constructor() {\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 //\n // It's set here, when the element is created, rather than when a gesture\n // is bound: Android decides whether an element gets a View of its own when\n // it first draws it, and turning flatten off afterwards doesn't give it one.\n // ngOnChanges came too late for a routed component's elements and for a\n // gesture bound after the first render (`[lynxGesture]=\"on ? pan : []\"`),\n // and those gestures never fired on Android (issue #56).\n const elementRef = (this.#el as any).element;\n if (elementRef) __SetAttribute(elementRef, 'flatten', false);\n }\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 // An element with no native handle (.element is undefined), such as the\n // renderer's in-memory test double, has nothing to register a gesture on.\n const elementRef = (this.#el as any).element;\n if (!elementRef) return;\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: g._config,\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`.\n *\n * Continuous gestures (pan, fling, pinch, rotation) always get an `onBegin`,\n * an empty one when the user didn't register theirs. Lynx's native fling\n * handler, and its pan handler before Lynx 3.9, fire `onStart` and `onEnd` only\n * after `onBegin` has fired, and fire `onBegin` only when one is registered\n * (LynxFlingGestureHandler.m / FlingGestureHandler.java), so without it those\n * two callbacks never ran, with no error. Running it also anchors the\n * gesture's translation where the touch began (see mapGestureEvent).\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 const callbacks = Object.entries(gesture._callbacks).map(([name, cb]) =>\n wrap(name, cb),\n );\n if (\n gesture instanceof ContinuousGesture &&\n !gesture._callbacks['onBegin']\n ) {\n // wrap() maps the event, which is what anchors the translation.\n callbacks.push(wrap('onBegin', () => {}));\n }\n return callbacks;\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","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 * ⚠️ Not read by Lynx's native pan handlers yet: as of Lynx 4.1 they read\n * only `minDistance` (LynxPanGestureHandler.m / PanGestureHandler.java\n * `handleConfigMap`). The same goes for activeOffsetY, failOffsetX/Y and\n * min/maxPointers. Kept for API parity with Lynx's gesture-runtime.\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 * ⚠️ Not read by Lynx's native pan handlers yet (see `activeOffsetX`). Call\n * the state manager's `fail()` from `onUpdate` instead.\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 { AccessibilityTrait } from '../accessibility/accessibility-traits';\nimport type { BaseLynxElement } from '../lynx-element/types';\n\n/**\n * A length Lynx's exposure detection parses, such as `'20px'` or `'-10rpx'`.\n * Lynx reads the margins as strings, so a bare number has no effect.\n */\nexport type ExposureMargin = `${number}px` | `${number}rpx`;\n\n/**\n * Lets a true/false input also be written as a static attribute, as Lynx's\n * guides and ours do: `flatten=\"false\"`, or a bare `ignore-focus` for true.\n * Angular type-checks a static attribute's string against the input, so\n * without this `<text flatten=\"false\">` stops compiling once `flatten` is an\n * input. Unlike Angular's `booleanAttribute`, `undefined` stays `undefined`,\n * so a binding can still remove the attribute and restore Lynx's default.\n */\n// oxlint-disable-next-line func-style, @blotch/no-function-declaration -- Angular's compiler takes a named input transform only as a function declaration (NG1010)\nfunction booleanInput(\n value: boolean | '' | 'true' | 'false' | undefined,\n): boolean | undefined {\n return typeof value === 'string' ? value !== 'false' : value;\n}\n\n/**\n * Lets `pan-intercept-direction` also be written as a static attribute,\n * `pan-intercept-direction=\"1\"`, and hands Lynx a number either way.\n */\n// oxlint-disable-next-line func-style, @blotch/no-function-declaration -- Angular's compiler takes a named input transform only as a function declaration (NG1010)\nfunction panInterceptDirectionInput(\n value: 0 | 1 | '0' | '1' | undefined,\n): 0 | 1 | undefined {\n return typeof value === 'string' ? (Number(value) as 0 | 1) : value;\n}\n\n/**\n * Lets `pan-intercept-scope` also be written as a static attribute,\n * `pan-intercept-scope=\"5\"`, and hands Lynx a number either way.\n */\n// oxlint-disable-next-line func-style, @blotch/no-function-declaration -- Angular's compiler takes a named input transform only as a function declaration (NG1010)\nfunction panInterceptScopeInput(\n value: 0 | 1 | 2 | 3 | 4 | 5 | '0' | '1' | '2' | '3' | '4' | '5' | undefined,\n): 0 | 1 | 2 | 3 | 4 | 5 | undefined {\n return typeof value === 'string'\n ? (Number(value) as 0 | 1 | 2 | 3 | 4 | 5)\n : value;\n}\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 { name: 'accessibility-element', transform: booleanInput },\n 'accessibility-label',\n // The current value a screen reader reads after the label (a slider's\n // position, a chart's focused point), and custom actions it offers\n // (string[]; the chosen one arrives as the accessibility action event's detail.name).\n 'accessibility-value',\n 'accessibility-actions',\n 'accessibility-traits',\n 'accessibility-elements',\n { name: 'accessibility-elements-hidden', transform: booleanInput },\n { name: 'accessibility-exclusive-focus', transform: booleanInput },\n 'a11y-id',\n { name: 'user-interaction-enabled', transform: booleanInput },\n { name: 'native-interaction-enabled', transform: booleanInput },\n { name: 'event-through', transform: booleanInput },\n 'hit-slop',\n { name: 'block-native-event', transform: booleanInput },\n { name: 'ignore-focus', transform: booleanInput },\n { name: 'ios-enable-simultaneous-touch', transform: booleanInput },\n { name: 'flatten', transform: booleanInput },\n { name: 'pan-intercept-direction', transform: panInterceptDirectionInput },\n { name: 'pan-intercept-scope', transform: panInterceptScopeInput },\n 'consume-slide-event',\n { name: 'enable-touch-pseudo-propagation', transform: booleanInput },\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 { name: 'enable-exposure-ui-margin', transform: booleanInput },\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 /**\n * The kind of element a screen reader announces. Plural, as Lynx reads it:\n * iOS, Android and Harmony ignore `accessibility-trait`. iOS also reads a\n * comma-separated list with no spaces, such as `button,selected`, which\n * is what LynxRouterLinkActive and LynxAccessibilityTraits write; Android\n * and Harmony read a single trait. @default 'none'\n */\n 'accessibility-traits'?:\n | AccessibilityTrait\n | `${AccessibilityTrait},${string}`;\n /**\n * Comma-separated `id`s of the child elements a screen reader visits, in\n * order. iOS and Android look each one up as an `id` selector.\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 * Lets Lynx draw the element into its parent's native view instead of\n * creating its own (Android). `false` gives it its own view, which sticky\n * positioning, text selection and reliable clipping need. @default true\n */\n flatten?: boolean;\n /**\n * Direction in which the element takes pan gestures from native views\n * outside Lynx: 0 = horizontal, 1 = vertical.\n */\n 'pan-intercept-direction'?: 0 | 1;\n /**\n * Which views `pan-intercept-direction` takes pans from: 0 = self,\n * 1 = ancestors, 2 = descendants, 3 = self and ancestors, 4 = self and\n * descendants, 5 = all.\n */\n 'pan-intercept-scope'?: 0 | 1 | 2 | 3 | 4 | 5;\n /**\n * Swipe angle ranges, `[start, end]` in degrees, that the element keeps\n * from platform gestures.\n */\n 'consume-slide-event'?: [number, number][];\n /**\n * Whether `:active` also applies to the ancestors on the touch's event path.\n */\n 'enable-touch-pseudo-propagation'?: 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 * How much of the element must be visible to count as exposed, as a\n * percentage string such as `'50%'`. @default '0%'\n */\n 'exposure-area'?: `${number}%`;\n /**\n * Extends/shrinks the viewport detection zone (top edge).\n */\n 'exposure-screen-margin-top'?: ExposureMargin;\n /**\n * Extends/shrinks the viewport detection zone (bottom edge).\n */\n 'exposure-screen-margin-bottom'?: ExposureMargin;\n /**\n * Extends/shrinks the viewport detection zone (left edge).\n */\n 'exposure-screen-margin-left'?: ExposureMargin;\n /**\n * Extends/shrinks the viewport detection zone (right edge).\n */\n 'exposure-screen-margin-right'?: ExposureMargin;\n /**\n * Adjusts the element's own bounding rect for exposure detection (top).\n * iOS and Android apply it only with `enable-exposure-ui-margin`.\n */\n 'exposure-ui-margin-top'?: ExposureMargin;\n /**\n * Adjusts the element's own bounding rect for exposure detection (bottom).\n * iOS and Android apply it only with `enable-exposure-ui-margin`.\n */\n 'exposure-ui-margin-bottom'?: ExposureMargin;\n /**\n * Adjusts the element's own bounding rect for exposure detection (left).\n * iOS and Android apply it only with `enable-exposure-ui-margin`.\n */\n 'exposure-ui-margin-left'?: ExposureMargin;\n /**\n * Adjusts the element's own bounding rect for exposure detection (right).\n * iOS and Android apply it only with `enable-exposure-ui-margin`.\n */\n 'exposure-ui-margin-right'?: ExposureMargin;\n /**\n * Turns on `exposure-ui-margin-*` on iOS and Android (always on for Harmony\n * and the web). It also changes how they apply `exposure-screen-margin-*`.\n * @default false\n */\n 'enable-exposure-ui-margin'?: boolean;\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 * Android only has the plain blur, a Gaussian blur of `blur-radius`. There\n * the runtime approximates `blur-effect`, `glass-style` and\n * `glass-tint-color` with a translucent background and rim over the blur,\n * which a background, background image or shadow the app sets replaces.\n * Nothing refracts, and `glass-interactive` and `spacing` do nothing.\n */\n@Directive({\n selector: 'blur-view',\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 'blur-material',\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\"`\n * (Android). The runtime points it at the page, so a blur-view inside\n * another blur-view still blurs what's behind it; an empty string restores\n * Android's own choice, the nearest ancestor that clips or contains it.\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. Android\n * gets a tint that approximates it. @default 'light'\n */\n 'blur-effect'?:\n | 'light'\n | 'extra-light'\n | 'dark'\n | 'glass'\n | 'glass-container';\n /**\n * One of UIKit's adaptive blur materials, which follow\n * `ios-user-interface-style` (iOS 13+, in apps built with\n * `ng build --platform ios`): `systemUltraThinMaterial` to\n * `systemThickMaterial`, or `systemChromeMaterial`, the bars'. While it's\n * set it replaces `blur-effect` and `blur-radius`. Lynx's own blur-view\n * doesn't have it, so Lynx Explorer and other hosts ignore it and draw the\n * `blur-effect`.\n */\n 'blur-material'?: 'ultra-thin' | 'thin' | 'regular' | 'thick' | 'chrome';\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; approximated on Android). @default 'transparent'\n */\n 'glass-tint-color'?: string;\n /**\n * Glass variant (iOS; approximated on Android). @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' })\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 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.\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 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 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 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 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 // 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 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 * Gaps between items aren't attributes: `list-main-axis-gap` and\n * `list-cross-axis-gap` are CSS properties, which Lynx's list reads from its\n * computed style, so set them in `style` (`[style.list-main-axis-gap]`).\n */\n@Directive({\n selector: 'list',\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 '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 * 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 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 ],\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","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Anonymous grouping element with no visual output.\n */\n@Directive({ selector: 'block' })\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' })\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' })\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 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 * The layer the overlay sits in when several are open: 1 is the top layer\n * and 4 the lowest. Within a layer the last one shown is on top. Lynx reads\n * it only while the overlay is hidden. @default 1\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 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})\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 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})\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})\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})\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 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 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 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 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 the text is laid out in. The text box ends after\n * that many lines, but the ellipsis needs `text-overflow: ellipsis`\n * (Tailwind's `text-ellipsis`). Without it, iOS cuts the text off at the\n * last line, and Android draws the remaining lines past the box.\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' })\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 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 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>`. Its\n * attributes (`flatten`, the pan-intercept ones, …) work on every element, so\n * they live on {@link LynxElementBase}.\n */\n@Directive({ selector: 'view' })\nexport class LynxView extends LynxElementBase {}\n","import { Directive } from '@angular/core';\nimport { LynxElementBase } from './base';\n\n/**\n * Horizontally swipeable paging container.\n */\n@Directive({\n selector: 'viewpager',\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})\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 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","import {\n DestroyRef,\n Directive,\n ElementRef,\n inject,\n InjectionToken,\n type OutputRef,\n} from '@angular/core';\nimport type { BaseLynxElement } from '../lynx-element/types';\n\n/**\n * Finds the `isActiveChange` output of Angular's `RouterLinkActive` on the\n * element being created, or null if it has none. Called in the injection\n * context of that element's LynxRouterLinkActive.\n *\n * `provideRouter()` provides it, rather than LynxRouterLinkActive importing\n * `RouterLinkActive` itself, because LynxRouterLinkActive is part of\n * LYNX_ELEMENTS, which every component imports: referring to the router from\n * there would put the whole router in the bundle of an app without routes.\n * Without `provideRouter()` there's no router to follow, and the token is\n * missing.\n */\nexport const ROUTER_LINK_ACTIVE_CHANGE = new InjectionToken<\n () => OutputRef<boolean> | null\n>('router-link-active-change');\n\n/**\n * Tells screen readers which router link is the current one: while Angular's\n * `RouterLinkActive` on the same element says its route is active, the\n * element has the `selected` accessibility trait, as the selected tab of a\n * native tab bar does. On the web, `routerLinkActive` only changes classes, or\n * `aria-current` with `ariaCurrentWhenActive`; Lynx elements have no ARIA,\n * and `accessibility-traits` is how they say this.\n *\n * It keeps the element's own traits: `accessibility-traits=\"button\"` becomes\n * `button,selected` while the link is active. On Android, which reads one\n * trait and has no selected trait, the element keeps its own traits as they\n * are.\n *\n * It's part of LYNX_ELEMENTS, so a component that imports LYNX_ELEMENTS and\n * Angular's `RouterLinkActive` gets it on every `routerLinkActive` element.\n * To add it to a component's host instead, list it in `hostDirectives` next\n * to `RouterLinkActive`.\n *\n * @usageNotes\n * ```ts\n * @Component({\n * imports: [LYNX_ELEMENTS, RouterLink, RouterLinkActive],\n * template: `\n * <view routerLink=\"/settings\" routerLinkActive=\"active\">\n * <text>Settings</text>\n * </view>\n * `,\n * })\n * ```\n */\n@Directive({ selector: '[routerLinkActive]' })\nexport class LynxRouterLinkActive {\n constructor() {\n const activeChange = inject(ROUTER_LINK_ACTIVE_CHANGE, {\n optional: true,\n })?.();\n if (!activeChange) return;\n const element: BaseLynxElement = inject(ElementRef).nativeElement;\n const subscription = activeChange.subscribe((active) =>\n element.setAccessibilityTrait('selected', active),\n );\n inject(DestroyRef).onDestroy(() => subscription.unsubscribe());\n }\n}\n","import { Directive, effect, ElementRef, inject, input } from '@angular/core';\nimport type { BaseLynxElement } from '../lynx-element/types';\n\n/**\n * One trait of `accessibility-traits`, each of which iOS turns into a\n * UIAccessibilityTraits flag (`LynxConverter+UI.m`).\n */\nexport type AccessibilityTrait =\n | 'text'\n | 'image'\n | 'button'\n | 'link'\n | 'header'\n | 'search'\n | 'selected'\n | 'playable'\n | 'keyboard'\n | 'summary'\n | 'disabled'\n | 'updating'\n | 'adjustable'\n | 'tabbar'\n | 'none';\n\n/**\n * Which traits LynxAccessibilityTraits adds, by name. `none` isn't one: it\n * says the element has no traits, so there's nothing to add.\n */\nexport type AccessibilityTraitStates = Partial<\n Record<Exclude<AccessibilityTrait, 'none'>, boolean>\n>;\n\n/**\n * Adds accessibility traits to an element's own `accessibility-traits` while\n * a binding says so, such as `selected` on the chosen one of several options,\n * or `disabled` on an item that can't be used now.\n *\n * Writing the state into the attribute instead,\n * `accessibility-traits=\"button,selected\"`, works only on iOS. Android reads\n * the attribute as a single trait, so a list stops being a button there. The\n * element merges these traits into its own instead (see\n * LynxElement.setAccessibilityTrait): `button` reads `button,selected` on iOS,\n * and stays `button` on Android, which has no selected trait to add. The\n * element can still set its own traits at any time, and neither undoes the\n * other.\n *\n * A trait that turns false, or that the map leaves out, is taken away again.\n * Only the traits this directive added are: the element's own stay.\n *\n * It's part of LYNX_ELEMENTS, so a component that imports LYNX_ELEMENTS can\n * bind it on any element.\n *\n * @usageNotes\n * ```html\n * <view\n * [accessibility-element]=\"true\"\n * accessibility-traits=\"button\"\n * [accessibility-label]=\"label()\"\n * [lynxAccessibilityTraits]=\"{ selected: selected() }\"\n * (bindtap)=\"chosen.emit()\"\n * >\n * ```\n */\n@Directive({ selector: '[lynxAccessibilityTraits]' })\nexport class LynxAccessibilityTraits {\n readonly lynxAccessibilityTraits = input<\n AccessibilityTraitStates | null | undefined\n >();\n\n readonly #element: BaseLynxElement = inject(ElementRef).nativeElement;\n /** The traits this has added, to take away those that turn off. */\n #added: string[] = [];\n\n constructor() {\n effect(() => {\n const states: Record<string, boolean | undefined> =\n this.lynxAccessibilityTraits() ?? {};\n const on = Object.keys(states).filter((trait) => states[trait]);\n for (const trait of this.#added) {\n if (!on.includes(trait)) {\n this.#element.setAccessibilityTrait(trait, false);\n }\n }\n for (const trait of on) this.#element.setAccessibilityTrait(trait, true);\n this.#added = on;\n });\n }\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';\nexport { LynxRouterLinkActive } from '../router/lynx-router-link-active';\nexport { LynxAccessibilityTraits } from '../accessibility/accessibility-traits';\n\nimport { LynxInputValueAccessor, LynxTextareaValueAccessor } 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';\nimport { LynxRouterLinkActive } from '../router/lynx-router-link-active';\nimport { LynxAccessibilityTraits } from '../accessibility/accessibility-traits';\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 // The same pair as LYNX_FORM_ACCESSORS, listed rather than spread: a minifier\n // keeps an array with a spread in it even when nothing uses the array, since\n // the spread runs the array's iterator. That kept every directive here, and\n // Angular with them, in the background bundle, which uses none of them.\n LynxInputValueAccessor,\n LynxTextareaValueAccessor,\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 // Activates on top of Angular's RouterLinkActive, like the CVA directives\n // on form attributes above: marks the active link `selected` for screen\n // readers. It doesn't import the router (see the file).\n LynxRouterLinkActive,\n // Adds accessibility traits, such as `selected`, from a binding, on any\n // element that binds `lynxAccessibilityTraits`.\n LynxAccessibilityTraits,\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: Angular, and so every LynxLogger call, runs on the main thread,\n * which has no fetch. Only the background thread has it. Logs are relayed to\n * 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: unknown[];\n};\n\nconst LOG_EVENT = '__lynx_log__';\n\n/**\n * The dev server's log endpoint, or '' when there's none (a production build,\n * or a dev build without a server).\n */\nconst logUrl = (): string =>\n __DEV__ && typeof __DEV_LOG_URL__ !== 'undefined' ? __DEV_LOG_URL__ : '';\n\n/**\n * This thread's fetch, which only the background thread has: Lynx injects it\n * through the background bundle's tt.define() wrapper, so it's in module scope\n * rather than on globalThis. Read once the module runs, on either thread.\n */\nconst resolveFetch = ():\n | ((url: string, init?: RequestInit) => Promise<Response>)\n | undefined => {\n try {\n if (typeof fetch === 'function') {\n return 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 return (globalThis as any).fetch;\n }\n /* v8 ignore stop */\n } catch {}\n return undefined;\n};\n\n/**\n * An argument as it travels to the dev server, which writes strings as they\n * are, objects and arrays as indented JSON, and an Error as its stack.\n *\n * The entry crosses to the background thread and then to the dev server as\n * JSON, which would turn an Error into `{}` (its message and stack aren't\n * enumerable): it goes as a plain object the dev server recognizes by its\n * `__type`. An object JSON can't hold, such as a circular one, goes as a\n * string, so it can't make the whole entry fail to send. So does everything\n * else: numbers, booleans, `undefined` and `null` print the same either way,\n * and JSON would turn `undefined` and `NaN` into `null`.\n */\nconst toLogArg = (arg: unknown): unknown => {\n if (arg instanceof Error) {\n return {\n __type: 'Error',\n name: arg.name,\n message: arg.message,\n stack: arg.stack,\n };\n }\n if (typeof arg === 'object' && arg !== null) {\n try {\n JSON.stringify(arg);\n return arg;\n } catch {}\n }\n return String(arg);\n};\n\n/**\n * Posts one entry to the dev server. Failures are dropped: logging must never\n * break the app.\n */\nconst postToServer = (\n fetchFn: (url: string, init?: RequestInit) => Promise<Response>,\n url: string,\n entry: LogEntry,\n): void => {\n try {\n fetchFn(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ logs: [entry] }),\n }).catch(() => {});\n } catch {}\n};\n\n/**\n * Background thread: posts the log entries the main thread relays. Installed\n * at module load, not by the service, because no Angular code, so no\n * LynxLogger, runs on this thread.\n */\nconst installLogRelay = (): void => {\n if (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__) return;\n const url = logUrl();\n const fetchFn = resolveFetch();\n if (!url || !fetchFn) return;\n try {\n if (\n typeof lynx !== 'undefined' &&\n typeof lynx.getCoreContext === 'function'\n ) {\n lynx.getCoreContext().addEventListener(LOG_EVENT, (event: any) => {\n try {\n postToServer(fetchFn, url, JSON.parse(event.data as string));\n } catch {}\n });\n }\n } catch {}\n};\n\ninstallLogRelay();\n\n@Injectable({ providedIn: 'root' })\nexport class LynxLogger {\n readonly #url: string = logUrl();\n /**\n * This thread's fetch: set when the logger runs on the background thread,\n * such as in a test, where it posts directly instead of relaying.\n */\n readonly #fetchFn = this.#url ? resolveFetch() : undefined;\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(toLogArg),\n };\n\n if (this.#fetchFn) {\n // Background thread: send directly via fetch.\n postToServer(this.#fetchFn, this.#url, entry);\n } else {\n // Main thread: no fetch available. Relay to background thread via IPC.\n // The relay installed above handles it there.\n try {\n if (\n typeof lynx !== 'undefined' &&\n typeof (lynx as any).getJSContext === 'function'\n ) {\n (lynx as any).getJSContext().dispatchEvent({\n type: LOG_EVENT,\n data: JSON.stringify(entry),\n });\n }\n } catch {}\n }\n }\n}\n","import { Injectable } from '@angular/core';\nimport {\n callOnBackground,\n isMainThread,\n relayedModule,\n relayFunctions,\n relayModuleObject,\n} from '../background-call';\nimport type { NativeModuleMap, NativeModuleProxy } 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 * Lynx provides both only on the background thread, while Angular runs on the\n * main thread. So on the main thread every method goes through the background\n * call relay (background-call.ts): calls run on the background thread, their\n * results and callbacks come back as JSON, and a module is a proxy whose\n * methods return promises.\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 typeof NativeModules !== 'undefined' && NativeModules != null;\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 * Resolves `undefined` when there is no bridge (web preview, tests).\n */\n call<T = unknown>(\n name: string,\n params: Record<string, unknown> = {},\n ): Promise<T | undefined> {\n if (isMainThread() && typeof lynx === 'undefined') {\n // No background thread to relay to.\n return Promise.resolve(undefined);\n }\n return callOnBackground('nativeBridgeCall', name, params) as Promise<\n T | undefined\n >;\n }\n\n /**\n * Subscribes to a native event via `NativeModules.bridge.on()`. From the\n * main thread, the callback gets the event's arguments copied as JSON.\n *\n * No-op when there is no bridge.\n */\n on(name: string, callback: (...args: unknown[]) => void): void {\n callOnBackground('nativeBridgeOn', name, relayFunctions(callback)).catch(\n () => {\n // Without a background thread there's no bridge to listen to.\n },\n );\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 * export {};\n *\n * declare module '@blotch/angular-lynx' {\n * interface NativeModuleMap {\n * NativeLocalStorageModule: { ... };\n * }\n * }\n *\n * const storage = modules.getNativeModule('NativeLocalStorageModule');\n * ```\n *\n * On the main thread, which can't reach native modules, it returns a proxy:\n * each method call runs on the background thread and returns a promise of\n * its result, and a call to a module or method the host doesn't have\n * rejects. The return type says so: a module in {@link NativeModuleMap}\n * comes back as a {@link NativeModuleProxy} of it, and any other name as\n * `unknown`.\n *\n * Returns `undefined` outside Lynx, or on the background thread when the\n * module is not registered.\n */\n getNativeModule<K extends string>(\n name: K,\n ): K extends keyof NativeModuleMap\n ? NativeModuleProxy<NativeModuleMap[K]> | undefined\n : unknown {\n if (isMainThread()) {\n return (\n typeof lynx !== 'undefined' ? relayedModule('native', name) : undefined\n ) as any;\n }\n if (!this.#hasNativeModules()) {\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`. On the main thread it returns a proxy, as\n * getNativeModule() does.\n *\n * Returns `undefined` when `lynx` is unavailable or, on the background\n * thread, when the module is not registered.\n */\n getJSModule<T = unknown>(name: string): T | undefined {\n if (isMainThread()) {\n return (\n typeof lynx !== 'undefined' ? relayedModule('js', name) : undefined\n ) as T | undefined;\n }\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()`. From the main thread, the\n * background thread registers a copy whose methods call this module's, with\n * their arguments copied as JSON and their return values dropped.\n *\n * No-op when `lynx` is unavailable.\n */\n registerJSModule<T extends object>(name: string, module: T): void {\n if (typeof lynx === 'undefined') {\n return;\n }\n callOnBackground('registerJSModule', name, relayModuleObject(module)).catch(\n () => {\n // Without a background thread there's no registry to add it to.\n },\n );\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 * The overlay's layer, from 1 (the top) to 4 (the lowest), as on\n * `<overlay>`. Lynx's default is 1.\n */\n level?: 1 | 2 | 3 | 4;\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","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` and `restoreRefs`\n * reconstitute a ref from this map when they see a `{ _wvid }` marker in\n * params, and MainThreadRef registers itself here on creation, on both threads.\n */\nexport const __mainThreadRefMap: Record<number | string, { current: unknown }> =\n {};\n\n/**\n * Pending runOnBackground() Promises keyed by `resolveId`. The main thread's\n * listener settles an entry when the background thread's reply arrives.\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 share one\n * monotonic sequence.\n */\nexport const nextResolveId = (): number => __nextResolveId++;\n\n/**\n * Rebuilds `value` with every `{ _wvid }` marker resolved to its MainThreadRef\n * and, when `elements` is set, every `{ elementRefptr }` wrapped as a\n * MainThreadElement.\n */\nconst transform = (value: unknown, elements: boolean): unknown => {\n if (typeof value !== 'object' || value === null) return value;\n if (Array.isArray(value)) {\n return value.map((item) => transform(item, elements));\n }\n const obj = value as Record<string, unknown>;\n if (elements && 'elementRefptr' in obj) {\n return new MainThreadElement(obj['elementRefptr'] as any);\n }\n if ('_wvid' in obj) {\n return __mainThreadRefMap[obj['_wvid'] as number | string] ?? obj;\n }\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = transform(obj[key], elements);\n }\n return result;\n};\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 transform(value, true);\n\n/**\n * Resolves the `{ _wvid }` markers in the arguments the main thread sends a\n * background function to this thread's MainThreadRef, the copy the function\n * would also see through its closure. Element handles are left alone: a\n * MainThreadElement only works on the main thread.\n */\nexport const restoreRefs = (value: unknown): unknown => transform(value, false);\n\n/**\n * Whether `value` is a promise, or any thenable an async function can return.\n */\nconst isThenable = (value: unknown): value is PromiseLike<unknown> =>\n typeof (value as { then?: unknown } | null | undefined)?.then === 'function';\n\n/**\n * The text a failed call sends back. The caller rejects with `new Error(text)`,\n * so an Error sends its message: `String(error)` would come out as\n * \"Error: Error: offline\".\n */\nconst errorText = (e: unknown): string =>\n e instanceof Error ? e.message : String(e);\n\n/**\n * Runs a function the other thread called and sends it the result, as the\n * JSON `{ resolveId, returnValue }` or `{ resolveId, error }` its pending\n * Promise settles from.\n *\n * A returned promise is awaited first, so an async function (anything that\n * awaits `fetch`) delivers its result rather than a promise, which JSON turns\n * into `{}`, and its rejection reaches the caller instead of going unhandled.\n * React Lynx doesn't await here (run-on-background.ts sends `f(...params)` as\n * is), so this is one place not to copy it: fetching on the background thread\n * is the main reason to call it.\n * A synchronous result is sent right away, without a microtask in between.\n * A result JSON can't encode, such as a circular object, is sent as an error,\n * so the caller doesn't wait forever.\n */\nexport const answerCall = (\n resolveId: number,\n run: () => unknown,\n send: (data: string) => void,\n): void => {\n const reply = (result: { returnValue?: unknown; error?: string }): void => {\n let data: string;\n try {\n data = JSON.stringify({ resolveId, ...result });\n } catch (e) {\n data = JSON.stringify({\n resolveId,\n error: `[angular-lynx] The return value can't be sent to the other thread: ${errorText(e)}`,\n });\n }\n send(data);\n };\n let returnValue: unknown;\n try {\n returnValue = run();\n } catch (e) {\n reply({ error: errorText(e) });\n return;\n }\n if (isThenable(returnValue)) {\n returnValue.then(\n (value) => reply({ returnValue: value }),\n (e: unknown) => reply({ error: errorText(e) }),\n );\n } else {\n reply({ returnValue });\n }\n};\n","import { DestroyRef, inject } from '@angular/core';\nimport { __workletMap } from '../worklet-bridge';\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\n/**\n * The DestroyRef of the component, directive or service being constructed, or\n * null outside an injection context, such as at module level. Angular has no\n * public check for an injection context, and `inject()` throws outside one.\n */\nconst constructorDestroyRef = (): DestroyRef | null => {\n try {\n return inject(DestroyRef);\n } catch {\n return null;\n }\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 // A class property with the 'main thread' directive becomes a\n // mainThreadFn() call in the constructor, so each instance registers its\n // own function. Releasing it with the instance keeps a component that's\n // created many times, such as a list row, from piling up registrations.\n constructorDestroyRef()?.onDestroy(() => {\n delete __workletMap[id];\n });\n }\n\n return {\n _wkltId: id,\n _workletType: 'main-thread',\n __isMainThreadFn: true,\n } as MainThreadFnHandle<TArgs, TReturn>;\n};\n","/**\n * The main thread calls a background function by its `_wkltId`, and the\n * background thread finds the function it registered under the same ID. A\n * module that calls backgroundFn() at module level runs on both threads: the\n * background thread's entry imports every such module at startup\n * (background-entry.ts in the build plugin). The build gives each such call an\n * ID from its file and position (cross-thread-transform.ts there), which\n * matches on both threads whatever order their modules load in.\n *\n * A call the build doesn't tag, such as one inside a function, takes the next\n * '__angular_bg_N' instead. That only matches if both threads make the same\n * calls in the same order, and Angular code such as a constructor runs on the\n * main thread only, so its handle reaches no 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\n/**\n * Registers `fn` on the background thread and returns a handle that\n * `runOnBackground()` calls it with from the main thread.\n *\n * @param fn - The function to run on the background thread.\n * @param id - Set by the build for a module-level call, so the handle has the\n * same ID on both threads. Don't pass it yourself.\n * @returns The handle.\n */\nexport const backgroundFn = <TArgs extends unknown[], TReturn>(\n fn: (...args: TArgs) => TReturn,\n id?: string,\n): BackgroundFnHandle<TArgs, TReturn> => {\n const workletId = id ?? '__angular_bg_' + nextBgWorkletId++;\n\n if (!__MAIN_THREAD__) {\n globalThis.registerWorklet('background', workletId, fn);\n }\n\n return {\n _wkltId: workletId,\n _workletType: 'background',\n __isBackgroundFn: true,\n } as BackgroundFnHandle<TArgs, TReturn>;\n};\n","import { __mainThreadRefMap } from '../worklet-bridge';\n\n/**\n * Cross-thread shared reference. Each thread has its own instance, found by\n * its _wvid in __mainThreadRefMap (also the `__workletRefMap` global).\n * When a MainThreadRef is passed as a param to runOnMainThread() or\n * runOnBackground(), JSON.stringify serializes it via toJSON() → { _wvid }.\n * The receiving thread's cross-thread listener (global-callbacks.ts) swaps the\n * marker for its own instance from the map, so the function gets the ref it\n * would also reach through its closure.\n *\n * A ref created at module level exists on both threads: the background\n * thread's entry imports every module that creates one (background-entry.ts\n * in the build plugin). The build gives each such call an ID from its file and\n * position (cross-thread-transform.ts in the build plugin), so it matches on\n * both threads whatever order their modules run in. A ref created anywhere\n * else, such as in a component, exists only on the main thread, where Angular\n * runs, and takes the next number instead.\n */\nlet nextRefId = 0;\n\nexport class MainThreadRef<T> {\n readonly _wvid: number | string;\n #_value: T;\n\n /**\n * @param initValue - The ref's starting value.\n * @param id - Set by the build for a ref created at module level, so the\n * ref has the same ID on both threads. Don't pass it yourself.\n */\n constructor(initValue: T, id?: string) {\n this._wvid = id ?? nextRefId++;\n this.#_value = initValue;\n\n // Both threads register: a ref passed to the other thread arrives as a\n // { _wvid } marker that the receiving thread resolves here.\n __mainThreadRefMap[this._wvid] = this;\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 resolves { _wvid } back to its own registered\n * MainThreadRef instance.\n */\n toJSON(): { _wvid: number | string } {\n return { _wvid: this._wvid };\n }\n}\n\n/**\n * Creates a {@link MainThreadRef}.\n *\n * @param initValue - The ref's starting value.\n * @param id - Set by the build for a ref created at module level. Don't pass\n * it yourself.\n * @returns The new ref.\n */\nexport const createMainThreadRef = <T>(\n initValue: T,\n id?: string,\n): MainThreadRef<T> => new MainThreadRef(initValue, id);\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 { __workletMap } from '../worklet-bridge';\nimport type { MainThreadFnHandle } from './main-thread-fn';\n\n/**\n * Plain functions are also accepted: the worklet build plugin turns one with\n * the 'main thread' directive into a MainThreadFnHandle at compile time, so\n * TypeScript only sees the function, and the directive registers any other\n * function itself.\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 // A desktop browser never fires touch events, so on Lynx for Web a mouse\n // drag needs these. Native Lynx on a phone never fires them, and a mobile\n // browser only fires them after a tap, so binding both is safe.\n mainThreadBindmousedown: ['bindEvent', 'mousedown'],\n mainThreadCatchmousedown: ['catchEvent', 'mousedown'],\n mainThreadBindmousemove: ['bindEvent', 'mousemove'],\n mainThreadCatchmousemove: ['catchEvent', 'mousemove'],\n mainThreadBindmouseup: ['bindEvent', 'mouseup'],\n mainThreadCatchmouseup: ['catchEvent', 'mouseup'],\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// IDs for the plain functions the directive registers itself. They have their\n// own prefix so they never collide with the IDs mainThreadFn() gives.\nlet nextHandlerId = 0;\n\n/**\n * The __AddEvent value that removes a main-thread handler: a worklet with no\n * ID, which runWorklet ignores. `undefined` works on the web, but native Lynx\n * keeps the handler: Element::RemoveEvent erases from `static_events_`, while\n * worklet handlers live in `lepus_events_` (attribute_holder.cc). React Lynx\n * removes them the same way (updateWorkletEvent in workletEvent.ts).\n */\nconst noHandler = (): {\n type: 'worklet';\n value: { _workletType: 'main-thread' };\n} => ({ type: 'worklet', value: { _workletType: 'main-thread' } });\n\n/** A handler the directive has passed to __AddEvent for one of its inputs. */\ntype Registration = {\n eventType: string;\n eventName: string;\n /** The ID the directive registered a plain function under, and releases. */\n ownId?: string;\n};\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)` handlers run on the main thread too (listen() registers\n * them as worklets), but each one goes through Angular's listener wrapper,\n * which marks the view for change detection on every dispatch: too much for\n * gesture-driven UI (scroll-tracking, drag, pinch) that mutates styles at\n * native frame rate. Their event's targets are also plain data.\n * - The `mainThreadBind*` / `mainThreadCatch*` family registers the function\n * itself as a *worklet* with `_workletType: 'main-thread'`, so Lynx invokes\n * it directly, and runWorklet hands it MainThreadElement targets, whose\n * __AddInlineStyle / __SetAttribute calls are synchronous. Angular does no\n * work per event.\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 '[mainThreadBindmousedown],[mainThreadCatchmousedown],' +\n '[mainThreadBindmousemove],[mainThreadCatchmousemove],' +\n '[mainThreadBindmouseup],[mainThreadCatchmouseup],' +\n '[mainThreadBindlongpress],[mainThreadCatchlongpress],' +\n '[mainThreadBindscroll],[mainThreadCatchscroll],' +\n '[mainThreadBindanimationstart],[mainThreadBindanimationend],' +\n '[mainThreadBindtransitionend],[mainThreadBindlayoutchange]',\n inputs: [\n 'mainThreadBindtap',\n 'mainThreadCatchtap',\n 'mainThreadBindtouchstart',\n 'mainThreadCatchtouchstart',\n 'mainThreadBindtouchmove',\n 'mainThreadCatchtouchmove',\n 'mainThreadBindtouchend',\n 'mainThreadCatchtouchend',\n 'mainThreadBindmousedown',\n 'mainThreadCatchmousedown',\n 'mainThreadBindmousemove',\n 'mainThreadCatchmousemove',\n 'mainThreadBindmouseup',\n 'mainThreadCatchmouseup',\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 readonly #registrations = new Map<string, Registration>();\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 mainThreadBindmousedown?: MaybeHandle;\n mainThreadCatchmousedown?: MaybeHandle;\n mainThreadBindmousemove?: MaybeHandle;\n mainThreadCatchmousemove?: MaybeHandle;\n mainThreadBindmouseup?: MaybeHandle;\n mainThreadCatchmouseup?: 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 this.#release(inputName);\n\n const registration: Registration = { eventType, eventName };\n let workletId: string | undefined;\n if (isMainThreadHandle(handle)) {\n workletId = handle._wkltId;\n } else if (typeof handle === 'function') {\n // A function the build didn't wrap, such as a method without the\n // directive. This copy of the app runs on the main thread, where the\n // function already lives, so registering it is all a handle would do.\n // Skipping it would leave the element silently without a handler.\n workletId = '__angular_mts_handler_' + nextHandlerId++;\n registration.ownId = workletId;\n __workletMap[workletId] = handle;\n }\n\n if (workletId === undefined) {\n // null or undefined removes the handler, as unbinding a DOM listener\n // would. Leaving it registered would keep the old handler firing.\n if (this.#registrations.delete(inputName)) {\n __AddEvent(elementRef, eventType, eventName, noHandler());\n }\n continue;\n }\n\n // type: 'worklet' tells the Lynx engine to invoke this handler via the\n // worklet system (runWorklet) on the main thread, NOT via the\n // background-thread event dispatch Lynx defaults to. _workletType:\n // 'main-thread' ensures the handler runs on the Lepus thread where it can\n // call __AddInlineStyle, __SetAttribute, etc. for 60fps animations\n // without cross-thread latency.\n // A new handler for the same event replaces the old one natively.\n __AddEvent(elementRef, eventType, eventName, {\n type: 'worklet',\n value: { _wkltId: workletId, _workletType: 'main-thread' },\n });\n this.#registrations.set(inputName, registration);\n }\n }\n\n ngOnDestroy(): void {\n const elementRef = (this.#el as any).element;\n if (!elementRef) return;\n\n // Lynx's PAPI has no __RemoveEvent: __AddEvent replaces the handler, here\n // with one that does nothing (see noHandler). Without this cleanup, the\n // worklet handle would keep its registration pointing at a destroyed\n // component, and any subsequent native dispatch would invoke a stale\n // closure (or, worse, leak a reference that pins the component graph).\n for (const [inputName, { eventType, eventName }] of this.#registrations) {\n __AddEvent(elementRef, eventType, eventName, noHandler());\n this.#release(inputName);\n }\n this.#registrations.clear();\n }\n\n /**\n * Unregisters the plain function the directive registered for an input, if\n * any, so replacing or removing it doesn't leave the old one in the registry.\n */\n #release(inputName: string): void {\n const ownId = this.#registrations.get(inputName)?.ownId;\n if (ownId !== undefined) {\n delete __workletMap[ownId];\n }\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 Angular\n * code, and getting their return values.\n *\n * Angular runs on the main thread only (see bootstrapApplication), so the\n * call never crosses threads: it invokes the registered worklet in place,\n * with the arguments as they are, and resolves with its result. Non-\n * serializable values (element handles, MainThreadRefs) pass through intact.\n *\n * It used to send the call across threads when it ran on the background\n * thread, for the copy of the app that booted there too. That copy is gone\n * (issue #81), and with it the background-to-main call channel.\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 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 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","import { Injectable } from '@angular/core';\nimport { callOnBackground } from '../background-call';\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 * Lynx has these APIs only on the background thread, while Angular runs on\n * the main thread, so the calls go through the background call relay\n * (background-call.ts).\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 return callOnBackground(\n 'requestResourcePrefetch',\n this.#toNativeData(resources),\n ) as Promise<ResourcePrefetchResult>;\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 return callOnBackground(\n 'cancelResourcePrefetch',\n this.#toNativeData(resources),\n ) as Promise<ResourcePrefetchResult>;\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, signal } from '@angular/core';\nimport type { SystemInfo, PlatformType } from '@lynx-js/types';\nimport { callOnBackground, isMainThread } from '../background-call';\n\n/**\n * The OS version the host app sent in its global props, if it sent one. The\n * apps `ng build --platform` makes send `osVersion`, because the native main\n * thread's `SystemInfo` has none (see {@link LynxSystemInfo.osVersion}).\n */\nconst hostOsVersion = (): string | undefined => {\n const value =\n typeof lynx !== 'undefined'\n ? (lynx.__globalProps as Record<string, unknown> | undefined)?.[\n 'osVersion'\n ]\n : undefined;\n return typeof value === 'string' && value !== '' ? value : undefined;\n};\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 * On iOS and Android (Lynx 4.1), the main thread has no global `SystemInfo`,\n * only `lynx.SystemInfo`, so that's read first. The background thread and the\n * web have the global. The main thread's copy has no `osVersion` either: see\n * {@link LynxSystemInfo.osVersion} for where that comes from instead.\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 * The OS version, from wherever it's known: SystemInfo, the host's global\n * props, or the background thread's SystemInfo, which answers later. A\n * signal, so a `computed()` reading {@link osVersion} sees the late answer.\n */\n readonly #osVersion = signal<string | undefined>(undefined);\n\n constructor() {\n const info =\n (typeof lynx !== 'undefined'\n ? (lynx as { SystemInfo?: SystemInfo }).SystemInfo\n : undefined) ??\n (typeof SystemInfo !== 'undefined' ? SystemInfo : undefined);\n if (!info) {\n throw new Error('SystemInfo is not available in this environment');\n }\n this.#info = info;\n this.#osVersion.set(info.osVersion || hostOsVersion());\n // Lynx builds the native main thread's SystemInfo, where Angular runs,\n // without the OS version (GenerateSystemInfo in Lynx core), so ask the\n // background thread's, which has it. It answers after the first frame, so\n // a host app that knows the version should send it as the `osVersion`\n // global prop, as the generated apps do.\n if (this.#osVersion() === undefined && isMainThread()) {\n callOnBackground('osVersion').then(\n (version) => {\n if (version) this.#osVersion.set(version);\n },\n () => {\n // No background thread to ask: the version stays unknown.\n },\n );\n }\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, such as `'26.1'` on iOS or `'15'`\n * on Android. Empty while it isn't known.\n *\n * The native main thread's SystemInfo lacks it, so there it comes from the\n * host app's `osVersion` global prop, or else from the background thread,\n * which answers shortly after the first frame. It reads a signal, so a\n * `computed()` that reads it updates when the answer arrives.\n */\n get osVersion(): string {\n return this.#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, Injector } 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 // LynxSystemInfo throws where there's no SystemInfo, such as in unit tests,\n // and only `platform` needs it, so it's looked up when that's read.\n readonly #injector = inject(Injector);\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.#injector.get(LynxSystemInfo).platform;\n }\n}\n","import {\n type Injector,\n DestroyRef,\n inject,\n Injectable,\n signal,\n} from '@angular/core';\nimport {\n subscribeSessionStorageFromMainThread,\n unsubscribeSessionStorageFromMainThread,\n} from '../background-call';\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. Subscriptions\n * made there go through the background thread (see background-call.ts).\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 /** Background-thread subscriptions made for main-thread listeners, by listener ID. */\n readonly #relayIds = new Map<number, number>();\n\n /**\n * Lynx for Web's background `lynx` declares the session storage methods\n * (lynx-core is the same script on every platform), but web-core's NativeApp\n * implements none of the ones they forward to: `getSessionStorageItem` throws\n * \"getNativeApp(...).getSessionStorageItem is not a function\" and crashed\n * the session-storage example in the docs' live preview. So the web uses the\n * in-memory fallback, like tests and SSR.\n *\n * `@lynx-js/types`' `PlatformType` leaves out the `'web'` that web-core\n * reports, hence the widening to `string`.\n */\n #hasNativeSessionStorage(): boolean {\n return (\n typeof lynx !== 'undefined' &&\n typeof (lynx as any).setSessionStorageItem === 'function' &&\n !(\n typeof SystemInfo !== 'undefined' &&\n (SystemInfo.platform as string) === 'web'\n )\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 * there uses the local listener map, plus a subscription made through the\n * background thread (see {@link subscribe}).\n */\n #hasNativeSubscription(): boolean {\n return this.#hasNativeSessionStorage() && !this.#isMainThread();\n }\n\n #isMainThread(): boolean {\n return typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__;\n }\n\n /**\n * Undoes setItem's main-thread wrapping of primitives, so callers get back\n * exactly what they stored. Applies wherever a value written on the main\n * thread can come back: main-thread reads, and background-thread reads and\n * notifications. The `Object.keys(raw).length === 1` guard keeps this from\n * mangling genuine user objects: a real payload that happens to have a\n * `__data` key (e.g. `{ __data, other }`) has more than one key and is\n * returned untouched, so only our own single-key wrapper { __data } is\n * unwrapped.\n */\n #unwrap<T>(raw: unknown): T {\n return (\n raw != null &&\n typeof raw === 'object' &&\n '__data' in raw &&\n Object.keys(raw).length === 1\n ? raw.__data\n : raw\n ) as T;\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 (this.#isMainThread()) {\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 (this.#isMainThread()) {\n return Promise.resolve(\n this.#unwrap<T>((lynx as any).getSessionStorageItem(key)),\n );\n }\n\n return new Promise<T>((resolve) => {\n (lynx as any).getSessionStorageItem(key, (value: unknown) =>\n resolve(this.#unwrap<T>(value)),\n );\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 (value: unknown) => callback(this.#unwrap<T>(value)),\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\n // The local map only sees this thread's own writes. On the main thread,\n // another LynxView's writes reach only a native subscription, which only\n // the background thread can make, so subscribe there too.\n if (this.#isMainThread() && this.#hasNativeSessionStorage()) {\n this.#relayIds.set(\n id,\n subscribeSessionStorageFromMainThread(key, (value) =>\n callback(this.#unwrap<T>(value)),\n ),\n );\n }\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 const relayId = this.#relayIds.get(subscription.listenerId);\n if (relayId !== undefined) {\n this.#relayIds.delete(subscription.listenerId);\n unsubscribeSessionStorageFromMainThread(relayId);\n }\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 { callOnBackground } from '../background-call';\n\n/**\n * What the shells' storage modules call back with: `{ value }` for a stored\n * value, `{}` for none, or `{ error }`.\n */\ntype NativeResult = { readonly value?: string; readonly error?: string };\n\n/** Somewhere to keep strings: the native module, the browser, or memory. */\ntype StringStore = {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n clear(): Promise<void>;\n};\n\n/**\n * The part of the browser's `Storage` this uses. The runtime builds without\n * the DOM's types, since Lynx has no DOM.\n */\ntype BrowserStorage = {\n readonly length: number;\n key(index: number): string | null;\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n};\n\n/**\n * A call that never reached a storage module: the host has none, as in Lynx\n * Explorer and tests. It isn't what the module answered, so it sends the\n * service to its in-memory store rather than to the caller.\n */\nclass NoModuleError extends Error {}\n\n/**\n * Calls one of the shells' storage modules, which answer through a callback\n * on the background thread, where `NativeModules` lives (see\n * callNativeModuleAsync in background-call.ts).\n */\nconst nativeStore = (module: string): StringStore => {\n const call = async (method: string, args: string[]) => {\n let result: NativeResult | undefined;\n try {\n result = (await callOnBackground(\n 'callNativeModuleAsync',\n module,\n method,\n args,\n )) as NativeResult | undefined;\n } catch (error) {\n throw new NoModuleError((error as Error).message);\n }\n if (result?.error !== undefined) {\n throw new Error(result.error);\n }\n return result?.value ?? null;\n };\n return {\n getItem: (key) => call('getItem', [key]),\n setItem: async (key, value) => {\n await call('setItem', [key, value]);\n },\n removeItem: async (key) => {\n await call('removeItem', [key]);\n },\n clear: async () => {\n await call('clear', []);\n },\n };\n};\n\n/**\n * The browser's `localStorage`, with each key behind `prefix`, so `clear()`\n * removes only this store's keys and not the rest of the page's.\n */\nconst browserStore = (\n storage: BrowserStorage,\n prefix: string,\n): StringStore => ({\n getItem: async (key) => storage.getItem(prefix + key),\n setItem: async (key, value) => storage.setItem(prefix + key, value),\n removeItem: async (key) => storage.removeItem(prefix + key),\n clear: async () => {\n const keys: string[] = [];\n for (let i = 0; i < storage.length; i++) {\n const key = storage.key(i);\n if (key?.startsWith(prefix)) keys.push(key);\n }\n for (const key of keys) storage.removeItem(key);\n },\n});\n\nconst memoryStore = (): StringStore => {\n const values = new Map<string, string>();\n return {\n getItem: async (key) => values.get(key) ?? null,\n setItem: async (key, value) => {\n values.set(key, value);\n },\n removeItem: async (key) => {\n values.delete(key);\n },\n clear: async () => values.clear(),\n };\n};\n\n/**\n * The page's `localStorage` in Lynx for Web, or undefined elsewhere.\n *\n * Web-core runs the main thread, where Angular runs, in an iframe with the\n * page's origin, so it has the page's `localStorage`. Reading it throws where\n * the browser blocks storage. Elsewhere it's left alone even where it exists,\n * such as in unit tests under jsdom, which stand in for a native host.\n */\nconst browserStorage = (): BrowserStorage | undefined => {\n if (\n typeof SystemInfo === 'undefined' ||\n // `@lynx-js/types`' PlatformType leaves out the 'web' web-core reports.\n (SystemInfo.platform as string) !== 'web'\n ) {\n return undefined;\n }\n try {\n return (globalThis as { localStorage?: BrowserStorage }).localStorage;\n } catch {\n return undefined;\n }\n};\n\n/**\n * Values are stored as JSON. One that isn't, such as a string the host app\n * wrote, comes back as the string it is.\n */\nconst decode = <T>(raw: string): T => {\n try {\n return JSON.parse(raw) as T;\n } catch {\n return raw as T;\n }\n};\n\n/**\n * What {@link LynxLocalStorage} and {@link LynxSecureStorage} share: a\n * key-value store of JSON values with an async API, kept by a native module\n * of the apps `ng build --platform` makes, by `localStorage` on the web, and\n * in memory elsewhere.\n */\nabstract class PersistentStorage {\n readonly #native: StringStore;\n readonly #webPrefix: string;\n readonly #memory = memoryStore();\n /** False once a call found that the host has no native module. */\n #hasModule = true;\n\n /**\n * @param module - The native module's name in `NativeModules`.\n * @param webPrefix - What this store's keys start with in `localStorage`.\n */\n constructor(module: string, webPrefix: string) {\n this.#native = nativeStore(module);\n this.#webPrefix = webPrefix;\n }\n\n /**\n * Resolves with the value stored under `key`, or `null` if there's none.\n */\n async getItem<T = unknown>(key: string): Promise<T | null> {\n const raw = await this.#run((store) => store.getItem(key));\n return raw === null ? null : decode<T>(raw);\n }\n\n /**\n * Stores `value` under `key`, as JSON: an object, an array, a string, a\n * number, a boolean or `null`. Resolves once it's stored.\n */\n async setItem<T = unknown>(key: string, value: T): Promise<void> {\n const raw = JSON.stringify(value);\n if (raw === undefined) {\n throw new TypeError(\n `Can't store a ${typeof value} under \"${key}\": values are stored as JSON.`,\n );\n }\n await this.#run((store) => store.setItem(key, raw));\n }\n\n /**\n * Removes the value stored under `key`, if there is one.\n */\n async removeItem(key: string): Promise<void> {\n await this.#run((store) => store.removeItem(key));\n }\n\n /**\n * Removes every value in this store.\n */\n async clear(): Promise<void> {\n await this.#run((store) => store.clear());\n }\n\n /**\n * Runs `operation` on the store this host has. The native module is tried\n * first, except on the web, and a host without one, which stays without\n * it, gets the in-memory store from then on.\n */\n async #run<R>(operation: (store: StringStore) => Promise<R>): Promise<R> {\n const web = browserStorage();\n if (web) {\n return operation(browserStore(web, this.#webPrefix));\n }\n if (this.#hasModule) {\n try {\n return await operation(this.#native);\n } catch (error) {\n if (!(error instanceof NoModuleError)) throw error;\n this.#hasModule = false;\n }\n }\n return operation(this.#memory);\n }\n}\n\n/**\n * A key-value store that keeps its values after the app closes, like the\n * browser's `localStorage`. Values are JSON (objects, arrays, strings,\n * numbers, booleans) and every method returns a promise.\n *\n * - **iOS:** `UserDefaults`, in a suite of its own.\n * - **Android:** `SharedPreferences`, in a file of its own.\n * - **Web:** the page's `localStorage`, with each key starting with\n * `angular-lynx:`.\n *\n * For tokens and other secrets, use {@link LynxSecureStorage}.\n *\n * Only the apps `ng build --platform` makes have the native module behind\n * it, `AngularLynxLocalStorage`. Elsewhere, such as in Lynx Explorer and\n * tests, it keeps values in memory, so they last until the app closes.\n *\n * @usageNotes\n * ```typescript\n * const storage = inject(LynxLocalStorage);\n *\n * await storage.setItem('settings', { units: 'metric' });\n * const settings = await storage.getItem<Settings>('settings');\n * await storage.removeItem('settings');\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxLocalStorage extends PersistentStorage {\n constructor() {\n super('AngularLynxLocalStorage', 'angular-lynx:');\n }\n}\n\n/**\n * A key-value store for secrets such as tokens, which keeps its values after\n * the app closes, encrypted by the platform. It has the same methods as\n * {@link LynxLocalStorage}.\n *\n * - **iOS:** the Keychain, readable once the phone has been unlocked after it\n * starts, and never copied to another device. The Keychain keeps its items\n * when the app is deleted, so a reinstalled app finds them again.\n * - **Android:** `SharedPreferences`, each value encrypted with AES-GCM by a\n * key the Android Keystore holds. The file is left out of backups, which\n * can't take the key with them.\n * - **Web:** the page's `localStorage`, with each key starting with\n * `angular-lynx-secure:`. Browsers have no store for secrets, and web\n * sign-in libraries keep their tokens there too.\n *\n * Only the apps `ng build --platform` makes have the native module behind\n * it, `AngularLynxSecureStorage`. Elsewhere, such as in Lynx Explorer and\n * tests, it keeps values in memory, so they last until the app closes.\n *\n * @usageNotes\n * ```typescript\n * const storage = inject(LynxSecureStorage);\n *\n * await storage.setItem('session', session);\n * const session = await storage.getItem<Session>('session');\n * await storage.removeItem('session');\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxSecureStorage extends PersistentStorage {\n constructor() {\n super('AngularLynxSecureStorage', 'angular-lynx-secure:');\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 // The web preview's main-thread lynx has no getTextInfo. Native has it on\n // both threads.\n if (\n typeof lynx === 'undefined' ||\n typeof (lynx as any).getTextInfo !== 'function'\n ) {\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 * The Material 3 color roles that dynamic color gives, by Material's names.\n * The error roles aren't here: Material keeps them red whatever the\n * wallpaper.\n */\nexport const DYNAMIC_COLOR_ROLES = [\n 'primary',\n 'onPrimary',\n 'primaryContainer',\n 'onPrimaryContainer',\n 'inversePrimary',\n 'secondary',\n 'onSecondary',\n 'secondaryContainer',\n 'onSecondaryContainer',\n 'tertiary',\n 'onTertiary',\n 'tertiaryContainer',\n 'onTertiaryContainer',\n 'background',\n 'onBackground',\n 'surface',\n 'onSurface',\n 'surfaceVariant',\n 'onSurfaceVariant',\n 'surfaceDim',\n 'surfaceBright',\n 'surfaceContainerLowest',\n 'surfaceContainerLow',\n 'surfaceContainer',\n 'surfaceContainerHigh',\n 'surfaceContainerHighest',\n 'inverseSurface',\n 'inverseOnSurface',\n 'outline',\n 'outlineVariant',\n] as const;\n\nexport type DynamicColorRole = (typeof DYNAMIC_COLOR_ROLES)[number];\n\n/**\n * Each role's color, as a hex color such as `#6750a4`.\n */\nexport type DynamicColorScheme = { readonly [R in DynamicColorRole]: string };\n\n/** The color scheme for each appearance: the app can be in either. */\nexport type DynamicColors = {\n readonly light: DynamicColorScheme;\n readonly dark: DynamicColorScheme;\n};\n\nconst HEX_COLOR = /^#[0-9a-f]{6}$/i;\n\n/**\n * A scheme as the host sent it, if it has a hex color (`#6750a4`) for every\n * role.\n * Half a scheme would mix the wallpaper's colors with the app's, so it counts\n * as none.\n */\nconst parseScheme = (value: unknown): DynamicColorScheme | null => {\n if (typeof value !== 'object' || value === null) return null;\n const colors = value as Record<string, unknown>;\n const scheme: Record<string, string> = {};\n for (const role of DYNAMIC_COLOR_ROLES) {\n const color = colors[role];\n if (typeof color !== 'string' || !HEX_COLOR.test(color)) return null;\n scheme[role] = color;\n }\n return scheme as DynamicColorScheme;\n};\n\nconst parseDynamicColors = (value: unknown): DynamicColors | null => {\n if (typeof value !== 'object' || value === null) return null;\n const { light, dark } = value as Record<string, unknown>;\n const lightScheme = parseScheme(light);\n const darkScheme = parseScheme(dark);\n return lightScheme && darkScheme\n ? { light: lightScheme, dark: darkScheme }\n : null;\n};\n\nconst sameColors = (a: DynamicColors | null, b: DynamicColors | null) =>\n a === b ||\n (a !== null &&\n b !== null &&\n DYNAMIC_COLOR_ROLES.every(\n (role) =>\n a.light[role] === b.light[role] && a.dark[role] === b.dark[role],\n ));\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 /**\n * The colors Android 12 and later take from the user's wallpaper (Material\n * You's dynamic color), as Material 3's color roles in light and dark, or\n * `null` where the host sends none.\n *\n * Lynx has no API for them, so they come from the host app, in its\n * `dynamicColors` global prop: `{ light, dark }`, each with a hex color,\n * such as `#6750a4`, for every role in {@link DYNAMIC_COLOR_ROLES}. The\n * Android app `ng build --platform android` makes sends them, and new ones\n * when the user changes their wallpaper or colors. iOS, the web preview and\n * Lynx Explorer have none.\n *\n * Both schemes come at once, so an app with a dark mode of its own can\n * follow it rather than the phone's.\n */\n readonly dynamicColors = computed(\n () =>\n parseDynamicColors(\n (this.#globalData.globalData() as Record<string, unknown>)[\n 'dynamicColors'\n ],\n ),\n // Every global prop update reaches here, such as new safe-area insets,\n // and the colors seldom change with them.\n { equal: sameColors },\n );\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 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 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 { inject, Injectable } from '@angular/core';\nimport { LynxNativeModule } from '../native-module/native-module';\n\n/**\n * The native module of the apps `ng build --platform` makes\n * (`WebAuthModule.swift` and `WebAuthModule.kt` in `packages/native/templates`).\n */\nconst WEB_AUTH_MODULE = 'AngularLynxWebAuth';\n\n/** What the page is opened with, as the native module reads it. */\ntype WebAuthRequest = {\n readonly url: string;\n readonly callbackScheme: string;\n readonly ephemeral: boolean;\n};\n\n/**\n * How a session ended, as the native module reports it: the URL the page\n * returned to, or why it didn't.\n */\ntype WebAuthResult = {\n readonly url?: string;\n readonly error?: 'canceled' | 'failed';\n readonly message?: string;\n};\n\ntype WebAuthModule = {\n start(\n request: WebAuthRequest,\n done: (result: WebAuthResult) => void,\n ): unknown;\n};\n\n/**\n * Why a web authentication session gave no callback URL:\n * - `canceled`: the person closed the sheet, or declined to open it.\n * - `unavailable`: the host can't open one. Only the apps that\n * `ng build --platform` makes can; Lynx Explorer, the web preview and\n * tests can't.\n * - `failed`: the platform couldn't open the page, or a session was already\n * open.\n */\nexport type WebAuthSessionErrorCode = 'canceled' | 'unavailable' | 'failed';\n\n/** The error a {@link LynxWebAuthSession} rejects with. */\nexport class WebAuthSessionError extends Error {\n constructor(\n readonly code: WebAuthSessionErrorCode,\n message: string,\n ) {\n super(message);\n this.name = 'WebAuthSessionError';\n }\n}\n\n/** What {@link LynxWebAuthSession.start} opens, and where it returns. */\nexport type WebAuthSessionOptions = {\n /** The page that starts the sign-in, such as a provider's authorize URL. */\n readonly url: string;\n /**\n * The URL scheme the page returns to, such as `myapp` for\n * `myapp://auth?code=…`. On Android it must also be one of the app's\n * `deepLinkSchemes`, so the redirect opens the app.\n */\n readonly callbackScheme: string;\n /**\n * Opens the page without the browser's cookies and keeps none it sets, so\n * the person signs in afresh and nothing stays signed in afterwards. iOS\n * only: Android's Custom Tabs share the browser's cookies.\n */\n readonly ephemeral?: boolean;\n};\n\n/**\n * Signs in through a web page, as OAuth and OpenID Connect providers need: it\n * opens the page in the platform's sign-in browser sheet, over the app, and\n * resolves with the URL the page redirects to on the app's own scheme. Read\n * the code or token from that URL.\n *\n * Lynx has no popups or redirects, so a web sign-in flow can't run inside\n * the app. The sheet is the platform's own: ASWebAuthenticationSession on\n * iOS, which asks before opening a site and shares Safari's sign-ins, and a\n * Custom Tab on Android, from which the redirect opens the app again.\n *\n * Only the apps `ng build --platform` makes have the native module behind\n * it. Elsewhere, such as Lynx Explorer, the web preview and tests, `start()`\n * rejects with `unavailable`.\n *\n * @usageNotes\n * ```typescript\n * const webAuth = inject(LynxWebAuthSession);\n *\n * const callback = await webAuth.start({\n * url: 'https://example.com/oauth/authorize?client_id=…&redirect_uri=myapp://auth',\n * callbackScheme: 'myapp',\n * });\n * const code = new URL(callback).searchParams.get('code');\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxWebAuthSession {\n readonly #modules = inject(LynxNativeModule);\n\n /**\n * Opens `url` in the sign-in sheet and resolves with the whole URL the page\n * redirects to on `callbackScheme`, query and fragment included. Rejects\n * with a {@link WebAuthSessionError}.\n */\n start({\n url,\n callbackScheme,\n ephemeral = false,\n }: WebAuthSessionOptions): Promise<string> {\n // On the main thread, where Angular runs, the module is a proxy whose\n // calls go through the background thread: a host without it rejects the\n // call rather than returning no module.\n const module = this.#modules.getNativeModule(WEB_AUTH_MODULE) as\n | WebAuthModule\n | undefined;\n return new Promise((resolve, reject) => {\n const unavailable = (): void =>\n reject(\n new WebAuthSessionError(\n 'unavailable',\n 'This host has no web authentication session. Only the apps `ng build --platform` makes have one.',\n ),\n );\n if (!module) {\n unavailable();\n return;\n }\n Promise.resolve()\n .then(() =>\n module.start({ url, callbackScheme, ephemeral }, (result) => {\n if (result.url !== undefined) {\n resolve(result.url);\n return;\n }\n const code = result.error === 'canceled' ? 'canceled' : 'failed';\n reject(\n new WebAuthSessionError(\n code,\n result.message ??\n (code === 'canceled'\n ? 'The sign-in was canceled.'\n : 'The sign-in page could not be opened.'),\n ),\n );\n }),\n )\n .catch(unavailable);\n });\n }\n}\n","import { type Type, reflectComponentType } from '@angular/core';\n\n/**\n * The Lynx elements a component's host can be, besides the `<view>` every\n * host is by default.\n */\nexport type HostElementTag =\n | 'view'\n | 'text'\n | 'image'\n | 'scroll-view'\n | 'svg'\n | 'blur-view';\n\n/**\n * A component host's tag (`ui-card-title`) → the Lynx element it renders as.\n * Keyed by tag, because that's all `createElement()` gets: Angular creates a\n * child component's host from the parent's template, before the component\n * exists.\n */\nconst hostElements = new Map<string, HostElementTag>();\n\n/** A selector part that is an element name alone, such as `ui-card-title`. */\nconst ELEMENT_SELECTOR = /^[a-z][\\w-]*$/i;\n\n/**\n * Makes a component's host element a Lynx element other than `<view>`, such\n * as a `<text>`. Call it once, next to the component:\n *\n * ```ts\n * @Component({\n * selector: 'app-title',\n * host: { class: 'text-2xl font-semibold' },\n * template: '<ng-content />',\n * })\n * export class AppTitle {}\n *\n * registerHostElement(AppTitle, 'text');\n * ```\n *\n * Every host is a `<view>` otherwise, a real element between the parent and\n * the component's template. A component that shows text then needs a\n * `<text>` inside its host, and a class the app writes on the component\n * (`<app-title class=\"mb-2\">`) lands on the host, which Angular gives every\n * static attribute, as well as on whatever element the component passes it\n * to: a margin there applies twice. With a `<text>` host, the component is\n * one element, the way a component's `<span>` or `<p>` would be on the web.\n *\n * The registration covers each element name in the selector, wherever a\n * template uses the component. Content projected into a `<text>` host follows\n * `<text>`'s rules: raw text, and nested `<text>` that runs inline.\n */\nexport const registerHostElement = (\n component: Type<unknown>,\n element: HostElementTag,\n): void => {\n const selector = reflectComponentType(component)?.selector ?? '';\n const tags = selector\n .split(',')\n .map((part) => part.trim())\n .filter((part) => ELEMENT_SELECTOR.test(part));\n if (tags.length === 0) {\n throw new Error(\n `registerHostElement: ${component.name} isn't a component with an element selector, such as 'app-title'.`,\n );\n }\n for (const tag of tags) hostElements.set(tag, element);\n};\n\n/**\n * The Lynx element to create for a tag: the registered host element for a\n * component's tag, or the tag itself.\n */\nexport const hostElementOf = (tag: string): string =>\n hostElements.get(tag) ?? tag;\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 * * lynx-stack/packages/react/runtime/src/snapshot/list/list.ts,\n * * componentAtChildCtx's `!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 { ANDROID_BLUR_CAPTURE_TARGET, isAndroid } from './android-blur-capture';\nimport {\n __pageElementRef,\n setPageElementRef,\n takePageHandOver,\n} from './page-ref';\n\nimport { createNativeRefByTag } from './create-native-ref';\nimport { hostElementOf } from './host-elements';\nimport {\n createCommentElement,\n createListElement,\n createPageElement,\n} from './element-creators';\nimport type { ElementRef } from '../types/lynx';\nimport type { LynxDocumentBase } from './types';\n\n/**\n * The page a previous app rendered into, emptied, when a hot update\n * bootstraps the app again (see `handOverPageToNextApp`). A Lynx page has one\n * page element, and the engine shows the first one created: a second\n * `__CreatePage()` gives the new app a page that's never shown, while the old\n * app's elements, whose views are gone, stay on screen. Angular's\n * `ApplicationRef.destroy()` doesn't remove a root component's elements (in a\n * browser they also stay in the page), so they're removed here.\n *\n * @returns The page element, or `null` when no re-bootstrap handed one over.\n */\nconst takeOverPage = (): ElementRef | null => {\n const page = __pageElementRef;\n if (!takePageHandOver() || !page) return null;\n for (const child of __GetChildren(page) ?? []) {\n __RemoveElement(page, child);\n }\n return page;\n};\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 = takeOverPage() ?? __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 if (isAndroid()) {\n // What every blur-view blurs on Android (see create-blur-view-element).\n __SetID(pageElement, ANDROID_BLUR_CAPTURE_TARGET);\n }\n this.#pageId = __GetElementUniqueID(pageElement);\n setPageElementRef(pageElement);\n return this.page;\n }\n createElement(name: string, value?: string): LynxElement | LynxListElement {\n // A component's host is a view, unless the component registered another\n // element for it (registerHostElement).\n const tag = hostElementOf(name);\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 // Before any attribute is set: a blur-view with no attributes must still\n // set its (empty) material, or it inherits a parent blur-view's.\n if (tag === 'blur-view') {\n el.updateBlurMaterial();\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 { hostElementOf } from '../lynx-document/host-elements';\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 // The snapshot holds the element the host registered (registerHostElement),\n // so the wrapper takes its tag too.\n el.tagName = hostElementOf(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 type { BaseLynxElement } from '../lynx-element';\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 marks elements so the component's scoped CSS\n * matches only them.\n *\n * On the web, Angular's EmulatedEncapsulationDomRenderer2 gives every element\n * the component creates a `_ngcontent-<id>` attribute, and each host element a\n * `_nghost-<id>` attribute, and the compiler scopes the component's selectors\n * with them. Lynx's CSS engine can't match attribute selectors, so the build\n * plugin turns them into class selectors (toLynxScopedCss in the plugin's\n * component-styles.ts), and this renderer adds classes instead. The plugin\n * sets ɵcmp.id, which is `id` here, to the scope ID the CSS was compiled with.\n */\nexport class EmulatedLynxRenderer extends LynxRenderer {\n readonly #contentClass: string;\n readonly #hostClass: string;\n\n constructor(document: LynxDocumentBase, componentId: string) {\n super(document);\n this.#contentClass = `_ngcontent-${componentId}`;\n this.#hostClass = `_nghost-${componentId}`;\n }\n\n /**\n * Marks a host element of this component type, for `:host` selectors.\n * LynxRendererFactory2 calls it for each component instance, as Angular's\n * DomRendererFactory2 does.\n */\n applyToHost(element: BaseLynxElement): void {\n element.addScopeClass(this.#hostClass);\n }\n\n override createElement(\n name: string,\n namespace?: string | null,\n ): BaseLynxElement {\n const element = super.createElement(name, namespace);\n element.addScopeClass(this.#contentClass);\n return element;\n }\n\n override selectRootElement() {\n const el = super.selectRootElement();\n this.applyToHost(el);\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, endCdTiming, startCdTiming } from '../devtools/stats';\nimport type { LynxDocumentBase } from '../lynx-document';\nimport {\n processPendingAttributeRemovals,\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.Emulated) {\n // ShadowDom (and Angular's experimental isolated variant) needs a shadow\n // root, which Lynx elements don't have. Their styles compile unscoped,\n // so they apply app-wide, as with None.\n if (type && type.encapsulation !== ViewEncapsulation.None) {\n console.warn(\n 'ViewEncapsulation.ShadowDom is not supported in Lynx. Falling back to no encapsulation.',\n );\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 // Angular calls createRenderer for each component instance, with its host\n // element. The bootstrap root has none here; selectRootElement marks it.\n if (hostElement) {\n renderer.applyToHost(hostElement);\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 // Build-time `define` gate — false in the Vitest config, so this\n // profiling call is dead code from the test bundle's point of view.\n /* v8 ignore start */\n if (__PROFILE__) {\n startCdTiming();\n }\n /* v8 ignore stop */\n }\n /**\n * Called by Angular after every change detection cycle completes.\n * 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\"). The cycle's attribute removals follow, for the same\n * flush (see processPendingAttributeRemovals).\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 * In development builds, the cycle's duration, timed from begin(), is\n * recorded on every return path, the flush included: it's how long the\n * cycle kept the main thread busy.\n */\n end?(): void {\n try {\n // This change-detection cycle is finishing: clear the flag first, on\n // EVERY return path, so mutations after this point are correctly seen\n // as outside-a-cycle (see begin() / scheduleSettleFlush). The flush\n // below is unconditional, so clearing the flag now does not affect it.\n setInsideChangeDetection(false);\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).\n // Drained even while the first-render flush is skipped: the\n // __RemoveElement calls mutate native elements directly, and native\n // performs its own flush once renderPage returns.\n processPendingRemovals();\n // Then the attributes removed this cycle and not set again: Lynx would\n // apply a removal after a value set in the same flush (see\n // LynxElement's #removedAttributes), so they wait until now.\n processPendingAttributeRemovals();\n // Re-derive positional edge whitespace for texts mutated this cycle,\n // after removals (so torn-down subtrees are skipped) and before the\n // flush (so the corrected text is painted in the same pass). Runs even\n // while the first render's explicit flush is skipped: it only mutates\n // native `text` attributes directly, which native commits in its own\n // post-renderPage flush — same rationale as processPendingRemovals\n // above.\n processPendingTextNormalization();\n if (!isFirstRenderPending()) {\n __FlushElementTree();\n }\n processPendingListUpdates();\n } finally {\n // In `finally` so a cycle that returns early or throws still ends its\n // timing: the start times nest, so a missed end would pair every later\n // cycle's end with the wrong start. Gated like the counters above.\n /* v8 ignore start */\n if (__PROFILE__) {\n endCdTiming();\n }\n /* v8 ignore stop */\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 { 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. The document (LynxDocument, or LynxHydrateDocument for SSR)\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 // Angular runs on the main thread only (see bootstrapApplication), so\n // the document always creates native elements: through PAPI, or by\n // reusing the snapshot's while SSR hydrates.\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 },\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 bites the *web* runtime: ImagePerformanceWarning.start() early-\n // returns when `PerformanceObserver` is undefined, which is the case in\n // native Lynx's JS engines. On web, Lynx runs JavaScript in a browser realm\n // (first the background thread's Web Worker, now the main thread's iframe),\n // which *does* have PerformanceObserver, so it proceeded to getDocument()\n // 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, type Injector, signal } from '@angular/core';\n\ntype HistoryEntry = { state: unknown; url: string };\n\n/**\n * The history a hot update's re-bootstrap hands from the old app's strategy to\n * the new one's (see {@link carryOverLocation}). It lives at module level\n * because the runtime's module isn't re-run by a hot update, while the app's\n * injectors, and the strategy in them, are.\n */\nlet carriedOver: HistorySnapshot | undefined;\n\ntype HistorySnapshot = { history: HistoryEntry[]; index: number };\n\n/**\n * Reads a strategy's history. Assigned in the class's static block, the only\n * place outside its methods that can reach its private fields, which keeps the\n * snapshot out of the class's public API.\n */\nlet snapshotOf: (strategy: LynxLocationStrategy) => HistorySnapshot;\n\n/**\n * Keeps the app on the screen it was showing when a hot update re-bootstraps\n * it. Called with the old app's injector before it's destroyed, it saves the\n * old strategy's history, and the next strategy created starts from it. The\n * router's initial navigation then goes to the current URL instead of `/`,\n * and Back still has the screens before it.\n *\n * Does nothing for an app without the router, or with another strategy.\n *\n * @param injector - The injector of the app that's about to be destroyed.\n */\nexport const carryOverLocation = (injector: Injector | undefined): void => {\n const strategy = injector?.get(LocationStrategy, null);\n if (strategy instanceof LynxLocationStrategy) {\n carriedOver = snapshotOf(strategy);\n }\n};\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: HistoryEntry[] = [{ state: null, url: '/' }];\n #historyIndex = 0;\n #listeners: LocationChangeListener[] = [];\n readonly #canGoBack = signal(false);\n\n constructor() {\n super();\n if (carriedOver) {\n this.#history = carriedOver.history;\n this.#historyIndex = carriedOver.index;\n this.#path = this.#history[this.#historyIndex].url;\n this.#canGoBack.set(this.#historyIndex > 0);\n carriedOver = undefined;\n }\n }\n\n static {\n snapshotOf = (strategy) => ({\n history: strategy.#history.map((entry) => ({ ...entry })),\n index: strategy.#historyIndex,\n });\n }\n\n /**\n * Whether there's an entry before the current one, so `back()` goes\n * somewhere. The Android back button follows it (see lynx-back-button.ts):\n * while it's false, back leaves the app, as on any root screen.\n */\n readonly canGoBack = this.#canGoBack.asReadonly();\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.#canGoBack.set(true);\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.#canGoBack.set(target > 0);\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 * Opt-in: `provideRouter()` doesn't install it, so leaving a route destroys\n * its components, as Angular does on the web. Provide it yourself to keep\n * every visited route's component, and its state, alive:\n *\n * ```typescript\n * providers: [\n * provideRouter(routes),\n * { provide: RouteReuseStrategy, useClass: LynxRouteReuseStrategy },\n * ]\n * ```\n *\n * Nothing is ever evicted, and `ngOnDestroy()` doesn't run when you leave a\n * route.\n *\n * ## Why it exists\n *\n * `provideRouter()` used to install it. A crash investigation in May 2026\n * blamed a ~256-slot native element pool that `__RemoveElement` never freed,\n * and detaching views was meant to reuse their elements. Neither holds on\n * Lynx 4.1 (measured October 2026 on the iOS Simulator and an Android\n * emulator, issue #68): 400 navigations between two 300-element routes\n * created 121,527 native elements without a crash, with this strategy and\n * with Angular's default alike. A re-attached view's native elements were\n * destroyed when it was detached, so `LynxElement` rebuilds them from cache\n * (`#recreateSubtree`), and a revisit creates as many elements as a fresh\n * route.\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, so the component and its state live on.\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 { Location, LocationStrategy } from '@angular/common';\nimport { effect, inject, Injectable } from '@angular/core';\nimport { LynxNativeModule } from '../native-module/native-module';\nimport { LynxLocationStrategy } from './lynx-location-strategy';\n\n/**\n * The native module and global event of the Android app that\n * `ng build --platform android` makes (`ShellModule.kt` in\n * `packages/native/templates/android`).\n */\nconst SHELL_MODULE = 'AngularLynxShell';\nconst BACK_EVENT = 'angularLynxBack';\n\ntype ShellModule = {\n setBackHandlerEnabled(enabled: boolean): unknown;\n};\n\ntype GlobalEventEmitter = {\n addListener(name: string, listener: () => void): unknown;\n};\n\n/**\n * Connects the Android back button to the router, so that it goes back a\n * screen, as the browser's back button does in a web app, and leaves the app\n * from the first one.\n *\n * Android decides whether an app handles back when the gesture starts, before\n * JavaScript could answer, so the shell can't ask the app each time. Instead\n * back is Android's (it leaves the app) until the app enables the shell's\n * handler, and while it's enabled each press arrives as the `angularLynxBack`\n * global event. This keeps the handler enabled while the router has a screen to\n * go back to, and turns each press into `Location.back()`. The router then\n * navigates as for the browser's back button, running guards and resolvers.\n *\n * Other hosts (the iOS app, Lynx Explorer, the web preview) have no\n * `AngularLynxShell` module and never send the event, so this does nothing\n * there. An app with its own `LocationStrategy` keeps Android's back, because\n * only `LynxLocationStrategy` says whether there's somewhere to go back to.\n *\n * Created by `provideRouter()`.\n */\n@Injectable({ providedIn: 'root' })\nexport class LynxBackButton {\n constructor() {\n const strategy = inject(LocationStrategy);\n if (!(strategy instanceof LynxLocationStrategy)) return;\n const location = inject(Location);\n const modules = inject(LynxNativeModule);\n\n // On the main thread, where Angular runs, both are proxies whose calls go\n // through the background thread and return promises. A host without the\n // module rejects the call, and then never gets another.\n const shell = modules.getNativeModule(SHELL_MODULE) as\n | ShellModule\n | undefined;\n let hasShell = true;\n effect(() => {\n const enabled = strategy.canGoBack();\n if (!hasShell) return;\n Promise.resolve()\n .then(() => shell?.setBackHandlerEnabled(enabled))\n .catch(() => (hasShell = false));\n });\n\n const emitter =\n modules.getJSModule<GlobalEventEmitter>('GlobalEventEmitter');\n Promise.resolve()\n .then(() => emitter?.addListener(BACK_EVENT, () => location.back()))\n .catch(() => {\n // Without a background thread there are no global events to hear.\n });\n }\n}\n","import { LocationStrategy, PlatformLocation } from '@angular/common';\nimport {\n type EnvironmentProviders,\n inject,\n makeEnvironmentProviders,\n provideEnvironmentInitializer,\n} from '@angular/core';\nimport {\n provideRouter as ngProvideRouter,\n RouterLinkActive,\n type RouterFeatures,\n type Routes,\n withRouterConfig,\n} from '@angular/router';\nimport { LynxBackButton } from './lynx-back-button';\nimport { LynxLocationStrategy } from './lynx-location-strategy';\nimport { LynxPlatformLocation } from './lynx-platform-location';\nimport { ROUTER_LINK_ACTIVE_CHANGE } from './lynx-router-link-active';\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 // No RouteReuseStrategy: leaving a route destroys it, as Angular does on\n // the web. This used to install LynxRouteReuseStrategy against a supposed\n // ~256-slot native element pool. Measured on Lynx 4.1 (iOS and Android,\n // October 2026), there's no such limit, and the strategy saved no\n // elements anyway: a re-attached route rebuilds them (#recreateSubtree in\n // lynx-element.ts). See lynx-route-reuse-strategy.ts.\n ngProvideRouter(\n routes,\n // Unhandled navigation promise rejections (e.g. from unmatched routes or\n // lazy chunk loading failures) left a blank 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 // The Android back button goes back through this router's history, like\n // the browser's back button on the web (see lynx-back-button.ts).\n provideEnvironmentInitializer(() => inject(LynxBackButton)),\n // Lets LYNX_ELEMENTS mark an active routerLinkActive element `selected`\n // for screen readers without importing the router itself (see\n // lynx-router-link-active.ts). Taps reach Angular's own RouterLink without\n // help: the renderer delivers a tap to its `click` listener.\n {\n provide: ROUTER_LINK_ACTIVE_CHANGE,\n useValue: () =>\n inject(RouterLinkActive, { self: true, optional: true })\n ?.isActiveChange ?? null,\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 * Legacy error codes of the DOMException names code here can raise, which\n * older code still checks (`error.code === 20` for an abort).\n */\nconst CODES: Record<string, number> = {\n NotSupportedError: 9,\n InvalidStateError: 11,\n SyntaxError: 12,\n InvalidAccessError: 15,\n NetworkError: 19,\n AbortError: 20,\n TimeoutError: 23,\n};\n\n/**\n * `DOMException` for Lynx's main thread, which has none. Angular's HTTP\n * backends create one when a request times out\n * (`new DOMException('signal timed out', 'TimeoutError')`); without the\n * global, that line threw a ReferenceError in a timer instead of failing the\n * request.\n */\nexport class LynxDOMException extends Error {\n readonly code: number;\n\n constructor(message = '', name = 'Error') {\n super(message);\n this.name = name;\n this.code = CODES[name] ?? 0;\n }\n}\n","/**\n * The Fetch Standard's `Headers` for Lynx's main thread, which has no Fetch\n * API. Angular's `FetchBackend` reads a response's headers through it\n * (`response.headers.get('content-type')`, and `new HttpHeaders(headers)`,\n * which iterates anything that is `instanceof Headers`).\n */\n\nexport type HeadersInit =\n | LynxHeaders\n | Iterable<readonly [string, string]>\n | Record<string, string>;\n\n/** RFC 9110's `token`: the characters a header name may use. */\nconst NAME = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\n\nconst normalizeValue = (value: unknown): string => {\n // Leading and trailing HTTP whitespace is dropped, as browsers do.\n const normalized = String(value).replace(/^[\\t\\n\\r ]+|[\\t\\n\\r ]+$/g, '');\n if (/[\\r\\n]/.test(normalized) || normalized.includes('\\0')) {\n throw new TypeError(`Invalid header value: ${JSON.stringify(value)}`);\n }\n return normalized;\n};\n\nconst normalizeName = (name: unknown): string => {\n const normalized = String(name);\n if (!NAME.test(normalized)) {\n throw new TypeError(`Invalid header name: ${JSON.stringify(name)}`);\n }\n return normalized.toLowerCase();\n};\n\nexport class LynxHeaders {\n /** Each header in the order it was added, with its name lowercased. */\n #list: [name: string, value: string][] = [];\n\n constructor(init?: HeadersInit | null) {\n if (init == null) return;\n if (init instanceof LynxHeaders) {\n this.#list = init.#list.map(([name, value]) => [name, value]);\n } else if (typeof (init as any)[Symbol.iterator] === 'function') {\n for (const pair of init as Iterable<readonly string[]>) {\n if (pair.length !== 2) {\n throw new TypeError(\n \"Failed to construct 'Headers': Invalid value: each header must be a [name, value] pair\",\n );\n }\n this.append(pair[0] as string, pair[1] as string);\n }\n } else {\n for (const name of Object.keys(init)) {\n this.append(name, (init as Record<string, string>)[name] as string);\n }\n }\n }\n\n append(name: string, value: string): void {\n this.#list.push([normalizeName(name), normalizeValue(value)]);\n }\n\n delete(name: string): void {\n const key = normalizeName(name);\n this.#list = this.#list.filter(([listed]) => listed !== key);\n }\n\n /**\n * The header's values joined with \", \", or null if it isn't set.\n */\n get(name: string): string | null {\n const key = normalizeName(name);\n const values = this.#list\n .filter(([listed]) => listed === key)\n .map(([, value]) => value);\n return values.length > 0 ? values.join(', ') : null;\n }\n\n /**\n * Each `Set-Cookie` value: the one header that can't be joined.\n */\n getSetCookie(): string[] {\n return this.#list\n .filter(([name]) => name === 'set-cookie')\n .map(([, value]) => value);\n }\n\n has(name: string): boolean {\n const key = normalizeName(name);\n return this.#list.some(([listed]) => listed === key);\n }\n\n set(name: string, value: string): void {\n const key = normalizeName(name);\n const index = this.#list.findIndex(([listed]) => listed === key);\n if (index === -1) {\n this.append(key, value);\n return;\n }\n // The first entry keeps its place and takes the value; the rest go.\n this.#list[index] = [key, normalizeValue(value)];\n this.#list = this.#list.filter(\n ([listed], i) => listed !== key || i === index,\n );\n }\n\n forEach(\n callback: (value: string, name: string, parent: LynxHeaders) => void,\n thisArg?: unknown,\n ): void {\n for (const [name, value] of this.entries()) {\n callback.call(thisArg, value, name, this);\n }\n }\n\n /**\n * The headers sorted by name, with each name's values joined, except\n * `Set-Cookie`, which is listed once per value, as the standard says.\n */\n *entries(): IterableIterator<[string, string]> {\n const names = [...new Set(this.#list.map(([name]) => name))].sort();\n for (const name of names) {\n if (name === 'set-cookie') {\n for (const value of this.getSetCookie()) yield [name, value];\n } else {\n yield [name, this.get(name) as string];\n }\n }\n }\n\n *keys(): IterableIterator<string> {\n for (const [name] of this.entries()) yield name;\n }\n\n *values(): IterableIterator<string> {\n for (const [, value] of this.entries()) yield value;\n }\n\n [Symbol.iterator](): IterableIterator<[string, string]> {\n return this.entries();\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 { utf8Encode } from '../url/percent-encoding';\n\n/**\n * `TextEncoder` and `TextDecoder` for Lynx's main thread, which has neither\n * (PrimJS implements only the JavaScript language). Angular's `FetchBackend`\n * decodes every `json` and `text` response with `new TextDecoder()`, so\n * `HttpClient` can't read a response without one. UTF-8 only: the Encoding\n * Standard's other encodings aren't needed for that, and an unknown label\n * throws a RangeError, as browsers do, which `FetchBackend` catches and falls\n * back to UTF-8.\n *\n * Lynx's background thread has `TextCodecHelper` instead (see the Lynx\n * networking guide), which the main thread lacks too.\n */\n\nconst UTF8_LABELS = new Set([\n 'unicode-1-1-utf-8',\n 'unicode11utf8',\n 'unicode20utf8',\n 'utf-8',\n 'utf8',\n 'x-unicode20utf8',\n]);\n\nconst REPLACEMENT_CHARACTER = 0xfffd;\nconst BYTE_ORDER_MARK = 0xfeff;\n\n/** See SLICE in base64.ts. */\nconst SLICE = 8192;\n\ntype BufferSource = ArrayBuffer | ArrayBufferView;\n\nconst toBytes = (input: BufferSource | undefined): Uint8Array => {\n if (input === undefined) return new Uint8Array(0);\n if (ArrayBuffer.isView(input)) {\n return new Uint8Array(input.buffer, input.byteOffset, input.byteLength);\n }\n if (input instanceof ArrayBuffer) return new Uint8Array(input);\n throw new TypeError(\n \"Failed to execute 'decode' on 'TextDecoder': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'.\",\n );\n};\n\n/**\n * The length of the UTF-8 sequence a lead byte starts, or 1 if it's invalid.\n */\nconst sequenceLength = (lead: number): number => {\n if (lead >= 0xc2 && lead <= 0xdf) return 2;\n if (lead >= 0xe0 && lead <= 0xef) return 3;\n if (lead >= 0xf0 && lead <= 0xf4) return 4;\n return 1;\n};\n\n/**\n * How many of `bytes` can be decoded now: all but a multi-byte sequence cut\n * off at the end, which a streaming decode keeps for the next call.\n */\nconst completeLength = (bytes: ArrayLike<number>): number => {\n for (let back = 1; back <= 3 && back <= bytes.length; back++) {\n const byte = bytes[bytes.length - back] as number;\n if ((byte & 0xc0) !== 0x80) {\n return sequenceLength(byte) > back ? bytes.length - back : bytes.length;\n }\n }\n return bytes.length;\n};\n\nexport class LynxTextEncoder {\n readonly encoding = 'utf-8';\n\n encode(input = ''): Uint8Array {\n return new Uint8Array(utf8Encode(String(input)));\n }\n\n encodeInto(\n source: string,\n destination: Uint8Array,\n ): { read: number; written: number } {\n let read = 0;\n let written = 0;\n for (const char of String(source)) {\n const bytes = utf8Encode(char);\n if (written + bytes.length > destination.length) break;\n destination.set(bytes, written);\n written += bytes.length;\n read += char.length;\n }\n return { read, written };\n }\n}\n\nexport class LynxTextDecoder {\n readonly encoding = 'utf-8';\n readonly fatal: boolean;\n readonly ignoreBOM: boolean;\n /** Bytes of a sequence a streaming decode cut off, kept for the next call. */\n #pending: number[] = [];\n /** Whether this stream has produced output yet, so a BOM can only lead it. */\n #started = false;\n\n constructor(\n label = 'utf-8',\n options: { fatal?: boolean; ignoreBOM?: boolean } = {},\n ) {\n if (!UTF8_LABELS.has(String(label).trim().toLowerCase())) {\n throw new RangeError(\n `The encoding label provided ('${label}') is invalid or isn't supported on Lynx, which only decodes UTF-8.`,\n );\n }\n this.fatal = !!options.fatal;\n this.ignoreBOM = !!options.ignoreBOM;\n }\n\n decode(input?: BufferSource, options: { stream?: boolean } = {}): string {\n let bytes: ArrayLike<number> = toBytes(input);\n if (this.#pending.length > 0) {\n bytes = [...this.#pending, ...Array.from(bytes)];\n }\n const end = options.stream ? completeLength(bytes) : bytes.length;\n this.#pending = Array.from({ length: bytes.length - end }, (_, i) =>\n Number(bytes[end + i]),\n );\n let output = this.#decode(bytes, end);\n if (\n !this.ignoreBOM &&\n !this.#started &&\n output.charCodeAt(0) === BYTE_ORDER_MARK\n ) {\n output = output.slice(1);\n }\n this.#started = options.stream ? this.#started || output !== '' : false;\n return output;\n }\n\n /**\n * The Encoding Standard's UTF-8 decoder: an invalid sequence becomes one\n * U+FFFD, or a TypeError when `fatal`. Unlike the URL polyfill's\n * utf8Decode(), which only sees short URL parts, it builds the string in\n * slices, since a response body can be megabytes long.\n */\n #decode(bytes: ArrayLike<number>, end: number): string {\n let output = '';\n const codes: number[] = [];\n const invalid = () => {\n if (this.fatal) {\n throw new TypeError(\n \"Failed to execute 'decode' on 'TextDecoder': The encoded data was not valid.\",\n );\n }\n codes.push(REPLACEMENT_CHARACTER);\n };\n let index = 0;\n while (index < end) {\n const lead = bytes[index] as number;\n if (lead < 0x80) {\n codes.push(lead);\n index++;\n } else {\n const needed = sequenceLength(lead) - 1;\n // The first continuation byte's valid range narrows for some leads,\n // which rules out overlong encodings and surrogates.\n let lower = lead === 0xe0 ? 0xa0 : lead === 0xf0 ? 0x90 : 0x80;\n let upper = lead === 0xed ? 0x9f : lead === 0xf4 ? 0x8f : 0xbf;\n let codePoint = lead & (0xff >> (needed + 2));\n let seen = 0;\n while (seen < needed && index + 1 + seen < end) {\n const next = bytes[index + 1 + seen] as number;\n if (next < lower || next > upper) break;\n lower = 0x80;\n upper = 0xbf;\n codePoint = (codePoint << 6) | (next & 0x3f);\n seen++;\n }\n if (needed === 0 || seen < needed) {\n // The byte that broke the sequence starts the next one.\n invalid();\n index += 1 + seen;\n } else {\n if (codePoint > 0xffff) {\n codePoint -= 0x10000;\n codes.push(\n 0xd800 | (codePoint >> 10),\n 0xdc00 | (codePoint & 0x3ff),\n );\n } else {\n codes.push(codePoint);\n }\n index += 1 + needed;\n }\n }\n if (codes.length >= SLICE) {\n output += String.fromCharCode(...codes);\n codes.length = 0;\n }\n }\n return output + String.fromCharCode(...codes);\n }\n}\n","import { callOnBackground } from '../background-call';\nimport type {\n RelayedBody,\n RelayedRequest,\n RelayedResponse,\n} from './background-fetch';\nimport { base64ToBytes, bytesToBase64 } from './base64';\nimport { LynxHeaders, type HeadersInit } from './headers';\nimport { LynxTextDecoder, LynxTextEncoder } from './text-codec';\n\n/**\n * `fetch`, `Request` and `Response` for Lynx's main thread.\n *\n * Lynx has `fetch` on the background thread only, and Angular runs on the\n * main thread, so `HttpClient` (whose default backend, `FetchBackend`, calls\n * `globalThis.fetch`), `httpResource` and any library that calls `fetch`\n * failed there. This `fetch` sends each request to the background thread\n * through callOnBackground() and builds the `Response` from what comes back\n * (background-fetch.ts has the other half).\n *\n * The whole body arrives at once: Lynx's own `fetch` doesn't stream unless\n * the page sets `enableFetchAPIStandardStreaming`, and the relay carries one\n * message per call. So `response.body` yields one chunk, and a download\n * reports its progress once, when it's done.\n *\n * Bodies can be strings, `URLSearchParams`, `ArrayBuffer`s and typed arrays.\n * A `Blob`, `FormData` or `ReadableStream` body throws a TypeError: Lynx has\n * no `Blob` or `FormData` and its `fetch` doesn't take them, and a stream\n * can't cross threads.\n */\n\n/** What a body holds: text, bytes, or nothing. */\ntype BodySource = string | Uint8Array | null;\n\nexport type RequestInit = {\n method?: string;\n headers?: HeadersInit;\n body?: unknown;\n signal?: AbortSignal | null;\n cache?: string;\n credentials?: string;\n integrity?: string;\n keepalive?: boolean;\n mode?: string;\n priority?: string;\n redirect?: string;\n referrer?: string;\n referrerPolicy?: string;\n};\n\nexport type ResponseInit = {\n status?: number;\n statusText?: string;\n headers?: HeadersInit;\n};\n\nconst toBytes = (source: BodySource): Uint8Array =>\n typeof source === 'string'\n ? new LynxTextEncoder().encode(source)\n : (source ?? new Uint8Array(0));\n\nconst unsupportedBody = (kind: string) =>\n new TypeError(\n `${kind} request bodies aren't supported on Lynx. Send a string, URLSearchParams, an ArrayBuffer or a typed array.`,\n );\n\n/**\n * Turns a `BodyInit` into text or bytes, and the `Content-Type` it implies.\n * Bytes are copied, so changing the caller's buffer later doesn't change the\n * request.\n */\nconst extractBody = (\n body: unknown,\n): { source: BodySource; type: string | null } => {\n if (body == null) return { source: null, type: null };\n if (typeof body === 'string') {\n return { source: body, type: 'text/plain;charset=UTF-8' };\n }\n if (body instanceof ArrayBuffer) {\n return { source: new Uint8Array(body.slice(0)), type: null };\n }\n if (ArrayBuffer.isView(body)) {\n return {\n source: new Uint8Array(\n body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength),\n ),\n type: null,\n };\n }\n if (\n typeof URLSearchParams !== 'undefined' &&\n body instanceof URLSearchParams\n ) {\n return {\n source: body.toString(),\n type: 'application/x-www-form-urlencoded;charset=UTF-8',\n };\n }\n for (const kind of ['Blob', 'FormData', 'ReadableStream']) {\n const type = (globalThis as any)[kind];\n if (typeof type === 'function' && body instanceof type) {\n throw unsupportedBody(kind);\n }\n }\n if (typeof (body as any).getReader === 'function') {\n throw unsupportedBody('ReadableStream');\n }\n return { source: String(body), type: 'text/plain;charset=UTF-8' };\n};\n\n/**\n * The single-chunk `ReadableStream` a body exposes as `body`: enough for\n * `getReader()` and `for await`, which is how Angular's `FetchBackend` and\n * most libraries read a stream.\n */\nclass LynxBodyStream {\n #chunk: Uint8Array | null;\n #onRead: () => void;\n locked = false;\n\n constructor(chunk: Uint8Array, onRead: () => void) {\n this.#chunk = chunk.length > 0 ? chunk : null;\n this.#onRead = onRead;\n }\n\n getReader() {\n if (this.locked) {\n throw new TypeError(\n \"Failed to execute 'getReader' on 'ReadableStream': ReadableStreamDefaultReader constructor can only accept readable streams that are not yet locked to a reader\",\n );\n }\n this.locked = true;\n this.#onRead();\n let released = false;\n return {\n read: async (): Promise<\n { done: false; value: Uint8Array } | { done: true; value: undefined }\n > => {\n if (released) {\n throw new TypeError('This reader has been released');\n }\n const chunk = this.#chunk;\n this.#chunk = null;\n return chunk\n ? { done: false, value: chunk }\n : { done: true, value: undefined };\n },\n cancel: async (): Promise<void> => {\n this.#chunk = null;\n },\n releaseLock: (): void => {\n released = true;\n this.locked = false;\n },\n closed: Promise.resolve(undefined),\n };\n }\n\n async cancel(): Promise<void> {\n this.#onRead();\n this.#chunk = null;\n }\n\n async *[Symbol.asyncIterator](): AsyncGenerator<Uint8Array> {\n const reader = this.getReader();\n for (;;) {\n const { done, value } = await reader.read();\n if (done) return;\n yield value;\n }\n }\n}\n\n/**\n * What `Request` and `Response` share: the body and the ways to read it.\n */\nabstract class LynxBody {\n #source: BodySource;\n #used = false;\n #stream: LynxBodyStream | undefined;\n\n abstract readonly headers: LynxHeaders;\n\n constructor(source: BodySource) {\n this.#source = source;\n }\n\n get body(): LynxBodyStream | null {\n if (this.#source === null) return null;\n this.#stream ??= new LynxBodyStream(toBytes(this.#source), () => {\n this.#used = true;\n });\n return this.#stream;\n }\n\n get bodyUsed(): boolean {\n return this.#used;\n }\n\n /**\n * The body for sending to the other thread, without consuming it.\n */\n protected relayedBody(): RelayedBody {\n const source = this.#source;\n if (source === null) return null;\n return typeof source === 'string'\n ? { text: source }\n : { base64: bytesToBase64(source) };\n }\n\n /**\n * The body for a clone, which must not share the original's stream.\n */\n protected cloneSource(): BodySource {\n if (this.#used) {\n throw new TypeError(\n \"Failed to execute 'clone': the body is already used\",\n );\n }\n return this.#source;\n }\n\n async #consume(): Promise<BodySource> {\n if (this.#used) {\n throw new TypeError(\n \"Failed to execute 'text' on 'Body': body stream already read\",\n );\n }\n this.#used = true;\n return this.#source;\n }\n\n async text(): Promise<string> {\n const source = await this.#consume();\n // `text()` always decodes UTF-8, whatever the Content-Type says.\n return typeof source === 'string'\n ? source\n : new LynxTextDecoder().decode(toBytes(source));\n }\n\n async json(): Promise<unknown> {\n return JSON.parse(await this.text());\n }\n\n async bytes(): Promise<Uint8Array> {\n return toBytes(await this.#consume());\n }\n\n async arrayBuffer(): Promise<ArrayBuffer> {\n const bytes = await this.bytes();\n return bytes.buffer.slice(\n bytes.byteOffset,\n bytes.byteOffset + bytes.byteLength,\n ) as ArrayBuffer;\n }\n\n async blob(): Promise<Blob> {\n const BlobType = (globalThis as any).Blob as typeof Blob | undefined;\n if (typeof BlobType !== 'function') {\n throw new TypeError('Lynx has no Blob. Use arrayBuffer() instead.');\n }\n return new BlobType([await this.arrayBuffer()], {\n type: this.headers.get('content-type') ?? '',\n });\n }\n\n async formData(): Promise<never> {\n throw new TypeError('Lynx has no FormData. Use text() or json() instead.');\n }\n}\n\n/** The methods the Fetch Standard uppercases. Others, such as PATCH, keep their case. */\nconst NORMALIZED_METHODS = new Set([\n 'DELETE',\n 'GET',\n 'HEAD',\n 'OPTIONS',\n 'POST',\n 'PUT',\n]);\n\n/**\n * Parses a request URL. There's no page URL on Lynx to resolve a relative\n * one against (Lynx's HTTP services reject it as \"unsupported URL\"), so it\n * must be absolute.\n */\nconst parseUrl = (input: string): string => {\n try {\n return new URL(input).href;\n } catch {\n throw new TypeError(\n `Failed to parse URL from ${input}. Lynx has no page URL to resolve a relative URL against, so requests need an absolute URL.`,\n );\n }\n};\n\n/** The Fetch Standard's defaults for a request's other options. */\nconst DEFAULT_OPTIONS: {\n cache: string;\n credentials: string;\n integrity: string;\n keepalive: boolean;\n mode: string;\n priority: string;\n redirect: string;\n referrer: string;\n referrerPolicy: string;\n} = {\n cache: 'default',\n credentials: 'same-origin',\n integrity: '',\n keepalive: false,\n mode: 'cors',\n priority: 'auto',\n redirect: 'follow',\n referrer: 'about:client',\n referrerPolicy: '',\n};\n\n/**\n * A signal that never aborts, for requests made without one.\n */\nconst neverAborts = (): AbortSignal => new AbortController().signal;\n\nexport class LynxRequest extends LynxBody {\n readonly url: string;\n readonly method: string;\n readonly headers: LynxHeaders;\n readonly signal: AbortSignal;\n readonly cache: string;\n readonly credentials: string;\n readonly integrity: string;\n readonly keepalive: boolean;\n readonly mode: string;\n readonly priority: string;\n readonly redirect: string;\n readonly referrer: string;\n readonly referrerPolicy: string;\n readonly destination = '';\n\n constructor(input: string | URL | LynxRequest, init: RequestInit = {}) {\n const base = input instanceof LynxRequest ? input : undefined;\n const method = init.method ?? base?.method ?? 'GET';\n const upper = method.toUpperCase();\n const normalizedMethod = NORMALIZED_METHODS.has(upper) ? upper : method;\n const { source, type } =\n init.body !== undefined\n ? extractBody(init.body)\n : { source: base ? base.cloneSource() : null, type: null };\n if (source !== null && (upper === 'GET' || upper === 'HEAD')) {\n throw new TypeError(\n \"Failed to construct 'Request': Request with GET/HEAD method cannot have body.\",\n );\n }\n super(source);\n this.url = base ? base.url : parseUrl(String(input));\n this.method = normalizedMethod;\n this.headers = new LynxHeaders(init.headers ?? base?.headers);\n if (type !== null && !this.headers.has('content-type')) {\n this.headers.set('content-type', type);\n }\n this.signal = init.signal ?? base?.signal ?? neverAborts();\n const options: typeof DEFAULT_OPTIONS = base ?? DEFAULT_OPTIONS;\n this.cache = init.cache ?? options.cache;\n this.credentials = init.credentials ?? options.credentials;\n this.integrity = init.integrity ?? options.integrity;\n this.keepalive = init.keepalive ?? options.keepalive;\n this.mode = init.mode ?? options.mode;\n this.priority = init.priority ?? options.priority;\n this.redirect = init.redirect ?? options.redirect;\n this.referrer = init.referrer ?? options.referrer;\n this.referrerPolicy = init.referrerPolicy ?? options.referrerPolicy;\n }\n\n clone(): LynxRequest {\n return new LynxRequest(this);\n }\n\n /**\n * The request as fetchForMainThread() takes it.\n */\n toRelayed(): RelayedRequest {\n return {\n url: this.url,\n method: this.method,\n headers: [...this.headers.entries()],\n body: this.relayedBody(),\n // Only what the caller set: Lynx ignores these, and Lynx for Web's\n // worker would apply them to a request it could make without them.\n options: Object.fromEntries(\n Object.entries(DEFAULT_OPTIONS)\n .filter(([name, value]) => (this as any)[name] !== value)\n .map(([name]) => [name, (this as any)[name]]),\n ),\n };\n }\n}\n\n/**\n * A body that's already text or bytes, which internal callers pass to the\n * constructors so it isn't converted again.\n */\nclass ExtractedBody {\n constructor(readonly source: BodySource) {}\n}\n\n/** Values only a response from the network has. */\ntype NetworkDetails = {\n url: string;\n redirected: boolean;\n type: string;\n};\n\nexport class LynxResponse extends LynxBody {\n readonly status: number;\n readonly statusText: string;\n readonly headers: LynxHeaders;\n readonly url: string;\n readonly redirected: boolean;\n /**\n * `basic` for a response from the network: Lynx's HTTP services have no\n * CORS, so there are no `cors` or `opaque` responses.\n */\n readonly type: string;\n\n constructor(\n body?: unknown,\n init: ResponseInit = {},\n details: NetworkDetails = { url: '', redirected: false, type: 'default' },\n ) {\n const status = init.status ?? 200;\n if (\n details.type === 'default' &&\n (!Number.isInteger(status) || status < 200 || status > 599)\n ) {\n throw new RangeError(\n `Failed to construct 'Response': The status provided (${status}) is outside the range [200, 599].`,\n );\n }\n const { source, type } =\n body instanceof ExtractedBody\n ? { source: body.source, type: null }\n : extractBody(body);\n super(source);\n this.status = status;\n this.statusText = init.statusText ?? '';\n this.headers = new LynxHeaders(init.headers);\n if (type !== null && !this.headers.has('content-type')) {\n this.headers.set('content-type', type);\n }\n this.url = details.url;\n this.redirected = details.redirected;\n this.type = details.type;\n }\n\n get ok(): boolean {\n return this.status >= 200 && this.status < 300;\n }\n\n clone(): LynxResponse {\n return new LynxResponse(\n new ExtractedBody(this.cloneSource()),\n {\n status: this.status,\n statusText: this.statusText,\n headers: this.headers,\n },\n { url: this.url, redirected: this.redirected, type: this.type },\n );\n }\n\n static error(): LynxResponse {\n return new LynxResponse(\n null,\n { status: 0 },\n { url: '', redirected: false, type: 'error' },\n );\n }\n\n static json(data: unknown, init: ResponseInit = {}): LynxResponse {\n const response = new LynxResponse(\n new ExtractedBody(JSON.stringify(data)),\n init,\n );\n if (!response.headers.has('content-type')) {\n response.headers.set('content-type', 'application/json');\n }\n return response;\n }\n\n static redirect(url: string, status = 302): LynxResponse {\n if (![301, 302, 303, 307, 308].includes(status)) {\n throw new RangeError(\n `Failed to execute 'redirect' on 'Response': Invalid status code ${status}`,\n );\n }\n return new LynxResponse(null, {\n status,\n headers: { location: parseUrl(url) },\n });\n }\n\n /**\n * Builds the response the background thread sent.\n *\n * @param relayed - The response from fetchForMainThread().\n * @returns The response.\n */\n static fromRelayed(relayed: RelayedResponse): LynxResponse {\n const body = relayed.body;\n const source: BodySource =\n body === null\n ? null\n : 'text' in body\n ? body.text\n : base64ToBytes(body.base64);\n return new LynxResponse(\n new ExtractedBody(source),\n {\n status: relayed.status,\n statusText: relayed.statusText,\n headers: relayed.headers,\n },\n { url: relayed.url, redirected: relayed.redirected, type: 'basic' },\n );\n }\n}\n\nlet nextFetchId = 0;\n\n/**\n * `fetch` for Lynx's main thread: runs the request on the background thread\n * and resolves with its response. It rejects with the signal's reason when\n * the signal aborts, which also aborts the background thread's request, and\n * with a TypeError when the request fails.\n *\n * @param input - The URL, or a Request.\n * @param init - The request's options.\n * @returns The response.\n */\nexport const relayFetch = (\n input: string | URL | LynxRequest,\n init?: RequestInit,\n): Promise<LynxResponse> =>\n new Promise((resolve, reject) => {\n const request = new LynxRequest(input, init);\n const { signal } = request;\n if (signal.aborted) {\n reject(signal.reason);\n return;\n }\n const id = nextFetchId++;\n let settled = false;\n /**\n * Removed once the request settles, so it only runs while in flight.\n */\n const onAbort = () => {\n settled = true;\n reject(signal.reason);\n callOnBackground('abortFetch', id).catch(() => {});\n };\n signal.addEventListener('abort', onAbort);\n const settle = (fn: () => void) => {\n signal.removeEventListener('abort', onAbort);\n if (settled) return;\n settled = true;\n fn();\n };\n callOnBackground('fetch', id, request.toRelayed()).then(\n (relayed) => settle(() => resolve(LynxResponse.fromRelayed(relayed))),\n (error: Error) => settle(() => reject(new TypeError(error.message))),\n );\n });\n","import { LynxDOMException } from './dom-exception';\nimport { LynxHeaders } from './headers';\n\n/**\n * `XMLHttpRequest` for Lynx, which has none on either thread, built on the\n * thread's `fetch` (on the main thread, fetch.ts's relay). Angular's\n * `HttpXhrBackend` (`provideHttpClient(withXhr())`) uses it, as do libraries\n * such as axios, which pick XHR whenever it exists.\n *\n * It's asynchronous only: a synchronous request would have to block the\n * thread until another thread answers. Like the relayed `fetch`, the body\n * arrives in one piece, so `progress` fires once, when it's done, and an\n * upload's `progress` fires once the response starts.\n */\n\ntype Listener = (event: XhrEvent) => void;\n\n/** The event objects XHR listeners get. */\nexport type XhrEvent = {\n type: string;\n target: unknown;\n currentTarget: unknown;\n lengthComputable: boolean;\n loaded: number;\n total: number;\n};\n\n/**\n * Listeners by type, plus the `on<type>` properties, for the request and `upload`.\n */\nclass XhrEventTarget {\n #listeners = new Map<string, Set<Listener>>();\n onloadstart: Listener | null = null;\n onprogress: Listener | null = null;\n onabort: Listener | null = null;\n onerror: Listener | null = null;\n onload: Listener | null = null;\n ontimeout: Listener | null = null;\n onloadend: Listener | null = null;\n\n addEventListener(type: string, listener: Listener | null): void {\n if (!listener) return;\n let listeners = this.#listeners.get(type);\n if (!listeners) {\n listeners = new Set();\n this.#listeners.set(type, listeners);\n }\n listeners.add(listener);\n }\n\n removeEventListener(type: string, listener: Listener | null): void {\n if (listener) this.#listeners.get(type)?.delete(listener);\n }\n\n dispatchEvent(event: { type: string }): boolean {\n const full: XhrEvent = {\n lengthComputable: false,\n loaded: 0,\n total: 0,\n ...event,\n target: this,\n currentTarget: this,\n };\n const handler = (this as any)[`on${event.type}`];\n if (typeof handler === 'function') handler.call(this, full);\n // A copy, so a listener that adds or removes listeners doesn't change\n // who this event reaches, as with EventTarget.\n for (const listener of Array.from(this.#listeners.get(event.type) ?? [])) {\n listener.call(this, full);\n }\n return true;\n }\n\n /**\n * Fires a progress-style event with byte counts.\n */\n protected fire(type: string, loaded = 0, total = 0): void {\n this.dispatchEvent({\n type,\n lengthComputable: total > 0,\n loaded,\n total,\n } as XhrEvent);\n }\n}\n\nclass XhrUpload extends XhrEventTarget {\n /**\n * Lets the request fire the upload's events.\n */\n emit(type: string, loaded?: number, total?: number): void {\n this.fire(type, loaded, total);\n }\n}\n\nconst UNSENT = 0;\nconst OPENED = 1;\nconst HEADERS_RECEIVED = 2;\nconst LOADING = 3;\nconst DONE = 4;\n\n/**\n * The size of a body for upload progress, as far as it can be known.\n */\nconst bodySize = (body: unknown): number => {\n if (typeof body === 'string') return body.length;\n if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n return body.byteLength;\n }\n return 0;\n};\n\nexport class LynxXMLHttpRequest extends XhrEventTarget {\n static readonly UNSENT = UNSENT;\n static readonly OPENED = OPENED;\n static readonly HEADERS_RECEIVED = HEADERS_RECEIVED;\n static readonly LOADING = LOADING;\n static readonly DONE = DONE;\n readonly UNSENT = UNSENT;\n readonly OPENED = OPENED;\n readonly HEADERS_RECEIVED = HEADERS_RECEIVED;\n readonly LOADING = LOADING;\n readonly DONE = DONE;\n\n readonly upload = new XhrUpload();\n onreadystatechange: Listener | null = null;\n readyState = UNSENT;\n status = 0;\n statusText = '';\n responseURL = '';\n responseType: XMLHttpRequestResponseType = '';\n response: unknown = '';\n timeout = 0;\n withCredentials = false;\n\n #method = 'GET';\n #url = '';\n #requestHeaders = new LynxHeaders();\n #responseHeaders = new LynxHeaders();\n #responseText = '';\n #controller: AbortController | undefined;\n /** Counts sends, so a request that was aborted or reopened ignores its old fetch. */\n #generation = 0;\n #timer: ReturnType<typeof setTimeout> | undefined;\n /** Whether the upload's events are still to come. */\n #uploading = false;\n\n get responseText(): string {\n if (this.responseType !== '' && this.responseType !== 'text') {\n throw new LynxDOMException(\n `Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'text' (was '${this.responseType}').`,\n 'InvalidStateError',\n );\n }\n return this.#responseText;\n }\n\n open(method: string, url: string | URL, async = true): void {\n if (!async) {\n throw new LynxDOMException(\n \"Failed to execute 'open' on 'XMLHttpRequest': Synchronous requests aren't supported on Lynx, where the request runs on another thread.\",\n 'InvalidAccessError',\n );\n }\n this.#cancel();\n this.#method = method;\n this.#url = String(url);\n this.#requestHeaders = new LynxHeaders();\n this.#reset();\n this.#setReadyState(OPENED);\n }\n\n setRequestHeader(name: string, value: string): void {\n this.#assertOpened('setRequestHeader');\n this.#requestHeaders.append(name, value);\n }\n\n send(body: unknown = null): void {\n this.#assertOpened('send');\n const generation = ++this.#generation;\n const controller = new AbortController();\n this.#controller = controller;\n const method = this.#method.toUpperCase();\n const sendsBody = method !== 'GET' && method !== 'HEAD' && body != null;\n const uploadSize = sendsBody ? bodySize(body) : 0;\n this.#uploading = sendsBody;\n this.fire('loadstart');\n if (sendsBody) this.upload.emit('loadstart', 0, uploadSize);\n if (this.timeout > 0) {\n this.#timer = setTimeout(() => {\n if (generation !== this.#generation) return;\n this.#fail('timeout');\n }, this.timeout);\n }\n const current = () => generation === this.#generation;\n Promise.resolve()\n .then(() =>\n globalThis.fetch(this.#url, {\n method: this.#method,\n headers: this.#requestHeaders as unknown as HeadersInit,\n body: sendsBody ? (body as BodyInit) : undefined,\n credentials: this.withCredentials ? 'include' : 'same-origin',\n signal: controller.signal,\n }),\n )\n .then(async (response) => {\n if (!current()) return;\n this.#uploadDone(uploadSize);\n this.status = response.status;\n this.statusText = response.statusText;\n this.responseURL = response.url;\n this.#responseHeaders = new LynxHeaders(\n response.headers as unknown as Iterable<[string, string]>,\n );\n this.#setReadyState(HEADERS_RECEIVED);\n this.#setReadyState(LOADING);\n const size = await this.#readResponse(response);\n if (!current()) return;\n this.#finish();\n this.fire('progress', size, size);\n this.#setReadyState(DONE);\n this.fire('load', size, size);\n this.fire('loadend', size, size);\n })\n .catch(() => {\n // An abort or a timeout has already ended the request.\n if (current()) this.#fail('error');\n });\n }\n\n abort(): void {\n if (this.#controller && this.readyState !== DONE) {\n this.#fail('abort');\n }\n if (this.readyState === DONE) {\n this.readyState = UNSENT;\n }\n }\n\n getResponseHeader(name: string): string | null {\n return this.readyState >= HEADERS_RECEIVED\n ? this.#responseHeaders.get(name)\n : null;\n }\n\n /**\n * Each header as `name: value`, one per line, the way browsers list them.\n */\n getAllResponseHeaders(): string {\n if (this.readyState < HEADERS_RECEIVED) return '';\n let headers = '';\n for (const [name, value] of this.#responseHeaders) {\n headers += `${name}: ${value}\\r\\n`;\n }\n return headers;\n }\n\n overrideMimeType(_mime: string): void {\n // Only UTF-8 text is decoded, so there's no charset to override.\n }\n\n /**\n * Reads the body into `response` for `responseType`, and returns its size\n * for the progress events. Text is read as text, so the relayed `fetch`\n * doesn't turn it into bytes only for this to decode them again.\n */\n async #readResponse(response: Response): Promise<number> {\n const type = this.responseType;\n if (type === 'arraybuffer' || type === 'blob') {\n const buffer = await response.arrayBuffer();\n const BlobType = (globalThis as any).Blob as typeof Blob | undefined;\n this.response =\n type === 'arraybuffer'\n ? buffer\n : typeof BlobType === 'function'\n ? new BlobType([buffer], {\n type: this.#responseHeaders.get('content-type') ?? '',\n })\n : // Lynx has no Blob, so there's nothing to return.\n null;\n return buffer.byteLength;\n }\n const text = await response.text();\n if (type === 'json') {\n try {\n this.response = text === '' ? null : JSON.parse(text);\n } catch {\n this.response = null;\n }\n } else if (type === 'document') {\n // There's no DOM to parse into.\n this.response = null;\n } else {\n this.#responseText = text;\n this.response = text;\n }\n const length = Number(this.#responseHeaders.get('content-length'));\n return Number.isFinite(length) && length > 0 ? length : text.length;\n }\n\n /**\n * Fires the upload's closing events, once the response starts.\n */\n #uploadDone(size: number): void {\n if (!this.#uploading) return;\n this.#uploading = false;\n this.upload.emit('progress', size, size);\n this.upload.emit('load', size, size);\n this.upload.emit('loadend', size, size);\n }\n\n /**\n * Ends a request that didn't load: a network error, an abort or a timeout.\n */\n #fail(type: 'error' | 'abort' | 'timeout'): void {\n this.#cancel();\n this.#reset();\n this.#setReadyState(DONE);\n if (this.#uploading) {\n this.#uploading = false;\n this.upload.emit(type);\n this.upload.emit('loadend');\n }\n this.fire(type);\n this.fire('loadend');\n }\n\n /**\n * Stops the request in flight, if any, so its result is ignored.\n */\n #cancel(): void {\n this.#generation++;\n this.#finish();\n this.#controller?.abort();\n this.#controller = undefined;\n }\n\n #finish(): void {\n if (this.#timer !== undefined) clearTimeout(this.#timer);\n this.#timer = undefined;\n }\n\n #reset(): void {\n this.status = 0;\n this.statusText = '';\n this.responseURL = '';\n this.response =\n this.responseType === '' || this.responseType === 'text' ? '' : null;\n this.#responseText = '';\n this.#responseHeaders = new LynxHeaders();\n }\n\n #assertOpened(method: string): void {\n if (this.readyState !== OPENED || this.#controller) {\n throw new LynxDOMException(\n `Failed to execute '${method}' on 'XMLHttpRequest': The object's state must be OPENED.`,\n 'InvalidStateError',\n );\n }\n }\n\n #setReadyState(state: number): void {\n this.readyState = state;\n this.dispatchEvent({ type: 'readystatechange' });\n }\n}\n","import { LynxDOMException } from './dom-exception';\nimport { LynxRequest, LynxResponse, relayFetch } from './fetch';\nimport { LynxHeaders } from './headers';\nimport { LynxTextDecoder, LynxTextEncoder } from './text-codec';\nimport { LynxXMLHttpRequest } from './xhr';\n\nexport {\n LynxDOMException,\n LynxHeaders,\n LynxRequest,\n LynxResponse,\n LynxTextDecoder,\n LynxTextEncoder,\n LynxXMLHttpRequest,\n relayFetch,\n};\n\n/**\n * Installs the web's network APIs on `target`, Lynx's main thread, where\n * they're missing: `fetch` (relayed to the background thread's), `Headers`,\n * `Request`, `Response`, `XMLHttpRequest`, `TextEncoder`, `TextDecoder` and\n * `DOMException`. With them, `provideHttpClient()` works as it does in a\n * browser, whichever backend it uses (`FetchBackend` by default, or\n * `HttpXhrBackend` with `withXhr()`), and so do `httpResource` and libraries\n * that call `fetch` or XHR.\n *\n * Each is installed only where it's missing, so the web preview, whose main\n * thread is a browser frame, keeps its own. Takes the global as a parameter\n * so tests can pass a stand-in, as installUrl() does.\n *\n * @param target - The global object.\n */\nexport const installNetworkGlobals = (\n target: Record<string, unknown>,\n): void => {\n const install = (name: string, value: unknown) => {\n if (typeof target[name] === 'undefined') target[name] = value;\n };\n install('TextEncoder', LynxTextEncoder);\n install('TextDecoder', LynxTextDecoder);\n install('DOMException', LynxDOMException);\n // The classes go together: the relayed fetch builds a LynxResponse, and\n // Angular checks `headers instanceof Headers`.\n if (typeof target['fetch'] === 'undefined') {\n install('fetch', relayFetch);\n install('Headers', LynxHeaders);\n install('Request', LynxRequest);\n install('Response', LynxResponse);\n }\n install('XMLHttpRequest', LynxXMLHttpRequest);\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 { isMainThread } from './background-call';\nimport { installNetworkGlobals } from './network';\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// Lynx's main thread has no fetch, XMLHttpRequest, Headers, TextDecoder or\n// DOMException, and the background thread, which has fetch, runs no Angular.\n// So HttpClient, httpResource and fetch-based libraries failed wherever they\n// ran. These versions send each request to the background thread's fetch.\n// The background thread keeps its own globals: its fetch is passed into the\n// bundle's wrapper function, so it isn't on globalThis and would look missing.\nif (isMainThread()) {\n installNetworkGlobals(globalThis as unknown as Record<string, unknown>);\n}\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 { ReplaySubject } from 'rxjs';\nimport {\n applyGlobalDataUpdate,\n applyInitDataUpdate,\n} from './data-flow/host-updates';\nimport { ssrEncode, ssrHydrate } from './ssr/ssr-callbacks';\nimport {\n __mainThreadRefMap,\n __pendingResolvers,\n __workletMap,\n answerCall,\n nextResolveId,\n restoreRefs,\n transformParams,\n} from './worklet-bridge';\n\n/**\n * Calls the worklet registered as `id` on this thread. A missing one throws,\n * which a cross-thread call sends back as its error: resolving `undefined`\n * would hide an ID that differs between the threads, such as a worklet\n * defined inside a function instead of at module level.\n */\nconst callWorklet = (id: string, args: unknown[], kind: string): unknown => {\n const fn = __workletMap[id];\n if (!fn) {\n throw new Error(`[angular-lynx] ${kind} not found: ${id}`);\n }\n return fn(...args);\n};\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 *\n * It replays, because the engine calls renderPage once per page, and a hot\n * update can bootstrap the app again after that. That includes after a first\n * bootstrap that failed, which leaves no app to tell a re-bootstrap from a\n * first boot by.\n */\nexport const pageReady = new ReplaySubject<void>(1);\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, with the page's\n * InitData. On the main thread, bootstrapApplication() awaits this before\n * calling Angular's bootstrap.\n * - updatePage: called when the host app sends updated InitData.\n * - updateGlobalProps: called when the host app changes the GlobalData.\n * - processData: called before data delivery for transformation. Overridden by\n * registerDataProcessors() if the app needs custom data processing.\n *\n * The engine calls renderPage, updatePage and updateGlobalProps on the main\n * thread only. The background thread hears about host updates through hooks\n * on lynx.getApp() instead (further down).\n *\n * Lynx stores InitData nowhere the app can read it, so the runtime keeps it as\n * `lynx.__initData`, where React Lynx keeps it and LynxInitData seeds from.\n * Each thread receives it differently: the main thread through renderPage(data)\n * (below), the background thread through the loadCard params (further down).\n */\n// @ts-expect-error\nglobalThis.renderPage = (data?: Record<string, unknown>) => {\n if (typeof lynx !== 'undefined') {\n (lynx as any).__initData = data ?? {};\n }\n pageReady.next();\n};\n\n// The main thread is where the UI is drawn, so its copy of LynxInitData must\n// hear about updates. `resetPageData` is set when the host resets the data\n// instead of updating it. React Lynx's updatePage merges the same way.\n// @ts-expect-error\nglobalThis.updatePage = (\n data?: Record<string, unknown>,\n options?: { resetPageData?: boolean },\n) => {\n if (typeof lynx !== 'undefined') {\n applyInitDataUpdate(data, !!options?.resetPageData);\n }\n};\n\n// Native Lynx calls this global unless an engine listener (below) is\n// registered for the same event. Native has already set lynx.__globalProps\n// to `data` by then; applyGlobalDataUpdate() sets it too, for the web.\n(globalThis as any).updateGlobalProps = (data?: Record<string, unknown>) => {\n if (typeof lynx !== 'undefined') {\n applyGlobalDataUpdate(data);\n }\n};\n\n// @lynx-js/web-core never calls the updateGlobalProps global. It only\n// dispatches `__UpdateGlobalProps` to listeners on lynx.getEngine(), with the\n// call's arguments as `data`. Newer native engines do the same once a listener\n// exists, instead of calling the global. Either way the update arrives once.\nif (\n __MAIN_THREAD__ &&\n typeof lynx !== 'undefined' &&\n typeof (lynx as any).getEngine === 'function'\n) {\n (lynx as any)\n .getEngine()\n .addEventListener('__UpdateGlobalProps', (event: { data?: unknown[] }) =>\n applyGlobalDataUpdate(event.data?.[0]),\n );\n}\n\n// The engine hands processData's return value to renderPage and to the\n// background thread, so the default must pass the data through unchanged, as\n// React Lynx's default processor does. Native Lynx falls back to the original\n// data when the result isn't an object, but @lynx-js/web-core doesn't, so a\n// no-op that returned undefined dropped every app's InitData on the web.\n// @ts-expect-error\nglobalThis.processData = (data?: Record<string, unknown>) => data;\n\n// The background thread gets no renderPage call. lynx-core keeps the params it\n// loaded the page with on the app instead: `initData`, plus any `updateData`\n// the host sent before the page loaded, which wins. React Lynx merges them the\n// same way. `getApp` is checked because it's missing outside a real Lynx\n// host, such as in unit tests.\nif (\n !__MAIN_THREAD__ &&\n typeof lynx !== 'undefined' &&\n typeof (lynx as any).getApp === 'function'\n) {\n const app = (lynx as any).getApp();\n const params = app._params;\n (lynx as any).__initData = { ...params?.initData, ...params?.updateData };\n\n /**\n * Host updates reach the background thread through the updateCardData and\n * updateGlobalProps hooks below, which lynx-core leaves for the framework to\n * define, as React Lynx does. Lynx emits no GlobalEventEmitter event for\n * them itself, so the hooks emit React Lynx's `onDataChanged` and\n * `onGlobalPropsChanged` through this, for app code that listens for them.\n */\n const emit = (eventName: string, args: unknown[]): void =>\n lynx.getJSModule?.('GlobalEventEmitter')?.emit?.(eventName, args);\n\n app.updateCardData = (\n data?: Record<string, unknown>,\n options?: { type?: number },\n ) => {\n // `__lynx_timing_flag` only marks the update for performance timing; it\n // isn't page data. React Lynx drops it too.\n const { __lynx_timing_flag: _timingFlag, ...patch } = data ?? {};\n // Type 1 is a reset (NativeUpdateDataType.RESET in React Lynx).\n applyInitDataUpdate(patch, options?.type === 1);\n emit('onDataChanged', [patch]);\n };\n app.updateGlobalProps = (data?: Record<string, unknown>) => {\n emit('onGlobalPropsChanged', [applyGlobalDataUpdate(data)]);\n };\n}\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: the main thread calls background functions with\n// 'Lynx.Worklet.runOnBackground', and the background thread replies with\n// 'Lynx.Worklet.BgFunctionCallRet'. resolveId ties each reply to its Promise.\n// There's no call the other way: Angular runs on the main thread only, so\n// LynxMainThread.runOnMainThread() runs its function in place (issue #81).\nif (__MAIN_THREAD__) {\n try {\n if (typeof lynx !== 'undefined' && (lynx as any).getJSContext) {\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: the background thread runs the main thread's\n// runOnBackground requests.\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 // 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 // answerCall awaits an async function, such as one that fetches,\n // before replying.\n answerCall(\n resolveId,\n () =>\n callWorklet(\n worklet._wkltId,\n params.map(restoreRefs),\n 'Background function',\n ),\n (data) =>\n (lynx as any).getCoreContext().dispatchEvent({\n type: 'Lynx.Worklet.BgFunctionCallRet',\n data,\n }),\n );\n },\n );\n }\n } catch {\n // lynx.getCoreContext() may not be available in all environments\n }\n}\n\n/**\n * Synchronously invoke a registered worklet by its _wkltId with raw,\n * already-in-process args. Used by LynxMainThread.runOnMainThread(): Angular\n * code runs on the main thread, where the worklets are, so the call needs no\n * thread hop. The args never go through JSON, so refs and element handles are\n * still the real objects. Exposed as a global (rather than imported) because\n * the __workletMap is a module-load side-effect while LynxMainThread is\n * DI-instantiated later.\n */\nglobalThis.__lynxRunMainThreadWorklet = (\n wkltId: string,\n args: unknown[],\n): unknown => callWorklet(wkltId, args, 'Main-thread worklet');\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, the global exposure bridge, the background call relay and the log\n// relay. They are all the background thread runs of the runtime, since Angular\n// boots on the main thread only. `pageReady` is the only value bootstrap itself\n// needs from them (renderPage readiness).\nimport './error-reporting';\nimport './polyfills';\nimport { pageReady } from './global-callbacks';\nimport './exposure/global-exposure-bridge';\nimport './background-call';\nimport './lynx-logger/lynx-logger';\nimport { installLazyBundleLoader } from './lazy-bundle/chunk-loader';\nimport { handOverPageToNextApp } from './lynx-document/page-ref';\nimport { carryOverLocation } from './router/lynx-location-strategy';\n\n/**\n * Starts the background thread. The build calls it from the background\n * thread's entry, a module it generates in place of the app's `main.ts`\n * (background-entry.ts in the build plugin): Angular runs on the main thread\n * only, so the background thread loads just this runtime and the modules that\n * define a background function or a `MainThreadRef`.\n *\n * Loading the runtime installs the background half of each bridge (the imports\n * above). This installs `lynx.loadLazyBundle`, for an `import()` in a\n * background function. Importing it is also what keeps the runtime in the\n * background bundle: the package is marked `\"sideEffects\": false`, so a bare\n * `import '@blotch/angular-lynx'` would be dropped.\n */\nexport const ɵstartBackgroundThread = (): void => {\n installLazyBundleLoader();\n};\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 *\n * Angular runs on the main thread only. The background thread starts from an\n * entry the build generates instead of `main.ts` (see\n * {@link ɵstartBackgroundThread}), so it doesn't reach this function, unless a\n * module it loads also bootstraps, such as a `main.ts` that defines a\n * `backgroundFn()` itself. Then it gets no app: the returned promise never\n * settles on that thread. Booting a second copy there ran every constructor,\n * `ngOnInit` and `effect()` twice, and its views went nowhere (issue #81).\n */\nexport const bootstrapApplication = async (\n rootComponent: Type<unknown>,\n options?: ApplicationConfig,\n): Promise<ApplicationRef> => {\n if (!__MAIN_THREAD__) {\n // A pending promise rather than a rejected one: main.ts usually ends in\n // `.catch(console.error)`, which would log an error on every launch.\n // Nothing that needs an ApplicationRef can run here anyway.\n return new Promise<ApplicationRef>(() => {});\n }\n\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 // before Angular can trigger any dynamic import. Placed before the hot\n // update 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 const bootstrap = bootstrapOnMainThread(rootComponent, options);\n // A hot update that re-runs the app's entry calls this again (see\n // `ɵhmrAccept`). The plugin's main-thread hot update client waits for this\n // promise after applying an update, and reloads the page if it rejects:\n // the old app is already gone by then, so a failed re-bootstrap would\n // otherwise leave a blank screen.\n (globalThis as any).__LYNX_ANGULAR_BOOTSTRAP__ = bootstrap;\n return bootstrap;\n};\n\nconst bootstrapOnMainThread = async (\n rootComponent: Type<unknown>,\n options: ApplicationConfig | undefined,\n): Promise<ApplicationRef> => {\n // Hot update re-bootstrap: destroy the previous app so Angular's platform\n // accepts a new one. A hot update whose changes no component could take in\n // place re-runs the app's entry, which calls this again. The old app is\n // destroyed (which removes its Lynx elements) and a fresh one is created\n // from the updated modules.\n const prev = (globalThis as any).__LYNX_ANGULAR_APP_REF__ as\n | ApplicationRef\n | undefined;\n if (prev) {\n // The new app opens on the screen the old one was showing, with the same\n // Back history, instead of on the initial route.\n carryOverLocation(prev.injector);\n // ...in the page the old app rendered into (see createRootElement).\n handOverPageToNextApp();\n prev.destroy();\n (globalThis as any).__LYNX_ANGULAR_APP_REF__ = undefined;\n // The main-thread worklet registry is deliberately left alone. A hot\n // update re-runs only the changed modules and the ones that import them,\n // so a module-level `mainThreadFn()` elsewhere is never registered again,\n // and clearing the registry (as an earlier version did) broke it. The\n // re-run modules register new functions under new IDs (the IDs come from\n // a counter), and the old app's per-instance functions were released by\n // its DestroyRefs in destroy() above.\n }\n\n // Wait for Lynx's renderPage callback. After the first boot, pageReady has\n // already fired, and replays it.\n await firstValueFrom(pageReady);\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__ && !wasHydrating) {\n setTimeout(() => __FlushElementTree(), 0);\n }\n\n return appRef;\n};\n"],"mappings":"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"}