@sigx/lynx-runtime-main 0.2.7 → 0.4.1

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 +0,0 @@
1
- {"version":3,"file":"entry-main-CBM2DHsU.js","names":[],"sources":["../src/element-registry.ts","../src/upstream/observers.ts","../src/upstream/processGesture.ts","../src/worklet-events.ts","../src/event-slots.ts","../src/animated-style-mappers.ts","../src/animated-bridge-mt.ts","../src/ops-apply.ts","../src/run-on-background-mt.ts","../src/entry-main.ts"],"sourcesContent":["/**\n * Element registry — maps BG-thread ShadowElement IDs to Lynx Main Thread\n * element handles.\n */\n\n/** Map from BG-thread ShadowElement id to Lynx Main Thread element handle */\nexport const elements = new Map<number, MainThreadElement>();\n\n/**\n * PAPI unique ID of the root PageElement.\n * Passed as `parentComponentUniqueId` to element creation PAPI calls.\n * `__SetCSSId` sets `css_style_sheet_manager_` directly on each element,\n * so CSS rendering works without a ComponentElement ancestor.\n */\nexport let pageUniqueId = 1;\n\nexport function setPageUniqueId(id: number): void {\n pageUniqueId = id;\n}\n","// Copyright 2025 The Lynx Authors. All rights reserved.\n// TypeScript types added 2026 by SignalX contributors.\n//\n// Licensed under the Apache License, Version 2.0. The full license text and\n// upstream attribution are reproduced in `THIRD_PARTY_NOTICES.md` at the\n// root of this package (`@sigx/lynx-runtime-main`). The MIT LICENSE at the\n// repository root governs the rest of this repository; it does NOT apply\n// to this file.\n//\n// Vendored from `@lynx-js/react@0.120.0`'s\n// `runtime/lib/worklet-runtime/bindings/observers.js`. Source preserved\n// verbatim; only types added. We vendor this 15-LOC helper to drop the\n// `@lynx-js/react` runtime dependency from `@sigx/lynx-runtime-main`, which\n// in turn keeps `@types/react` out of the install tree of consumer apps\n// (sigx-lynx apps use sigx primitives, not ReactLynx JSX).\n\ninterface WorkletLike {\n _execId?: number;\n}\n\ninterface JsFunctionLifecycleManager {\n addRef(execId: number, worklet: WorkletLike): void;\n}\n\ninterface EventDelayImpl {\n runDelayedWorklet(worklet: WorkletLike, element: unknown): void;\n}\n\ninterface LynxWorkletImpl {\n _jsFunctionLifecycleManager?: JsFunctionLifecycleManager;\n _eventDelayImpl: EventDelayImpl;\n _hydrateCtx(worklet: WorkletLike, oldWorklet: WorkletLike): void;\n}\n\nfunction impl(): LynxWorkletImpl | undefined {\n return (globalThis as { lynxWorkletImpl?: LynxWorkletImpl }).lynxWorkletImpl;\n}\n\n/**\n * Must be called when a worklet context is updated. Mirrors the upstream\n * ReactLynx behaviour:\n * 1. Register the new worklet with the JS-side lifecycle manager (so the\n * background thread can free it).\n * 2. On first screen with a previous ctx, hydrate the new ctx from the old.\n * 3. On first screen, flush any worklets that were delayed waiting for this\n * element (legacy dynamic-component compat path).\n */\nexport function onWorkletCtxUpdate(\n worklet: WorkletLike,\n oldWorklet: WorkletLike | null | undefined,\n isFirstScreen: boolean,\n element: unknown,\n): void {\n const w = impl();\n if (worklet._execId !== undefined) {\n w?._jsFunctionLifecycleManager?.addRef(worklet._execId, worklet);\n }\n if (isFirstScreen && oldWorklet) {\n w?._hydrateCtx(worklet, oldWorklet);\n }\n if (isFirstScreen) {\n w?._eventDelayImpl.runDelayedWorklet(worklet, element);\n }\n}\n","// Copyright 2024 The Lynx Authors. All rights reserved.\n// TypeScript types added 2026 by SignalX contributors.\n//\n// Licensed under the Apache License, Version 2.0. The full license text and\n// upstream attribution are reproduced in `THIRD_PARTY_NOTICES.md` at the\n// root of this package (`@sigx/lynx-runtime-main`). The MIT LICENSE at the\n// repository root governs the rest of this repository; it does NOT apply\n// to this file.\n//\n// TS port of `@lynx-js/react@0.119.0`'s\n// `runtime/lib/gesture/processGesture.js`. Source preserved verbatim; only\n// types added. Why vendor: upstream's `gesture/processGesture.js` is the\n// canonical platform-call sequence used by `@lynx-js/react`'s snapshot\n// pipeline. Calling our hand-rolled equivalent on a real device shows the\n// gesture arena doesn't engage; vendoring eliminates any subtle divergence.\n//\n// Sigx-specific deltas:\n// - `dom` is sigx's raw `MainThreadElement`, not a SnapshotInstance member.\n// - Caller passes `isFirstScreen=false` (no SSR/hydration in sigx).\n// - `gestureOptions` always undefined.\n\nimport { onWorkletCtxUpdate } from './observers.js';\n\nconst COMPOSED = -1;\n\ninterface GestureWorklet {\n _wkltId: string;\n _execId?: number;\n _c?: Record<string, unknown>;\n _jsFn?: Record<string, unknown>;\n _workletType?: string;\n}\n\ninterface BaseGesture {\n __isSerialized: true;\n type: number;\n id: number;\n callbacks: Record<string, GestureWorklet>;\n waitFor?: BaseGesture[];\n simultaneousWith?: BaseGesture[];\n continueWith?: BaseGesture[];\n config?: Record<string, unknown>;\n}\n\ninterface ComposedGesture {\n __isSerialized: true;\n type: -1;\n gestures: AnyGesture[];\n}\n\ntype AnyGesture = BaseGesture | ComposedGesture;\n\ninterface GestureOptions {\n domSet?: boolean;\n}\n\ninterface RelationMap {\n waitFor: number[];\n simultaneous: number[];\n continueWith: number[];\n}\n\ninterface GestureConfig {\n callbacks: { name: string; callback: GestureWorklet }[];\n config?: Record<string, unknown>;\n}\n\nfunction isSerializedGesture(gesture: unknown): gesture is AnyGesture {\n return (gesture as { __isSerialized?: boolean })?.__isSerialized === true;\n}\n\nfunction getSerializedBaseGesture(\n gesture: AnyGesture | undefined,\n): BaseGesture | undefined {\n if (!gesture || !isSerializedGesture(gesture)) return undefined;\n if (gesture.type !== COMPOSED) return gesture as BaseGesture;\n return undefined;\n}\n\nfunction appendUniqueSerializedBaseGestures(\n gesture: AnyGesture | undefined,\n out: BaseGesture[],\n seenIds: Set<number>,\n): void {\n if (!gesture || !isSerializedGesture(gesture)) return;\n if (gesture.type === COMPOSED) {\n for (const sub of (gesture as ComposedGesture).gestures) {\n appendUniqueSerializedBaseGestures(sub, out, seenIds);\n }\n return;\n }\n const base = gesture as BaseGesture;\n if (seenIds.has(base.id)) return;\n seenIds.add(base.id);\n out.push(base);\n}\n\ninterface OldGestureInfo {\n uniqOldBaseGestures: BaseGesture[];\n oldBaseGesturesById: Map<number, BaseGesture>;\n}\n\nfunction appendOldGestureInfo(\n gesture: AnyGesture | undefined,\n out: BaseGesture[],\n byId: Map<number, BaseGesture>,\n): void {\n if (!gesture || !isSerializedGesture(gesture)) return;\n if (gesture.type === COMPOSED) {\n for (const sub of (gesture as ComposedGesture).gestures) {\n appendOldGestureInfo(sub, out, byId);\n }\n return;\n }\n const base = gesture as BaseGesture;\n if (!byId.has(base.id)) {\n byId.set(base.id, base);\n out.push(base);\n }\n}\n\nfunction collectOldGestureInfo(\n oldGesture: AnyGesture | undefined,\n): OldGestureInfo {\n const uniqOldBaseGestures: BaseGesture[] = [];\n const oldBaseGesturesById = new Map<number, BaseGesture>();\n appendOldGestureInfo(oldGesture, uniqOldBaseGestures, oldBaseGesturesById);\n return { uniqOldBaseGestures, oldBaseGesturesById };\n}\n\nfunction consumeOldBaseGesture(\n baseGesture: BaseGesture,\n uniqOldBaseGestures: BaseGesture[],\n oldBaseGesturesById: Map<number, BaseGesture>,\n): BaseGesture | undefined {\n const idMatched = oldBaseGesturesById.get(baseGesture.id);\n if (idMatched) {\n oldBaseGesturesById.delete(baseGesture.id);\n return idMatched;\n }\n const fallback = uniqOldBaseGestures.find((og) =>\n oldBaseGesturesById.has(og.id),\n );\n if (!fallback) return undefined;\n oldBaseGesturesById.delete(fallback.id);\n return fallback;\n}\n\nfunction removeGestureDetector(dom: MainThreadElement, id: number): void {\n if (typeof __RemoveGestureDetector === 'function') {\n __RemoveGestureDetector(dom, id);\n }\n}\n\nfunction getGestureInfo(\n gesture: BaseGesture,\n oldGesture: BaseGesture | undefined,\n isFirstScreen: boolean,\n dom: MainThreadElement,\n): { config: GestureConfig; relationMap: RelationMap } {\n const config: GestureConfig = { callbacks: [] };\n if (gesture.config) {\n config.config = gesture.config;\n }\n for (const key of Object.keys(gesture.callbacks)) {\n const callback = gesture.callbacks[key]!;\n const oldCallback = oldGesture?.callbacks[key];\n // Upstream types `Worklet._c` as `Record<string, ClosureValueType>`; ours\n // is `Record<string, unknown>` from the wire. The runtime contract is\n // identical — cast through `unknown` to satisfy the upstream signature.\n onWorkletCtxUpdate(\n callback as unknown as Parameters<typeof onWorkletCtxUpdate>[0],\n oldCallback as unknown as Parameters<typeof onWorkletCtxUpdate>[1],\n isFirstScreen,\n dom as unknown as Parameters<typeof onWorkletCtxUpdate>[3],\n );\n config.callbacks.push({ name: key, callback });\n }\n const relationMap: RelationMap = {\n waitFor: gesture.waitFor?.map((g) => g.id) ?? [],\n simultaneous: gesture.simultaneousWith?.map((g) => g.id) ?? [],\n continueWith: gesture.continueWith?.map((g) => g.id) ?? [],\n };\n return { config, relationMap };\n}\n\nexport function processGesture(\n dom: MainThreadElement,\n gesture: AnyGesture | undefined,\n oldGesture: AnyGesture | undefined,\n isFirstScreen: boolean,\n gestureOptions?: GestureOptions,\n): void {\n const domSet = gestureOptions?.domSet === true;\n const { uniqOldBaseGestures, oldBaseGesturesById } =\n collectOldGestureInfo(oldGesture);\n\n const singleBaseGesture = getSerializedBaseGesture(gesture);\n const singleOldBaseGesture = getSerializedBaseGesture(oldGesture);\n\n if (singleBaseGesture && (!oldGesture || singleOldBaseGesture)) {\n if (!domSet) {\n __SetAttribute(dom, 'has-react-gesture', true);\n __SetAttribute(dom, 'flatten', false);\n }\n if (singleOldBaseGesture) {\n removeGestureDetector(dom, singleOldBaseGesture.id);\n }\n const { config, relationMap } = getGestureInfo(\n singleBaseGesture,\n singleOldBaseGesture,\n isFirstScreen,\n dom,\n );\n __SetGestureDetector(\n dom,\n singleBaseGesture.id,\n singleBaseGesture.type,\n config,\n relationMap,\n );\n return;\n }\n\n const uniqBaseGestures: BaseGesture[] = [];\n appendUniqueSerializedBaseGestures(gesture, uniqBaseGestures, new Set());\n if (uniqBaseGestures.length === 0) {\n for (const og of oldBaseGesturesById.values()) {\n removeGestureDetector(dom, og.id);\n }\n if (!domSet) {\n __SetAttribute(dom, 'has-react-gesture', null);\n }\n return;\n }\n\n if (!domSet) {\n __SetAttribute(dom, 'has-react-gesture', true);\n __SetAttribute(dom, 'flatten', false);\n }\n\n for (const og of oldBaseGesturesById.values()) {\n removeGestureDetector(dom, og.id);\n }\n\n for (const base of uniqBaseGestures) {\n const oldBase = consumeOldBaseGesture(\n base,\n uniqOldBaseGestures,\n oldBaseGesturesById,\n );\n const { config, relationMap } = getGestureInfo(\n base,\n oldBase,\n isFirstScreen,\n dom,\n );\n __SetGestureDetector(dom, base.id, base.type, config, relationMap);\n }\n}\n","/**\n * Helpers for invoking worklets from the BG → MT bridge.\n *\n * Most of the worklet machinery (registry, ref map, event dispatch) is owned\n * by `@lynx-js/react/worklet-runtime`, which is side-effect-imported from\n * `entry-main.ts`. That runtime installs `globalThis.lynxWorkletImpl`,\n * `globalThis.registerWorkletInternal`, and `globalThis.runWorklet`. Lynx\n * native dispatches MT-routed events directly into `runWorklet`.\n *\n * What sigx-lynx still needs to provide is the `runOnMainThread` BG → MT call\n * path: BG ships `{ wkltId, args }` over `callLepusMethod('sigxRunOnMT')`, the\n * MT bridge handler in `entry-main.ts` calls `invokeWorklet()` here, and we\n * look up the function in upstream's `_workletMap`.\n */\n\ninterface WorkletImpl {\n _workletMap: Record<string, Function>;\n _refImpl?: {\n _workletRefMap: Record<number, { current: unknown; _wvid: number }>;\n };\n}\n\nexport interface WorkletPlaceholder {\n _wkltId: string;\n _c?: Record<string, unknown>;\n}\n\nfunction getWorkletImpl(): WorkletImpl | undefined {\n return (globalThis as Record<string, unknown>)['lynxWorkletImpl'] as\n | WorkletImpl\n | undefined;\n}\n\n/**\n * Invoke a worklet by id with the given args. Used by the runOnMainThread\n * bridge — event-driven worklets go through Lynx's native runWorklet path\n * and never touch this function.\n */\nexport function invokeWorklet(\n wkltId: string,\n captured: Record<string, unknown> | undefined,\n args: unknown[],\n): unknown {\n const impl = getWorkletImpl();\n if (!impl) {\n console.log('[sigx-mt] lynxWorkletImpl not initialized');\n return undefined;\n }\n const fn = impl._workletMap[wkltId];\n if (!fn) {\n console.log('[sigx-mt] worklet not registered:', wkltId);\n return undefined;\n }\n // Match upstream's calling convention: `function(arg) { let { x } = this[\"_c\"]; ... }`\n try {\n return fn.apply({ _c: captured ?? {} }, args);\n } catch (e) {\n console.log('[sigx-mt] worklet threw:', String(e));\n return undefined;\n }\n}\n\n/** Reset hook — for testing. The upstream worklet-runtime has its own state. */\nexport function resetWorkletEvents(): void {\n // No sigx-side state to clear; upstream's _workletMap survives module reset\n // (registrations re-run when the user module re-evaluates on hot reload).\n}\n","/**\n * MT-side per-slot event registration state machine.\n *\n * Lynx native's `__AddEvent(el, eventType, eventName, value)` only stores ONE\n * value per `(el, eventType, eventName)` slot — the second call wins. When\n * sigx user code declares both a `main-thread-bind*` worklet AND a regular\n * `bind*` BG handler on the same element, two ops arrive in the same patch\n * batch (SET_WORKLET_EVENT + SET_EVENT). Calling `__AddEvent` eagerly per op\n * means the second one silently overwrites the first.\n *\n * This module defers the `__AddEvent` call. Each op updates per-slot state\n * (`worklet?`, `bgSign?`) and marks the slot dirty. After the entire op\n * batch is processed (`flushDirtySlots` is called at the tail of `applyOps`),\n * we issue ONE `__AddEvent` per dirty slot using whichever shape combines\n * the present handlers — string sign, worklet ctx, or hybrid ctx.\n *\n * State persists across batches because re-renders may update only one of\n * the two handlers (the BG event-registry already deduplicates SET_EVENT\n * after the first registration, and `sentWorklets` deduplicates\n * SET_WORKLET_EVENT by `_wkltId`).\n */\n\nimport { elements } from './element-registry.js';\nimport { hybridCtx } from './hybrid-worklet.js';\nimport type { WorkletPlaceholder } from './worklet-events.js';\n\ninterface SlotState {\n worklet?: WorkletPlaceholder;\n bgSign?: string;\n /** Last value passed to __AddEvent, kept for skip-if-unchanged diffing. */\n installed?: unknown;\n}\n\n/** elementId → typeName ('bindEvent:tap' etc.) → slot state */\nconst slotStates = new Map<number, Map<string, SlotState>>();\n/** Set of `${elementId}|${typeName}` keys that need __AddEvent re-issuing. */\nconst dirtySlots = new Set<string>();\n\nfunction getOrCreateSlot(elId: number, type: string, name: string): SlotState {\n let perEl = slotStates.get(elId);\n if (!perEl) {\n perEl = new Map();\n slotStates.set(elId, perEl);\n }\n const typeName = `${type}:${name}`;\n let slot = perEl.get(typeName);\n if (!slot) {\n slot = {};\n perEl.set(typeName, slot);\n }\n return slot;\n}\n\nfunction markDirty(elId: number, type: string, name: string): void {\n dirtySlots.add(`${elId}|${type}:${name}`);\n}\n\nexport function setSlotWorklet(\n elId: number,\n type: string,\n name: string,\n ctx: WorkletPlaceholder | undefined,\n): void {\n const slot = getOrCreateSlot(elId, type, name);\n slot.worklet = ctx;\n markDirty(elId, type, name);\n}\n\nexport function setSlotBgSign(\n elId: number,\n type: string,\n name: string,\n sign: string | undefined,\n): void {\n const slot = getOrCreateSlot(elId, type, name);\n slot.bgSign = sign;\n markDirty(elId, type, name);\n}\n\n/**\n * Pick the right __AddEvent value given which handlers are present.\n * Returns `undefined` to mean \"unregister this slot\".\n */\nfunction computeAddEventValue(slot: SlotState): unknown {\n const { worklet, bgSign } = slot;\n if (!worklet && !bgSign) return undefined;\n if (worklet && !bgSign) {\n return { type: 'worklet', value: worklet };\n }\n if (!worklet && bgSign) {\n return bgSign;\n }\n return { type: 'worklet', value: hybridCtx(worklet!, bgSign!) };\n}\n\n/**\n * Commit __AddEvent for every slot that changed since the last flush.\n * Called from `applyOps` after the op loop, before `__FlushElementTree()`.\n */\nexport function flushDirtySlots(): void {\n for (const key of dirtySlots) {\n const sep = key.indexOf('|');\n const elId = Number(key.slice(0, sep));\n const typeName = key.slice(sep + 1);\n const colon = typeName.indexOf(':');\n const type = typeName.slice(0, colon);\n const name = typeName.slice(colon + 1);\n\n const el = elements.get(elId);\n if (!el) continue;\n\n const slot = slotStates.get(elId)?.get(typeName);\n if (!slot) continue;\n\n const value = computeAddEventValue(slot);\n if (sameRef(value, slot.installed)) continue;\n\n // Lynx PAPI: undefined as the 4th arg unregisters.\n __AddEvent(el, type, name, value as string | undefined);\n slot.installed = value;\n }\n dirtySlots.clear();\n}\n\nfunction sameRef(a: unknown, b: unknown): boolean {\n // Reference equality is enough for our usage:\n // - undefined === undefined\n // - bgSign string deduplicated by event-registry, so identity stable\n // - worklet ctx is a fresh object per SET_WORKLET_EVENT op (never compared\n // to itself across batches because the prev value would always differ),\n // so this is mostly a defensive no-op for the first three branches.\n return a === b;\n}\n\n/** Hot-reload / test reset hook — clears all slot state. */\nexport function resetSlotStates(): void {\n slotStates.clear();\n dirtySlots.clear();\n}\n","/**\n * MT-side mapper registry for `useAnimatedStyle`.\n *\n * Maps a `SharedValue`'s current scalar to a partial style object that the\n * binding flush passes to `setStyleProperties` on the bound element. Keyed by\n * a string name (`'translateX'`, `'scale'`, ...) so the SWC worklet transform\n * can capture the selection trivially: a string is a primitive `_c` value\n * with no special lifting required (unlike arbitrary functions, which can't\n * be captured into a worklet's closure).\n *\n * Custom mappers can be registered via `registerMapper(name, fn)` from MT\n * code (e.g. a `'main thread'`-marked module body in a user app). BG-side\n * `useAnimatedStyle` validates the name only against the type union; a\n * lookup mismatch on MT is a silent no-op at flush time.\n *\n * Param shapes are mapper-specific. The `MapperParams` type in\n * `@sigx/lynx-runtime-internal` is the single source of truth — both\n * BG-side `useAnimatedStyle` and the MT runtime import it from there.\n *\n * Range mapping: `translateX` / `translateY` / `scale` / `opacity` accept\n * either their linear `factor`/`offset` shape or a `RangeParams` shape\n * (`{ inputRange, outputRange, extrapolate? }`). The mapper picks the branch\n * by looking for `inputRange` on the params.\n */\n\nimport type {\n MapperParams,\n RangeParams,\n AnimatedStyleMapper,\n} from '@sigx/lynx-runtime-internal';\n\n// Re-export so that consumers importing from lynx-runtime-main don't have\n// to reach into lynx-runtime-internal directly.\nexport type {\n MapperParams,\n BuiltinMapperName,\n AnimatedStyleMapper,\n RangeParams,\n} from '@sigx/lynx-runtime-internal';\n\nfunction isRangeParams(p: unknown): p is RangeParams {\n return (\n typeof p === 'object' && p !== null\n && 'inputRange' in p\n && 'outputRange' in p\n );\n}\n\n/**\n * Linear interpolation across a multi-stop range. Locates the input segment\n * via simple linear scan (inputRange is small in practice — typically 2-4\n * stops) and lerps within it. Out-of-range behavior controlled by\n * `extrapolate`: `'clamp'` (default) caps at endpoint outputs; `'identity'`\n * extends linearly using the slope of the nearest segment.\n */\nfunction interpolateLinear(\n v: number,\n inputRange: number[],\n outputRange: number[],\n extrapolate: 'clamp' | 'identity' = 'clamp',\n): number {\n const n = inputRange.length;\n if (n < 2) return outputRange[0] ?? v;\n\n if (v <= inputRange[0]!) {\n if (extrapolate === 'clamp') return outputRange[0]!;\n const dx = inputRange[1]! - inputRange[0]!;\n const dy = outputRange[1]! - outputRange[0]!;\n return outputRange[0]! + (v - inputRange[0]!) * (dy / dx);\n }\n if (v >= inputRange[n - 1]!) {\n if (extrapolate === 'clamp') return outputRange[n - 1]!;\n const dx = inputRange[n - 1]! - inputRange[n - 2]!;\n const dy = outputRange[n - 1]! - outputRange[n - 2]!;\n return outputRange[n - 1]! + (v - inputRange[n - 1]!) * (dy / dx);\n }\n for (let i = 1; i < n; i++) {\n if (v <= inputRange[i]!) {\n const t = (v - inputRange[i - 1]!) / (inputRange[i]! - inputRange[i - 1]!);\n return outputRange[i - 1]! + t * (outputRange[i]! - outputRange[i - 1]!);\n }\n }\n return outputRange[n - 1]!;\n}\n\nconst mtMappers: Record<string, AnimatedStyleMapper> = {\n translateX: (v, p) => {\n if (isRangeParams(p)) {\n const out = interpolateLinear(v as number, p.inputRange, p.outputRange, p.extrapolate);\n return { transform: `translateX(${out}px)` };\n }\n const factor = (p as { factor?: number } | undefined)?.factor ?? 1;\n return { transform: `translateX(${(v as number) * factor}px)` };\n },\n translateY: (v, p) => {\n if (isRangeParams(p)) {\n const out = interpolateLinear(v as number, p.inputRange, p.outputRange, p.extrapolate);\n return { transform: `translateY(${out}px)` };\n }\n const factor = (p as { factor?: number } | undefined)?.factor ?? 1;\n return { transform: `translateY(${(v as number) * factor}px)` };\n },\n translate: (v, p) => {\n const params = (p as MapperParams['translate'] | undefined) ?? {};\n const fx = params.factorX ?? 1;\n const fy = params.factorY ?? 1;\n const xy = v as { x: number; y: number };\n return { transform: `translate(${xy.x * fx}px, ${xy.y * fy}px)` };\n },\n scale: (v, p) => {\n if (isRangeParams(p)) {\n const out = interpolateLinear(v as number, p.inputRange, p.outputRange, p.extrapolate);\n return { transform: `scale(${out})` };\n }\n const offset = (p as { offset?: number } | undefined)?.offset ?? 0;\n return { transform: `scale(${(v as number) + offset})` };\n },\n opacity: (v, p) => {\n if (isRangeParams(p)) {\n const raw = interpolateLinear(v as number, p.inputRange, p.outputRange, p.extrapolate);\n const out = Math.max(0, Math.min(1, raw));\n return { opacity: String(out) };\n }\n const params = (p as { factor?: number; offset?: number } | undefined) ?? {};\n const factor = params.factor ?? 1;\n const offset = params.offset ?? 0;\n const out = Math.max(0, Math.min(1, (v as number) * factor + offset));\n return { opacity: String(out) };\n },\n rotate: (v) => ({ transform: `rotate(${v as number}deg)` }),\n paddingTop: (v, p) => ({ paddingTop: `${linearOrRange(v, p)}px` }),\n paddingRight: (v, p) => ({ paddingRight: `${linearOrRange(v, p)}px` }),\n paddingBottom: (v, p) => ({ paddingBottom: `${linearOrRange(v, p)}px` }),\n paddingLeft: (v, p) => ({ paddingLeft: `${linearOrRange(v, p)}px` }),\n marginTop: (v, p) => ({ marginTop: `${linearOrRange(v, p)}px` }),\n marginRight: (v, p) => ({ marginRight: `${linearOrRange(v, p)}px` }),\n marginBottom: (v, p) => ({ marginBottom: `${linearOrRange(v, p)}px` }),\n marginLeft: (v, p) => ({ marginLeft: `${linearOrRange(v, p)}px` }),\n};\n\nfunction linearOrRange(v: unknown, p: unknown): number {\n if (isRangeParams(p)) {\n return interpolateLinear(v as number, p.inputRange, p.outputRange, p.extrapolate);\n }\n const factor = (p as { factor?: number } | undefined)?.factor ?? 1;\n return (v as number) * factor;\n}\n\n/**\n * Look up a registered mapper by name. Returns `undefined` if the name\n * isn't registered — the binding flush treats that as a no-op.\n */\nexport function lookupMapper(name: string): AnimatedStyleMapper | undefined {\n return mtMappers[name];\n}\n\n/**\n * Register a custom MT-side mapper. Idempotent on (name, fn) — last\n * registration wins for the same name. Intended for `'main thread'`-marked\n * user modules that ship project-specific styling math.\n */\nexport function registerMapper(name: string, mapper: AnimatedStyleMapper): void {\n mtMappers[name] = mapper;\n}\n\n/**\n * Reset hook — drops every custom mapper, reseats the built-ins. Used by\n * the MT-side resetMainThreadState path (HMR / tests).\n */\nconst BUILTIN_NAMES = new Set([\n 'translateX', 'translateY', 'translate', 'scale', 'opacity', 'rotate',\n 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',\n 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',\n]);\n\nexport function resetMappers(): void {\n for (const k in mtMappers) {\n if (!BUILTIN_NAMES.has(k)) {\n delete mtMappers[k];\n }\n }\n}\n","/**\n * MT-side SharedValue bridge — publishes MT-thread mutations to BG.\n *\n * Diffs every registered SharedValue against its last-published snapshot\n * and dispatches one batched `Lynx.Sigx.AvPublish` event per flush boundary\n * with the changed `[wvid, value]` tuples. The BG side ingests these via\n * `@sigx/lynx-runtime/src/animated-bridge.ts` and writes them into the\n * mirror signal so any sigx `effect` reading `sv.value` re-runs.\n *\n * Bridge state (`bridgedAvWvids` / `bridgedAvLastValues`) lives in\n * `ops-apply.ts` because the BG→MT op handlers mutate it; this module\n * imports the references and reads them on every flush.\n *\n * Two flush hook points:\n * 1. `ops-apply.ts` calls `flushAvBridgePublishes()` at its tail (covers\n * every BG-driven ops batch).\n * 2. `installAvBridgeFlushHook()` wraps `globalThis.__FlushElementTree`\n * so spontaneous MT writes (e.g. a touchmove worklet that eventually\n * calls `setStyleProperties`) also trigger a publish on the same\n * tick the native tree flushes. Called once from `entry-main.ts`\n * after PAPI globals are present.\n *\n * Coalescing: `===` per-wvid diff. Identical writes are filtered. N writes\n * within one flush window collapse to one BG event with N entries.\n */\n\nimport { bridgedAvWvids, bridgedAvLastValues } from './ops-apply.js';\nimport { lookupMapper } from './animated-style-mappers.js';\n\nconst AV_PUBLISH = 'Lynx.Sigx.AvPublish';\n\ninterface AvRef {\n current: { value?: unknown };\n _wvid: number;\n}\n\ninterface WorkletImpl {\n _refImpl?: {\n _workletRefMap: Record<number, AvRef>;\n };\n}\n\ninterface JSContextLike {\n dispatchEvent?: (e: { type: string; data: string }) => void;\n}\n\ninterface LynxLike {\n getJSContext?: () => JSContextLike;\n}\n\n/**\n * Diff registered AVs against their last-published snapshots; dispatch one\n * batched `Lynx.Sigx.AvPublish` event with all changed tuples. No-op when\n * the bridge set is empty or when nothing has changed since the last call.\n */\nexport function flushAvBridgePublishes(): void {\n if (bridgedAvWvids.size === 0) return;\n\n const impl = (globalThis as { lynxWorkletImpl?: WorkletImpl }).lynxWorkletImpl;\n const refMap = impl?._refImpl?._workletRefMap;\n if (!refMap) return;\n\n let updates: Array<[number, unknown]> | undefined;\n for (const wvid of bridgedAvWvids) {\n const ref = refMap[wvid];\n if (!ref) continue;\n const v = ref.current?.value;\n if (v !== bridgedAvLastValues.get(wvid)) {\n (updates ??= []).push([wvid, v]);\n bridgedAvLastValues.set(wvid, v);\n }\n }\n\n if (!updates) return;\n\n const lynxObj = (globalThis as { lynx?: LynxLike }).lynx;\n const ctx = lynxObj?.getJSContext?.();\n if (!ctx?.dispatchEvent) return;\n\n let data: string;\n try {\n data = JSON.stringify(updates);\n } catch (e) {\n console.log('[sigx-mt] av-bridge: JSON.stringify failed:', String(e));\n return;\n }\n\n ctx.dispatchEvent({ type: AV_PUBLISH, data });\n}\n\n// ---------------------------------------------------------------------------\n// useAnimatedStyle bindings\n//\n// Each registered binding maps a SharedValue -> a partial style object\n// applied to a bound element on every flush where the SharedValue's value\n// changed. The MT side never sees the user's mapper code directly — the BG\n// ops carry only the mapper's *name*, which the MT runtime resolves via\n// lookupMapper().\n// ---------------------------------------------------------------------------\n\ninterface AnimatedStyleBinding {\n elementWvid: number;\n avWvid: number;\n mapperName: string;\n params: unknown;\n lastValue: unknown;\n}\n\nconst animatedStyleBindings = new Map<number, AnimatedStyleBinding>();\n\n/**\n * Register a binding (called from the OP.REGISTER_AV_STYLE_BINDING op\n * handler in `ops-apply.ts`). Initializes `lastValue` to a sentinel so the\n * first flush always applies the mapper, even when the AV is at its initial.\n */\nexport function registerAnimatedStyleBinding(\n bindingId: number,\n elementWvid: number,\n avWvid: number,\n mapperName: string,\n params: unknown,\n): void {\n // Sentinel — guaranteed not to equal any user value, so the first flush\n // applies the mapper regardless of whether the AV ever gets written.\n const sentinel = {} as unknown;\n animatedStyleBindings.set(bindingId, {\n elementWvid,\n avWvid,\n mapperName,\n params,\n lastValue: sentinel,\n });\n}\n\nexport function unregisterAnimatedStyleBinding(bindingId: number): void {\n animatedStyleBindings.delete(bindingId);\n}\n\nexport function resetAnimatedStyleBindings(): void {\n animatedStyleBindings.clear();\n}\n\nexport function animatedStyleBindingCount(): number {\n return animatedStyleBindings.size;\n}\n\ninterface ElementWithStyleApply {\n setStyleProperties?: (styles: Record<string, string | number>) => void;\n}\n\n/**\n * For each element with at least one *dirty* binding (AV value changed since\n * the last apply), re-run **all** of that element's bindings, merge their\n * mapper outputs, and apply the result with a single `setStyleProperties`\n * call. Called from the wrapped `__FlushElementTree` *before* the native\n * tree flush.\n *\n * Why \"all bindings on a dirty element\" rather than \"only changed bindings\":\n * - Multiple bindings on the same element can write the same style key\n * (e.g. `translateX` + `translateY` both produce `transform`). If we\n * applied only the changed ones, the unchanged-binding's contribution\n * would be lost and the element would visibly snap. By re-running every\n * binding on the dirty element and merging, all contributions land in\n * the same `setStyleProperties` call.\n *\n * Merge semantics:\n * - `transform` values from multiple bindings *concatenate* in registration\n * order (e.g. `translateX(50px)` + `translateY(20px)` ->\n * `translateX(50px) translateY(20px)`).\n * - All other keys merge by last-write-wins; a binding registered later on\n * the same element overwrites an earlier binding's same-key output.\n *\n * Skip cases (silent, by design):\n * - AV ref missing in `_workletRefMap` (race with unregister).\n * - Element ref's `current` is null (component not yet mounted, or\n * unmounted before the binding's UNREGISTER op landed).\n * - Mapper name not registered (typo or missing custom registration).\n */\nexport function flushAnimatedStyleBindings(): void {\n if (animatedStyleBindings.size === 0) return;\n\n const impl = (globalThis as { lynxWorkletImpl?: WorkletImpl }).lynxWorkletImpl;\n const refMap = impl?._refImpl?._workletRefMap;\n if (!refMap) return;\n\n // Phase 1 — find which elements have at least one dirty binding. Update\n // each binding's lastValue so the next flush only re-applies on further\n // change. Skip bindings whose AV ref is missing.\n let dirtyElements: Set<number> | undefined;\n for (const binding of animatedStyleBindings.values()) {\n const avRef = refMap[binding.avWvid];\n if (!avRef) continue;\n const v = avRef.current?.value;\n if (v === binding.lastValue) continue;\n binding.lastValue = v;\n (dirtyElements ??= new Set()).add(binding.elementWvid);\n }\n if (!dirtyElements) return;\n\n // Phase 2 — for each dirty element, run *all* its bindings and merge the\n // outputs into one style object. Iteration order over the Map is insertion\n // order, which equals registration order — so transform concatenations\n // come out in the order the user registered them.\n const merged = new Map<number, Record<string, string | number>>();\n for (const binding of animatedStyleBindings.values()) {\n if (!dirtyElements.has(binding.elementWvid)) continue;\n\n const avRef = refMap[binding.avWvid];\n if (!avRef) continue;\n const v = avRef.current?.value;\n\n const mapper = lookupMapper(binding.mapperName);\n if (!mapper) continue;\n\n let out: Record<string, string | number>;\n try {\n out = mapper(v, binding.params);\n } catch (e) {\n console.log('[sigx-mt] av-style mapper threw:', binding.mapperName, String(e));\n continue;\n }\n\n let acc = merged.get(binding.elementWvid);\n if (!acc) {\n acc = {};\n merged.set(binding.elementWvid, acc);\n }\n for (const k in out) {\n if (k === 'transform' && typeof acc.transform === 'string') {\n acc.transform = `${acc.transform} ${String(out.transform)}`;\n } else {\n acc[k] = out[k]!;\n }\n }\n }\n\n // Phase 3 — one setStyleProperties per dirty element.\n for (const [elementWvid, styleObj] of merged) {\n const elRef = refMap[elementWvid];\n const el = elRef?.current as unknown as ElementWithStyleApply | null | undefined;\n if (!el?.setStyleProperties) continue;\n try {\n el.setStyleProperties(styleObj);\n } catch (e) {\n console.log('[sigx-mt] av-style setStyleProperties threw:', String(e));\n }\n }\n}\n\nconst INSTALLED = Symbol.for('sigx.avBridgeFlushHookInstalled');\n\n/**\n * Wrap `globalThis.__FlushElementTree` once so every flush also runs the AV\n * bridge publish step. Idempotent — safe to call across hot reloads. Test\n * setups that `vi.stubGlobal('__FlushElementTree', ...)` AFTER this hook\n * installs will replace our wrapper, which is the correct behavior for\n * unit tests that drive `flushAvBridgePublishes` directly.\n */\nexport function installAvBridgeFlushHook(): void {\n const g = globalThis as Record<string | symbol, unknown>;\n if (g[INSTALLED]) return;\n const original = g['__FlushElementTree'];\n if (typeof original !== 'function') return;\n g[INSTALLED] = true;\n g['__FlushElementTree'] = function wrappedFlushElementTree(\n this: unknown,\n ...args: unknown[]\n ): unknown {\n try {\n flushAvBridgePublishes();\n } catch (e) {\n console.log('[sigx-mt] av-bridge flush threw:', String(e));\n }\n try {\n flushAnimatedStyleBindings();\n } catch (e) {\n console.log('[sigx-mt] av-style bindings flush threw:', String(e));\n }\n return (original as (...a: unknown[]) => unknown).apply(this, args);\n };\n}\n","/**\n * Main Thread ops executor.\n *\n * Receives the flat-array ops buffer sent by the Background Thread via\n * callLepusMethod('sigxPatchUpdate', { data: JSON.stringify(ops) }) and applies\n * each operation using Lynx PAPI.\n */\n\nimport { OP } from '@sigx/lynx-runtime-internal';\n\nimport { processGesture } from './upstream/processGesture.js';\nimport {\n elements,\n pageUniqueId,\n setPageUniqueId,\n} from './element-registry.js';\nimport { resetWorkletEvents, type WorkletPlaceholder } from './worklet-events.js';\nimport {\n setSlotBgSign,\n setSlotWorklet,\n flushDirtySlots,\n resetSlotStates,\n} from './event-slots.js';\nimport {\n flushAvBridgePublishes,\n flushAnimatedStyleBindings,\n registerAnimatedStyleBinding,\n unregisterAnimatedStyleBinding,\n resetAnimatedStyleBindings,\n} from './animated-bridge-mt.js';\n\n/**\n * Placeholder element inserted by renderPage() to give the host a non-empty\n * tree immediately, suppressing the \"loadCard failed USER_RUNTIME_ERROR\"\n * timeout. Removed on the first applyOps() call.\n */\nlet placeholderParent: MainThreadElement | null = null;\nlet placeholderEl: MainThreadElement | null = null;\n\n/**\n * SharedValue bridge state — registered wvids and last-published snapshots.\n * The op handlers (`OP.REGISTER_AV_BRIDGE` / `OP.UNREGISTER_AV_BRIDGE` below)\n * mutate these collections; `animated-bridge-mt.ts:flushAvBridgePublishes`\n * reads them on every flush boundary to compute the diff to publish to BG.\n */\nexport const bridgedAvWvids = new Set<number>();\nexport const bridgedAvLastValues = new Map<number, unknown>();\n\n/**\n * Gesture-detector tracking — per-element wvid → set of attached gesture ids.\n * Used to drive the `has-react-gesture` setup attribute lifecycle: set on the\n * first SET_GESTURE_DETECTOR for an element, cleared when the last gesture is\n * removed via REMOVE_GESTURE_DETECTOR.\n */\nconst gesturesByElementWvid = new Map<number, Set<number>>();\n\n/**\n * Last-set BaseGesture tree per element wvid. Vendored upstream\n * `processGesture` takes an `oldGesture` arg to diff against — pass the prior\n * tree so callback updates wire correctly through `onWorkletCtxUpdate`.\n */\nconst lastTreeByElementWvid = new Map<number, unknown>();\n\n/**\n * elementWvid → elementId mapping populated by SET_MT_REF when a\n * `main-thread:ref` binds to an element. Gesture ops carry the elRef's wvid\n * (set at BG-side useGestureDetector time, before the renderer assigns an\n * element id), so resolution is wvid → elementId → raw MainThreadElement.\n *\n * We deliberately do NOT use `lynxWorkletImpl._refImpl._workletRefMap[wvid].current`:\n * that map stores the upstream-wrapped `Element` class (with `setStyleProperties`\n * etc.) which is what worklets need, but the platform's `__SetAttribute` /\n * `__SetGestureDetector` PAPI expect the raw RefCounted element handle.\n * Passing the wrapper trips the `FiberSetAttribute param 0 should be RefCounted`\n * native error.\n */\nconst elementIdByWvid = new Map<number, number>();\n\nfunction resolveElementByWvid(wvid: number): MainThreadElement | undefined {\n const elementId = elementIdByWvid.get(wvid);\n if (elementId === undefined) return undefined;\n return elements.get(elementId);\n}\n\nexport function setPlaceholder(parent: MainThreadElement, el: MainThreadElement): void {\n placeholderParent = parent;\n placeholderEl = el;\n}\n\nfunction removePlaceholderOnce(): void {\n if (placeholderEl != null && placeholderParent != null) {\n __RemoveElement(placeholderParent, placeholderEl);\n placeholderParent = null;\n placeholderEl = null;\n }\n}\n\n/**\n * Use typed PAPI creators for known element types.\n * Native Lynx may set up type-specific internals (e.g. overflow clipping\n * for View, hardware-accelerated decoding for Image) via the typed functions\n * that the generic __CreateElement does not.\n */\nfunction createTypedElement(\n type: string,\n parentComponentUniqueId: number,\n): MainThreadElement {\n switch (type) {\n case 'view':\n return __CreateView(parentComponentUniqueId);\n case 'text':\n return __CreateText(parentComponentUniqueId);\n case 'image':\n return __CreateImage(parentComponentUniqueId);\n case 'scroll-view':\n return __CreateScrollView(parentComponentUniqueId);\n case 'page':\n // The page root is special — it's created once by __CreatePage() in\n // renderPage() and aliased to ShadowElement id=1 in BG. Lynx hosts\n // (e.g. Lynx Go) have no behavior class for a second `page` element\n // and will throw \"No BehaviorController defined for class page\".\n // If user code wraps content in <page>...</page>, treat it as a\n // transparent <view> on the Main Thread so the tree stays valid.\n return __CreateView(parentComponentUniqueId);\n default:\n return __CreateElement(type, parentComponentUniqueId);\n }\n}\n\nexport function applyOps(ops: unknown[]): void {\n const len = ops.length;\n if (len === 0) return;\n\n // On the first real ops batch, remove the placeholder element that\n // renderPage() inserted to suppress the host's USER_RUNTIME_ERROR timeout.\n removePlaceholderOnce();\n\n // Detect duplicate batch from double BG bundle evaluation.\n // Each __init_card_bundle__ invocation gets a fresh webpack module cache, so\n // ShadowElement.nextId resets to 2, producing the same element IDs.\n // If the first CREATE op targets an ID that already exists in our elements Map,\n // this is a duplicate batch — skip it entirely.\n if (len >= 3 && ops[0] === OP.CREATE) {\n const firstId = ops[1] as number;\n if (elements.has(firstId)) {\n return;\n }\n }\n\n let i = 0;\n\n while (i < len) {\n const code = ops[i++] as number;\n\n switch (code) {\n case OP.CREATE: {\n const id = ops[i++] as number;\n const type = ops[i++] as string;\n let el: MainThreadElement;\n if (type === '__comment') {\n el = __CreateRawText('');\n } else {\n el = createTypedElement(type, pageUniqueId);\n __SetCSSId([el], 0);\n }\n elements.set(id, el);\n if (type !== '__comment') {\n __SetAttribute(el, `sigx-ref-${id}`, 1);\n }\n break;\n }\n\n case OP.CREATE_TEXT: {\n const id = ops[i++] as number;\n const el = __CreateText(pageUniqueId);\n __SetCSSId([el], 0);\n elements.set(id, el);\n __SetAttribute(el, `sigx-ref-${id}`, 1);\n break;\n }\n\n case OP.INSERT: {\n const parentId = ops[i++] as number;\n const childId = ops[i++] as number;\n const anchorId = ops[i++] as number;\n const parent = elements.get(parentId);\n const child = elements.get(childId);\n if (parent && child) {\n if (anchorId === -1) {\n __AppendElement(parent, child);\n } else {\n const anchor = elements.get(anchorId);\n if (anchor) __InsertElementBefore(parent, child, anchor);\n }\n }\n break;\n }\n\n case OP.REMOVE: {\n const _parentId = ops[i++] as number;\n const childId = ops[i++] as number;\n const parent = elements.get(_parentId);\n const child = elements.get(childId);\n if (parent && child) {\n __RemoveElement(parent, child);\n }\n break;\n }\n\n case OP.SET_PROP: {\n const id = ops[i++] as number;\n const key = ops[i++] as string;\n const value = ops[i++];\n const el = elements.get(id);\n if (el) __SetAttribute(el, key, value);\n break;\n }\n\n case OP.SET_TEXT: {\n const id = ops[i++] as number;\n const text = ops[i++] as string;\n const el = elements.get(id);\n if (el) __SetAttribute(el, 'text', text);\n break;\n }\n\n case OP.SET_EVENT: {\n const id = ops[i++] as number;\n const eventType = ops[i++] as string;\n const eventName = ops[i++] as string;\n const sign = ops[i++] as string;\n // Defer __AddEvent to flushDirtySlots (end of batch). When a worklet\n // is also registered for the same slot, the slot machine combines\n // them into a single hybrid registration.\n setSlotBgSign(id, eventType, eventName, sign);\n break;\n }\n\n case OP.REMOVE_EVENT: {\n const id = ops[i++] as number;\n const eventType = ops[i++] as string;\n const eventName = ops[i++] as string;\n // Clear the BG side of this slot. The MT worklet (if any) survives.\n // No worklet-removal op exists yet (see plan Open items).\n setSlotBgSign(id, eventType, eventName, undefined);\n break;\n }\n\n case OP.SET_STYLE: {\n const id = ops[i++] as number;\n const value = ops[i++] as string | object;\n const el = elements.get(id);\n if (el) __SetInlineStyles(el, value);\n break;\n }\n\n case OP.SET_CLASS: {\n const id = ops[i++] as number;\n const cls = ops[i++] as string;\n const el = elements.get(id);\n if (el) __SetClasses(el, cls);\n break;\n }\n\n case OP.SET_ID: {\n const id = ops[i++] as number;\n const idStr = ops[i++] as string | null | undefined;\n const el = elements.get(id);\n if (el) __SetID(el, idStr ?? undefined);\n break;\n }\n\n case OP.SET_WORKLET_EVENT: {\n const id = ops[i++] as number;\n const eventType = ops[i++] as string;\n const eventName = ops[i++] as string;\n const ctx = ops[i++] as WorkletPlaceholder;\n if (ctx && ctx._wkltId) {\n (ctx as unknown as Record<string, unknown>)['_workletType'] = 'main-thread';\n // Defer __AddEvent — flushDirtySlots will pick the right shape:\n // worklet-only ({type:'worklet', value: ctx}) when no BG handler\n // shares this slot, or hybrid ctx when one does.\n setSlotWorklet(id, eventType, eventName, ctx);\n }\n break;\n }\n\n case OP.SET_MT_REF: {\n const id = ops[i++] as number;\n const wvid = ops[i++] as number;\n const el = elements.get(id);\n if (el) {\n // Delegate to upstream's worklet-runtime. updateWorkletRef wraps the\n // element in its own Element class and stores it under _wvid.\n const impl = (globalThis as Record<string, unknown>)['lynxWorkletImpl'] as\n { _refImpl: { _workletRefMap: Record<number, { current: unknown; _wvid: number }>; updateWorkletRef: (refImpl: unknown, el: unknown) => void } } | undefined;\n if (impl?._refImpl) {\n const refMap = impl._refImpl._workletRefMap;\n if (!(wvid in refMap)) {\n refMap[wvid] = { current: null, _wvid: wvid };\n }\n impl._refImpl.updateWorkletRef({ _wvid: wvid }, el);\n }\n // Record wvid → raw elementId so SET_GESTURE_DETECTOR can resolve\n // the unwrapped MainThreadElement for `__SetAttribute` /\n // `__SetGestureDetector` (which require RefCounted handles, not\n // upstream's Element wrapper).\n elementIdByWvid.set(wvid, id);\n }\n break;\n }\n\n case OP.INIT_MT_REF: {\n const wvid = ops[i++] as number;\n const initValue = ops[i++];\n const impl = (globalThis as Record<string, unknown>)['lynxWorkletImpl'] as\n { _refImpl: { _workletRefMap: Record<number, { current: unknown; _wvid: number }> } } | undefined;\n if (impl?._refImpl) {\n const refMap = impl._refImpl._workletRefMap;\n if (!(wvid in refMap)) {\n refMap[wvid] = { current: initValue, _wvid: wvid };\n }\n }\n break;\n }\n\n case OP.RELEASE_MT_REF: {\n // Owning component unmounted on BG; drop the MT-side holder so the\n // worklet ref map doesn't grow unbounded across navigation. Mirrors\n // upstream's WorkletEvents.releaseWorkletRef path (we don't dispatch\n // upstream's event because we manage the map ourselves via ops).\n const wvid = ops[i++] as number;\n const impl = (globalThis as Record<string, unknown>)['lynxWorkletImpl'] as\n { _refImpl: { _workletRefMap: Record<number, unknown> } } | undefined;\n if (impl?._refImpl) {\n delete impl._refImpl._workletRefMap[wvid];\n }\n elementIdByWvid.delete(wvid);\n break;\n }\n\n case OP.REGISTER_AV_BRIDGE: {\n const wvid = ops[i++] as number;\n const initValue = ops[i++];\n bridgedAvWvids.add(wvid);\n bridgedAvLastValues.set(wvid, initValue);\n break;\n }\n\n case OP.UNREGISTER_AV_BRIDGE: {\n const wvid = ops[i++] as number;\n bridgedAvWvids.delete(wvid);\n bridgedAvLastValues.delete(wvid);\n break;\n }\n\n case OP.REGISTER_AV_STYLE_BINDING: {\n const bindingId = ops[i++] as number;\n const elementWvid = ops[i++] as number;\n const avWvid = ops[i++] as number;\n const mapperName = ops[i++] as string;\n const params = ops[i++];\n registerAnimatedStyleBinding(bindingId, elementWvid, avWvid, mapperName, params);\n break;\n }\n\n case OP.UNREGISTER_AV_STYLE_BINDING: {\n const bindingId = ops[i++] as number;\n unregisterAnimatedStyleBinding(bindingId);\n break;\n }\n\n case OP.SET_GESTURE_DETECTOR: {\n // Wire format: [op, wvid, gestureId, type, config, relationMap].\n // We reconstruct upstream's BaseGesture shape and delegate to vendored\n // `processGesture` so the platform-call sequence is byte-for-byte\n // identical to `@lynx-js/react`'s snapshot pipeline. Per-base wire\n // means we register one base per op; processGesture handles the\n // single-base fast path. Composed gestures arrive as multiple ops,\n // each carrying its relationMap.\n const elementWvid = ops[i++] as number;\n const gestureId = ops[i++] as number;\n const type = ops[i++] as number;\n const config = ops[i++] as {\n callbacks: { name: string; callback: Record<string, unknown> }[];\n config?: Record<string, unknown>;\n };\n const relationMap = ops[i++] as {\n waitFor: number[];\n simultaneous: number[];\n continueWith: number[];\n };\n const el = resolveElementByWvid(elementWvid);\n if (!el) break;\n\n // Reconstruct callbacks Record from the wire's array shape.\n const callbacksRecord: Record<string, Record<string, unknown>> = {};\n for (const cb of config.callbacks) {\n callbacksRecord[cb.name] = cb.callback;\n }\n\n // Build a fake BaseGesture: relation arrays are id-stubs `[{id}]`\n // because vendored `getGestureInfo` reads `.id` off each entry to\n // produce the relationMap. The platform never sees these objects.\n const stub = (ids: number[]) => ids.map((id) => ({ id }));\n const fakeBaseGesture = {\n __isSerialized: true as const,\n type,\n id: gestureId,\n callbacks: callbacksRecord,\n waitFor: stub(relationMap.waitFor),\n simultaneousWith: stub(relationMap.simultaneous),\n continueWith: stub(relationMap.continueWith),\n ...(config.config ? { config: config.config } : {}),\n };\n\n // Phase 2.12.1 bug fix: pass `undefined` as oldGesture, NOT the last\n // tree we saw on this element.\n //\n // Our wire format is one SET_GESTURE_DETECTOR op per BaseGesture.\n // When `<Pressable>` registers `Simultaneous(Tap, LongPress)`, two\n // ops arrive in sequence on the same element. If we pass the previous\n // tree to `processGesture`, its diff path treats the second op as\n // \"Tap → LongPress\" and emits a `__RemoveGestureDetector` for Tap\n // before installing LongPress. Result: only the last gesture stays\n // registered; all earlier gestures are silently uninstalled.\n //\n // The right model for our wire is additive: each op installs ONE\n // gesture without disturbing siblings. Removal is explicit via the\n // REMOVE_GESTURE_DETECTOR op (emitted from `useGestureDetector`'s\n // unmount cleanup), which calls `__RemoveGestureDetector` directly.\n // Note: this means we don't get diff-based callback updates if the\n // BG side re-emits a gesture with the same id — but our wire never\n // does that today; on prop changes BG emits REMOVE then SET.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n processGesture(el, fakeBaseGesture as any, undefined, false);\n lastTreeByElementWvid.set(elementWvid, fakeBaseGesture);\n\n // Track for REMOVE op cleanup and to drive `has-react-gesture` toggle\n // when the last gesture goes (vendored function clears it on remove).\n let attached = gesturesByElementWvid.get(elementWvid);\n if (!attached) {\n attached = new Set();\n gesturesByElementWvid.set(elementWvid, attached);\n }\n attached.add(gestureId);\n break;\n }\n\n case OP.REMOVE_GESTURE_DETECTOR: {\n const elementWvid = ops[i++] as number;\n const gestureId = ops[i++] as number;\n const el = resolveElementByWvid(elementWvid);\n if (el && typeof __RemoveGestureDetector === 'function') {\n __RemoveGestureDetector(el, gestureId);\n const attached = gesturesByElementWvid.get(elementWvid);\n if (attached) {\n attached.delete(gestureId);\n if (attached.size === 0) {\n gesturesByElementWvid.delete(elementWvid);\n lastTreeByElementWvid.delete(elementWvid);\n __SetAttribute(el, 'has-react-gesture', null);\n }\n }\n }\n break;\n }\n\n default:\n // Unknown op – skip (future-compat)\n break;\n }\n }\n\n // Commit deferred __AddEvent registrations now that the entire batch is\n // processed — this is what lets worklet + BG handler on the same slot\n // coexist via the hybrid worklet ctx, without one overwriting the other.\n flushDirtySlots();\n\n // Diff registered SharedValues against their last-published snapshots\n // and dispatch a batched Lynx.Sigx.AvPublish event with anything that\n // changed during this op batch. See animated-bridge-mt.ts for details.\n flushAvBridgePublishes();\n\n // Apply any useAnimatedStyle bindings whose source SharedValue changed\n // during this batch. Runs after flushAvBridgePublishes so the BG mirror\n // stays consistent with the styles we're about to commit.\n flushAnimatedStyleBindings();\n\n // Flush all pending PAPI changes to the native layer in one shot.\n __FlushElementTree();\n}\n\n/** Reset module state — for testing and hot reload. */\nexport function resetMainThreadState(): void {\n elements.clear();\n setPageUniqueId(1);\n placeholderParent = null;\n placeholderEl = null;\n // Also defined in this module's imports — reset worklet state\n resetWorkletEvents();\n resetSlotStates();\n bridgedAvWvids.clear();\n bridgedAvLastValues.clear();\n gesturesByElementWvid.clear();\n lastTreeByElementWvid.clear();\n elementIdByWvid.clear();\n resetAnimatedStyleBindings();\n // Clear upstream's worklet ref map too on hard reset (HMR / test).\n const impl = (globalThis as Record<string, unknown>)['lynxWorkletImpl'] as\n { _refImpl: { _workletRefMap: Record<number, unknown> } } | undefined;\n if (impl?._refImpl) impl._refImpl._workletRefMap = {};\n}\n","/**\n * MT-side runOnBackground — dispatches function calls from the Main Thread\n * to the Background Thread via 'Lynx.Sigx.RunOnBackground' events.\n *\n * Called inside extracted worklet bodies on the Main Thread. The SWC LEPUS\n * pass leaves bare `runOnBackground(_jsFnK)` references in the registered\n * worklet body; we install this implementation as `globalThis.runOnBackground`\n * from `entry-main.ts` so the bare identifier resolves at runtime.\n *\n * Mirrors @lynx-js/react/runtime/lib/worklet/call/runOnMainThread (the dual\n * direction) and vue-lynx's run-on-background-mt.ts. Sigx-namespaced event\n * types so we don't conflict with upstream's own bridge if it ships in the\n * same lynx process.\n */\n\nconst RUN_ON_BACKGROUND = 'Lynx.Sigx.RunOnBackground';\nconst FUNCTION_CALL_RET = 'Lynx.Sigx.FunctionCallRet';\n\n// ---------------------------------------------------------------------------\n// JsFnHandle shape — matches BG-side @sigx/lynx-runtime/run-on-background.ts\n// ---------------------------------------------------------------------------\n\ninterface JsFnHandle {\n _jsFnId?: number;\n _execId?: number;\n _isFirstScreen?: boolean;\n _error?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Return-value resolver — correlates resolveId → Promise resolve callback\n// ---------------------------------------------------------------------------\n\nlet resolveMap: Map<number, (v: unknown) => void> | undefined;\nlet nextResolveId = 1;\n\ninterface JSContextLike {\n addEventListener?: (type: string, listener: (e: { data?: unknown }) => void) => void;\n dispatchEvent?: (e: { type: string; data: string }) => void;\n}\ninterface LynxLike {\n getJSContext?: () => JSContextLike;\n}\n\nfunction getJSContext(): JSContextLike | undefined {\n // On MT, `lynx` is a globalThis property (no closure injection like BG).\n const lynxObj = (globalThis as { lynx?: LynxLike }).lynx;\n return lynxObj?.getJSContext?.();\n}\n\nfunction initReturnListener(): void {\n resolveMap = new Map();\n getJSContext()?.addEventListener?.(FUNCTION_CALL_RET, (event) => {\n let payload: { resolveId: number; returnValue: unknown };\n try {\n payload = JSON.parse(event.data as string);\n } catch {\n return;\n }\n const resolve = resolveMap?.get(payload.resolveId);\n if (resolve) {\n resolveMap!.delete(payload.resolveId);\n resolve(payload.returnValue);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// dispatch — ship the call across to BG\n// ---------------------------------------------------------------------------\n\nfunction dispatch(fnId: number, params: unknown[], execId: number, resolveId: number): void {\n getJSContext()?.dispatchEvent?.({\n type: RUN_ON_BACKGROUND,\n data: JSON.stringify({\n obj: { _jsFnId: fnId, _execId: execId },\n params,\n resolveId,\n }),\n });\n}\n\n// ---------------------------------------------------------------------------\n// First-screen delay hook — lynxWorkletImpl provides this when the MT runtime\n// hasn't finished bootstrapping yet (worklet was loaded directly into the\n// LEPUS template, no _execId stamped). Delegate to upstream's implementation\n// when available; otherwise, the call is a no-op.\n// ---------------------------------------------------------------------------\n\ninterface LynxWorkletImpl {\n _runOnBackgroundDelayImpl?: {\n delayRunOnBackground(\n handle: JsFnHandle,\n cb: (fnId: number, execId: number) => void,\n ): void;\n };\n}\n\ndeclare const lynxWorkletImpl: LynxWorkletImpl | undefined;\n\n// ---------------------------------------------------------------------------\n// runOnBackground — the global function called in extracted LEPUS code\n// ---------------------------------------------------------------------------\n\nexport function runOnBackground(\n handle: JsFnHandle,\n): (...args: unknown[]) => Promise<unknown> {\n return (...params: unknown[]): Promise<unknown> => {\n return new Promise((resolve) => {\n if (!resolveMap) initReturnListener();\n const resolveId = nextResolveId++;\n resolveMap!.set(resolveId, resolve);\n\n if (\n handle._isFirstScreen\n && typeof lynxWorkletImpl !== 'undefined'\n && lynxWorkletImpl?._runOnBackgroundDelayImpl\n ) {\n lynxWorkletImpl._runOnBackgroundDelayImpl.delayRunOnBackground(\n handle,\n (fnId, execId) => dispatch(fnId, params, execId, resolveId),\n );\n return;\n }\n\n if (handle._jsFnId == null || handle._execId == null) {\n // Handle never carried a (fnId, execId) pair — most likely the BG\n // sender did not call registerWorkletCtx. Resolve undefined so the\n // worklet promise settles instead of leaking.\n resolveMap!.delete(resolveId);\n resolve(undefined);\n return;\n }\n\n dispatch(handle._jsFnId, params, handle._execId, resolveId);\n });\n };\n}\n\n// ---------------------------------------------------------------------------\n// Reset — for testing only\n// ---------------------------------------------------------------------------\n\nexport function resetRunOnBackgroundMtState(): void {\n resolveMap = undefined;\n nextResolveId = 1;\n}\n","/**\n * Main Thread (Lepus) bootstrap entry.\n *\n * Injected by @sigx/lynx-plugin as the sole content of the main-thread bundle.\n * Sets up:\n * - globalThis.processData — required by Lynx Lepus runtime (data processor)\n * - globalThis.renderPage — creates the Lynx page root (id=1)\n * - globalThis.updatePage — no-op stub (required by Lynx Lepus runtime)\n * - globalThis.sigxPatchUpdate — receives ops from Background Thread\n */\n\nimport { elements, setPageUniqueId } from './element-registry.js';\nimport { applyOps, resetMainThreadState, setPlaceholder } from './ops-apply.js';\nimport { invokeWorklet } from './worklet-events.js';\nimport { runOnBackground } from './run-on-background-mt.js';\nimport { installAvBridgeFlushHook } from './animated-bridge-mt.js';\n\nconst g = globalThis as Record<string, unknown>;\n\n// CRITICAL: SystemInfo must be set BEFORE the @lynx-js/react/worklet-runtime\n// IIFE evaluates (it reads SystemInfo as a free identifier at init time).\n// lynx-plugin orders MT entries [entry-main, worklet-runtime, ...userImports]\n// so this module body runs before the worklet-runtime entry. Keeping the\n// install in module body (not an import) prevents vite from hoisting it.\nif (g['SystemInfo'] === undefined) {\n const lynxObj = (g as { lynx?: { SystemInfo?: unknown } })['lynx'];\n g['SystemInfo'] = lynxObj?.SystemInfo ?? {};\n}\n\n/** PAGE_ROOT_ID must match the value used in the BG-thread renderer */\nconst PAGE_ROOT_ID = 1;\n\n// Lynx Lepus runtime requires globalThis.processData to be set.\n// It is called to transform initial data before renderPage runs.\n// For sigx we have no data processors, so just pass data through.\ng['processData'] = function (data: unknown, _processorName?: string): unknown {\n return data ?? {};\n};\n\n// Lynx calls renderPage on the Main Thread first (before Background JS runs).\n// We create the root page element and store it as id=1 so Background ops that\n// target the root can resolve it correctly.\ng['renderPage'] = function (_data: unknown): void {\n resetMainThreadState();\n const page = __CreatePage('0', 0);\n __SetCSSId([page], 0);\n setPageUniqueId(__GetElementUniqueID(page));\n elements.set(PAGE_ROOT_ID, page);\n\n // Append a placeholder __CreateView under the page root so the host sees a\n // non-empty tree immediately. Without this, the host's \"no UI within timeout\"\n // check fires before the BG thread's first ops batch arrives, producing a\n // phantom USER_RUNTIME_ERROR. The placeholder is removed on the first\n // applyOps() call (see ops-apply.ts).\n const placeholder = __CreateView(__GetElementUniqueID(page));\n __SetCSSId([placeholder], 0);\n __AppendElement(page, placeholder);\n setPlaceholder(page, placeholder);\n\n __FlushElementTree(page);\n};\n\n// Lynx may call updatePage / updateGlobalProps after data changes.\n// We have no data binding on Main Thread, so these are no-ops.\ng['updatePage'] = function (_data: unknown): void {\n // no-op\n};\n\ng['updateGlobalProps'] = function (_data: unknown): void {\n // no-op\n};\n\n// Called by the BG Thread via callLepusMethod('sigxHotReload', {}) when a\n// webpack HMR update is about to be applied. Resets the Main Thread element\n// registry and re-creates the page root so the next sigxPatchUpdate batch\n// builds on a clean tree.\n//\n// NOTE: With component-level HMR, component file changes are self-accepted\n// by the HMR loader and patched in-place on the BG thread — this handler\n// is NOT involved. It exists as a safety net for future non-component\n// reload scenarios (e.g., if a host decides to send sigxHotReload\n// explicitly). See docs/hmr-investigation.md.\ng['sigxHotReload'] = function (): void {\n const existingPage = elements.get(PAGE_ROOT_ID);\n resetMainThreadState();\n\n const page = existingPage ?? __CreatePage('0', 0);\n __SetCSSId([page], 0);\n setPageUniqueId(__GetElementUniqueID(page));\n elements.set(PAGE_ROOT_ID, page);\n\n const placeholder = __CreateView(__GetElementUniqueID(page));\n __SetCSSId([placeholder], 0);\n __AppendElement(page, placeholder);\n setPlaceholder(page, placeholder);\n\n __FlushElementTree(page);\n};\n\n// Called by the BG Thread via callLepusMethod('sigxApplyMtHotUpdate', { code }).\n// `code` is the concatenated `registerWorkletInternal(...)` calls extracted\n// from the matching `main__main-thread.<hash>.hot-update.js` file. Eval'd in\n// the existing realm so new content-hash worklet IDs land in the live\n// `_workletMap` before the user taps a re-rendered button.\n//\n// See `lynx-runtime/src/mt-hmr-bridge.ts` for the BG-side fetch + forward.\ng['sigxApplyMtHotUpdate'] = function ({ code }: { code: string }): void {\n if (!code) return;\n try {\n new Function(code)();\n } catch (e) {\n console.log('[sigx-mt] sigxApplyMtHotUpdate eval failed:', String(e));\n }\n};\n\n// Called by the BG Thread via callLepusMethod('sigxPatchUpdate', { data }).\ng['sigxPatchUpdate'] = function ({ data }: { data: string }): void {\n let ops: unknown[];\n try {\n ops = JSON.parse(data) as unknown[];\n } catch (e) {\n console.log('[sigx-mt] sigxPatchUpdate JSON parse failed:', String(e));\n return;\n }\n try {\n applyOps(ops);\n } catch (e) {\n console.log('[sigx-mt] applyOps threw:', String(e));\n }\n // applyOps() already calls __FlushElementTree() at its tail.\n};\n\n// ---------------------------------------------------------------------------\n// runOnMainThread bridge (BG → MT worklet invocation)\n//\n// Called by the BG Thread via callLepusMethod('sigxRunOnMT',\n// { wkltId, args, captured }). When `captured` is supplied, route through\n// upstream's `runWorklet({_wkltId, _c}, args)` so its `I()` walker hydrates\n// the placeholders inside `_c` (resolves nested `{_wkltId}` worklet refs to\n// callable functions and `{_wvid}` ref placeholders to live MainThreadRefs\n// from `_workletRefMap`). This matches the path SET_WORKLET_EVENT uses for\n// JSX-attached MT handlers, and is what makes captures like\n// `runOnMainThread(() => { 'main thread'; withSpring(sv, 0); })` work\n// (`withSpring` is a worklet placeholder that needs hydration before the\n// destructure-and-call inside the body).\n//\n// `invokeWorklet` is kept as a fallback for the `captured === undefined`\n// case (no captures to hydrate) and for direct-from-MT callers that already\n// hand over a hydrated ctx.\n// ---------------------------------------------------------------------------\n\ng['sigxRunOnMT'] = function (\n { wkltId, args, captured }: { wkltId: string; args: unknown[]; captured?: Record<string, unknown> },\n callback?: (result: unknown) => void,\n): void {\n const argsArr = args ?? [];\n let result: unknown;\n const runWorkletFn = (globalThis as Record<string, unknown>)['runWorklet'] as\n | ((placeholder: { _wkltId: string; _c?: Record<string, unknown> }, args: unknown[]) => unknown)\n | undefined;\n if (captured && typeof runWorkletFn === 'function') {\n try {\n result = runWorkletFn({ _wkltId: wkltId, _c: captured }, argsArr);\n } catch (e) {\n console.log('[sigx-mt] sigxRunOnMT worklet threw:', String(e));\n result = undefined;\n }\n } else {\n result = invokeWorklet(wkltId, captured, argsArr);\n }\n if (typeof callback === 'function') {\n callback(result);\n }\n};\n\n// MT-side worklet event dispatch is handled natively: the SET_WORKLET_EVENT\n// op handler in ops-apply.ts calls __AddEvent with `{ type: 'worklet', value }`,\n// and Lynx native routes those to globalThis.runWorklet (installed by the\n// @lynx-js/react/worklet-runtime side-effect import above).\n\n// Install the SharedValue bridge flush hook. Wraps __FlushElementTree so\n// every native flush also runs flushAvBridgePublishes (covers the\n// touchmove path: worklet writes SharedValue → calls setStyleProperties →\n// upstream queues a __FlushElementTree microtask → our wrapper publishes\n// diffed SharedValues to BG before the tree flush). Idempotent.\ninstallAvBridgeFlushHook();\n\n// ---------------------------------------------------------------------------\n// runOnBackground bridge (MT → BG worklet invocation)\n//\n// SWC's LEPUS pass leaves bare `runOnBackground(_jsFnK)` references in the\n// extracted worklet body — they resolve as a free identifier. Install our\n// MT-side dispatcher as a global so those calls reach the BG event bus.\n// ---------------------------------------------------------------------------\ng['runOnBackground'] = runOnBackground;\n"],"mappings":"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"}
@@ -1,58 +0,0 @@
1
- //#region src/hybrid-worklet.ts
2
- var e = "__sigx_hybrid_dispatch__";
3
- function t(e) {
4
- if (this._c.realCtx) try {
5
- this._c.realCtx(e);
6
- } catch (e) {
7
- console.log("[sigx-mt] hybrid worklet body threw:", String(e));
8
- }
9
- this._c.bgSign && n(this._c.bgSign, e);
10
- }
11
- function n(e, t) {
12
- let n = globalThis.lynx;
13
- if (!n) {
14
- console.log("[sigx-mt] bridgeToBg: globalThis.lynx is undefined");
15
- return;
16
- }
17
- let r = n.getJSContext?.();
18
- if (!r) {
19
- console.log("[sigx-mt] bridgeToBg: lynx.getJSContext() returned", typeof r);
20
- return;
21
- }
22
- if (!r.dispatchEvent) {
23
- console.log("[sigx-mt] bridgeToBg: jsContext has no dispatchEvent", Object.keys(r).join(","));
24
- return;
25
- }
26
- let i;
27
- try {
28
- i = JSON.stringify({
29
- sign: e,
30
- event: t
31
- });
32
- } catch (e) {
33
- console.log("[sigx-mt] bridgeToBg: JSON.stringify failed", String(e));
34
- return;
35
- }
36
- console.log("[sigx-mt] bridgeToBg: dispatching to BG, sign=", e), r.dispatchEvent({
37
- type: "Lynx.Sigx.PublishEvent",
38
- data: i
39
- });
40
- }
41
- function r() {
42
- let n = globalThis.lynxWorkletImpl;
43
- n && (n._workletMap[e] = t);
44
- }
45
- function i(t, n) {
46
- return {
47
- _wkltId: e,
48
- _workletType: "main-thread",
49
- _c: {
50
- realCtx: t,
51
- bgSign: n
52
- }
53
- };
54
- }
55
- //#endregion
56
- export { i as n, r, e as t };
57
-
58
- //# sourceMappingURL=hybrid-worklet-nTcCh-mA.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hybrid-worklet-nTcCh-mA.js","names":[],"sources":["../src/hybrid-worklet.ts"],"sourcesContent":["/**\n * Hybrid worklet — combines a user worklet handler and a BG-side handler\n * into a single registration that fits Lynx's one-handler-per-slot rule.\n *\n * Registered ONCE at MT init under the stable id `__sigx_hybrid_dispatch__`\n * in upstream's `lynxWorkletImpl._workletMap`. When the slot machine sees a\n * slot with both a worklet and a BG sign, it asks `hybridCtx(worklet, sign)`\n * for the ctx to hand to `__AddEvent({ type: 'worklet', value })`.\n *\n * Lynx native dispatches via `runWorklet` → upstream's `transformWorklet`\n * walks the ctx and `_c`. It detects nested `_wkltId` (our `realCtx`) and\n * replaces it with the bound user-worklet callable. Our hybrid body then\n * just invokes it, then bridges to BG via the `Lynx.Sigx.PublishEvent`\n * channel that `bg-bridge.ts` listens on.\n */\n\nimport type { WorkletPlaceholder } from './worklet-events.js';\n\nexport const HYBRID_WORKLET_ID = '__sigx_hybrid_dispatch__';\n\ninterface HybridThis {\n _c: {\n /** After transformWorklet walks _c, this is the bound user worklet. */\n realCtx?: (event: unknown) => void;\n bgSign?: string;\n };\n}\n\nfunction hybridDispatch(this: HybridThis, event: unknown): void {\n if (this._c.realCtx) {\n try { this._c.realCtx(event); }\n catch (e) { console.log('[sigx-mt] hybrid worklet body threw:', String(e)); }\n }\n if (this._c.bgSign) bridgeToBg(this._c.bgSign, event);\n}\n\ninterface JSContextLike {\n dispatchEvent?: (e: { type: string; data: string }) => void;\n}\ninterface LynxLike {\n getJSContext?: () => JSContextLike;\n}\n\nfunction bridgeToBg(sign: string, event: unknown): void {\n const lynxObj = (globalThis as { lynx?: LynxLike }).lynx;\n if (!lynxObj) {\n console.log('[sigx-mt] bridgeToBg: globalThis.lynx is undefined');\n return;\n }\n const ctx = lynxObj.getJSContext?.();\n if (!ctx) {\n console.log('[sigx-mt] bridgeToBg: lynx.getJSContext() returned', typeof ctx);\n return;\n }\n if (!ctx.dispatchEvent) {\n console.log('[sigx-mt] bridgeToBg: jsContext has no dispatchEvent', Object.keys(ctx as object).join(','));\n return;\n }\n let data: string;\n try { data = JSON.stringify({ sign, event }); }\n catch (e) {\n console.log('[sigx-mt] bridgeToBg: JSON.stringify failed', String(e));\n return;\n }\n console.log('[sigx-mt] bridgeToBg: dispatching to BG, sign=', sign);\n ctx.dispatchEvent({ type: 'Lynx.Sigx.PublishEvent', data });\n}\n\n/**\n * Install the hybrid worklet into upstream's worklet map. Must be called\n * AFTER the @lynx-js/react/worklet-runtime IIFE has populated\n * globalThis.lynxWorkletImpl. Idempotent — safe to call across hot reloads.\n */\nexport function installHybridWorklet(): void {\n const impl = (globalThis as { lynxWorkletImpl?: { _workletMap: Record<string, Function> } })\n .lynxWorkletImpl;\n if (impl) impl._workletMap[HYBRID_WORKLET_ID] = hybridDispatch as Function;\n}\n\n/** Build the ctx for a hybrid registration. */\nexport function hybridCtx(realCtx: WorkletPlaceholder, bgSign: string): {\n _wkltId: string;\n _workletType: 'main-thread';\n _c: { realCtx: WorkletPlaceholder; bgSign: string };\n} {\n return {\n _wkltId: HYBRID_WORKLET_ID,\n _workletType: 'main-thread',\n _c: { realCtx, bgSign },\n };\n}\n"],"mappings":";AAkBA,IAAa,IAAoB;AAUjC,SAAS,EAAiC,GAAsB;CAC9D,IAAI,KAAK,GAAG,SACV,IAAI;EAAE,KAAK,GAAG,QAAQ,EAAM;UACrB,GAAG;EAAE,QAAQ,IAAI,wCAAwC,OAAO,EAAE,CAAC;;CAE5E,AAAI,KAAK,GAAG,UAAQ,EAAW,KAAK,GAAG,QAAQ,EAAM;;AAUvD,SAAS,EAAW,GAAc,GAAsB;CACtD,IAAM,IAAW,WAAmC;CACpD,IAAI,CAAC,GAAS;EACZ,QAAQ,IAAI,qDAAqD;EACjE;;CAEF,IAAM,IAAM,EAAQ,gBAAgB;CACpC,IAAI,CAAC,GAAK;EACR,QAAQ,IAAI,sDAAsD,OAAO,EAAI;EAC7E;;CAEF,IAAI,CAAC,EAAI,eAAe;EACtB,QAAQ,IAAI,wDAAwD,OAAO,KAAK,EAAc,CAAC,KAAK,IAAI,CAAC;EACzG;;CAEF,IAAI;CACJ,IAAI;EAAE,IAAO,KAAK,UAAU;GAAE;GAAM;GAAO,CAAC;UACrC,GAAG;EACR,QAAQ,IAAI,+CAA+C,OAAO,EAAE,CAAC;EACrE;;CAGF,AADA,QAAQ,IAAI,kDAAkD,EAAK,EACnE,EAAI,cAAc;EAAE,MAAM;EAA0B;EAAM,CAAC;;AAQ7D,SAAgB,IAA6B;CAC3C,IAAM,IAAQ,WACX;CACH,AAAI,MAAM,EAAK,YAAY,KAAqB;;AAIlD,SAAgB,EAAU,GAA6B,GAIrD;CACA,OAAO;EACL,SAAS;EACT,cAAc;EACd,IAAI;GAAE;GAAS;GAAQ;EACxB"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/mt-element.ts","../src/index.ts"],"sourcesContent":["/**\n * MainThread element wrapper — provides a high-level API over raw PAPI\n * element handles for use in main-thread event handlers.\n *\n * When a MainThreadRef's `.current` is set, it receives one of these\n * wrappers so user code can call:\n * - setStyleProperties({ transform: '...' })\n * - getComputedStyleProperty('width')\n * - animate(keyframes, options)\n *\n * These methods call Lynx PAPI directly on the main thread — no cross-thread\n * round-trip, enabling zero-latency UI updates.\n */\n\n// ---------------------------------------------------------------------------\n// Animation types\n// ---------------------------------------------------------------------------\n\nexport interface AnimationKeyframe {\n [property: string]: string | number;\n}\n\nexport interface AnimationOptions {\n duration?: number;\n delay?: number;\n iterations?: number;\n direction?: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse';\n easing?: string;\n fill?: 'none' | 'forwards' | 'backwards' | 'both';\n name?: string;\n 'play-state'?: 'running' | 'paused';\n}\n\nexport interface Animation {\n play(): void;\n pause(): void;\n cancel(): void;\n}\n\n// ---------------------------------------------------------------------------\n// MTElementWrapper\n// ---------------------------------------------------------------------------\n\n/**\n * Module-level latch that microtask-debounces `__FlushElementTree()` across\n * every MTElementWrapper write within a single microtask. Mirrors the\n * pattern in upstream `@lynx-js/react`'s `Element` class\n * (`runtime/lib/worklet-runtime/api/element.js`):\n *\n * - First write in a microtask: schedule one Promise-microtask to flush.\n * - Subsequent writes (same wrapper or any other) before the microtask\n * fires: no-op (`willFlush` is already `true`).\n * - Microtask runs: clear the latch, call the (animated-bridge-wrapped)\n * `__FlushElementTree()` exactly once.\n *\n * Why the latch is module-level, not per-instance: a single tick often\n * touches multiple element wrappers (e.g. `<Draggable>` writes its own\n * transform AND issues `scrollBy` on the parent `<scroll-view>`). Two\n * wrappers, two writes, but the native flush is a tree-wide operation —\n * coalescing them into one is the whole point.\n *\n * Without this debounce, each of `setStyleProperties` / `setStyleProperty`\n * / `setAttribute` / `invoke` was firing a synchronous\n * `__FlushElementTree()`, paying the full layout pass per-call. The\n * stutter showed up most obviously in the `<Draggable edgeScroll>` rAF\n * tick (one transform write + one scrollBy invoke = 2 flushes/frame).\n */\nlet willFlush = false;\n\nexport class MTElementWrapper {\n /** The raw PAPI element handle. */\n readonly _el: MainThreadElement;\n\n constructor(el: MainThreadElement) {\n this._el = el;\n }\n\n /**\n * Coalesce multiple element writes into a single `__FlushElementTree()`\n * call at the end of the current microtask. See `willFlush` doc for the\n * full rationale; mirrors `Element.flushElementTree` in upstream\n * `@lynx-js/react`.\n *\n * `__FlushElementTree` itself is wrapped by `animated-bridge-mt` to\n * apply pending `useAnimatedStyle` bindings before the native flush, so\n * the debounce automatically coalesces SV-binding application too.\n */\n flushElementTree(): void {\n if (willFlush) return;\n willFlush = true;\n void Promise.resolve().then(() => {\n willFlush = false;\n __FlushElementTree();\n });\n }\n\n /**\n * Synchronously update inline styles on this element.\n * This bypasses the BG→MT op queue — styles are applied immediately\n * on the main thread, making it ideal for scroll-driven animations.\n *\n * The native `__FlushElementTree` call is microtask-debounced (see\n * `flushElementTree`), so chaining multiple writes within one tick\n * pays for a single flush instead of one per call.\n *\n * @example\n * ```ts\n * ref.current?.setStyleProperties({\n * transform: `translateX(${offset}px)`,\n * opacity: `${1 - ratio}`,\n * });\n * ```\n */\n setStyleProperties(styles: Record<string, string | number>): void {\n __SetInlineStyles(this._el, styles);\n this.flushElementTree();\n }\n\n /**\n * Get a computed style property value from this element.\n *\n * @param name - CSS property name in kebab-case (e.g. 'background-color')\n * @returns The computed value as a string\n */\n getComputedStyleProperty(name: string): string {\n if (typeof __GetComputedStyleByKey === 'function') {\n return __GetComputedStyleByKey(this._el, name);\n }\n return '';\n }\n\n /**\n * Get a single attribute value by name. Returns the value as set via\n * `setAttribute` (or by a parent component); does not resolve aliases.\n */\n getAttribute(name: string): unknown {\n if (typeof __GetAttributeByName === 'function') {\n return __GetAttributeByName(this._el, name);\n }\n return undefined;\n }\n\n /**\n * Get the list of attribute names currently set on this element.\n */\n getAttributeNames(): string[] {\n if (typeof __GetAttributeNames === 'function') {\n return __GetAttributeNames(this._el);\n }\n return [];\n }\n\n /**\n * Find the first descendant element matching the CSS selector.\n * Mirrors `Element.prototype.querySelector` from the DOM.\n *\n * Returns `null` when no match is found OR when the host runtime does not\n * provide `__QuerySelector` (older Lynx SDKs).\n */\n querySelector(selector: string): MTElementWrapper | null {\n if (typeof __QuerySelector !== 'function') return null;\n const ref = __QuerySelector(this._el, selector, {});\n return ref ? new MTElementWrapper(ref) : null;\n }\n\n /**\n * Find every descendant element matching the CSS selector. Returns an empty\n * array when nothing matches OR when the host runtime does not provide\n * `__QuerySelectorAll`.\n */\n querySelectorAll(selector: string): MTElementWrapper[] {\n if (typeof __QuerySelectorAll !== 'function') return [];\n return __QuerySelectorAll(this._el, selector, {})\n .map((el) => new MTElementWrapper(el));\n }\n\n /**\n * Invoke a UI method exposed by the underlying native element (e.g.\n * `scrollIntoView` on `<scroll-view>`, `scrollToIndex` on `<list>`).\n *\n * Resolves with the method's `data` payload on success (`code === 0`);\n * rejects with an Error containing the JSON-stringified response otherwise.\n */\n invoke(methodName: string, params?: Record<string, unknown>): Promise<unknown> {\n return new Promise((resolve, reject) => {\n if (typeof __InvokeUIMethod !== 'function') {\n reject(new Error('UI method invoke: __InvokeUIMethod not available'));\n return;\n }\n __InvokeUIMethod(this._el, methodName, params ?? {}, (res) => {\n if (res.code === 0) resolve(res.data);\n else reject(new Error('UI method invoke: ' + JSON.stringify(res)));\n });\n this.flushElementTree();\n });\n }\n\n /**\n * Start a keyframe animation on this element using the Lynx animation API.\n *\n * @param keyframes - Array of keyframe objects\n * @param options - Animation configuration\n * @returns Animation controller with play/pause/cancel methods\n *\n * @example\n * ```ts\n * ref.current?.animate(\n * [{ opacity: 0 }, { opacity: 1 }],\n * { duration: 300, easing: 'ease-in-out' }\n * );\n * ```\n */\n animate(\n keyframes: AnimationKeyframe[],\n options: AnimationOptions = {},\n ): Animation | null {\n const el = this._el as any;\n if (typeof el.animate === 'function') {\n return el.animate(keyframes, options) as Animation;\n }\n return null;\n }\n\n /**\n * Set a single attribute on this element. Microtask-debounced flush —\n * see `flushElementTree`.\n */\n setAttribute(key: string, value: unknown): void {\n __SetAttribute(this._el, key, value);\n this.flushElementTree();\n }\n\n /**\n * Set a single inline style property. Microtask-debounced flush — see\n * `flushElementTree`.\n */\n setStyleProperty(name: string, value: string | number): void {\n __AddInlineStyle(this._el, name, value);\n this.flushElementTree();\n }\n}\n","/// <reference path=\"./shims.d.ts\" />\n\n// Side-effect import — entry-main.ts registers globalThis.renderPage /\n// processData / sigxPatchUpdate / sigxRunOnMT and side-effect imports\n// @lynx-js/react/worklet-runtime which installs lynxWorkletImpl /\n// registerWorkletInternal / runWorklet. Must run at module load time so\n// the main-thread entry of the Lynx template has these globals.\nimport './entry-main.js';\n\nexport { elements, pageUniqueId, setPageUniqueId } from './element-registry.js';\nexport { applyOps, resetMainThreadState } from './ops-apply.js';\nexport { MTElementWrapper } from './mt-element.js';\nexport { invokeWorklet, type WorkletPlaceholder } from './worklet-events.js';\nexport {\n setSlotWorklet,\n setSlotBgSign,\n flushDirtySlots,\n resetSlotStates,\n} from './event-slots.js';\nexport {\n HYBRID_WORKLET_ID,\n hybridCtx,\n installHybridWorklet,\n} from './hybrid-worklet.js';\n\n/**\n * Compatibility shim — upstream's worklet-runtime provides the canonical\n * `loadWorkletRuntime`, but @lynx-js/react/transform's LEPUS output imports\n * it from `runtimePkg`. Our MT loader strips the import + gating before\n * shipping registrations, so this re-export is only for the rare case where\n * upstream's raw output is used unstripped (tests, future Phase 1c).\n */\nexport function loadWorkletRuntime(_globDynamicComponentEntry?: unknown): boolean {\n return true;\n}\n"],"mappings":";;;AAmEA,IAAI,IAAY,IAEH,IAAb,MAAa,EAAiB;CAE5B;CAEA,YAAY,GAAuB;EACjC,KAAK,MAAM;;CAab,mBAAyB;EACnB,MACJ,IAAY,IACZ,QAAa,SAAS,CAAC,WAAW;GAEhC,AADA,IAAY,IACZ,oBAAoB;IACpB;;CAoBJ,mBAAmB,GAA+C;EAEhE,AADA,kBAAkB,KAAK,KAAK,EAAO,EACnC,KAAK,kBAAkB;;CASzB,yBAAyB,GAAsB;EAI7C,OAHI,OAAO,2BAA4B,aAC9B,wBAAwB,KAAK,KAAK,EAAK,GAEzC;;CAOT,aAAa,GAAuB;EAClC,IAAI,OAAO,wBAAyB,YAClC,OAAO,qBAAqB,KAAK,KAAK,EAAK;;CAQ/C,oBAA8B;EAI5B,OAHI,OAAO,uBAAwB,aAC1B,oBAAoB,KAAK,IAAI,GAE/B,EAAE;;CAUX,cAAc,GAA2C;EACvD,IAAI,OAAO,mBAAoB,YAAY,OAAO;EAClD,IAAM,IAAM,gBAAgB,KAAK,KAAK,GAAU,EAAE,CAAC;EACnD,OAAO,IAAM,IAAI,EAAiB,EAAI,GAAG;;CAQ3C,iBAAiB,GAAsC;EAErD,OADI,OAAO,sBAAuB,aAC3B,mBAAmB,KAAK,KAAK,GAAU,EAAE,CAAC,CAC9C,KAAK,MAAO,IAAI,EAAiB,EAAG,CAAC,GAFa,EAAE;;CAYzD,OAAO,GAAoB,GAAoD;EAC7E,OAAO,IAAI,SAAS,GAAS,MAAW;GACtC,IAAI,OAAO,oBAAqB,YAAY;IAC1C,EAAO,gBAAI,MAAM,mDAAmD,CAAC;IACrE;;GAMF,AAJA,iBAAiB,KAAK,KAAK,GAAY,KAAU,EAAE,GAAG,MAAQ;IAC5D,AAAI,EAAI,SAAS,IAAG,EAAQ,EAAI,KAAK,GAChC,EAAO,gBAAI,MAAM,uBAAuB,KAAK,UAAU,EAAI,CAAC,CAAC;KAClE,EACF,KAAK,kBAAkB;IACvB;;CAkBJ,QACE,GACA,IAA4B,EAAE,EACZ;EAClB,IAAM,IAAK,KAAK;EAIhB,OAHI,OAAO,EAAG,WAAY,aACjB,EAAG,QAAQ,GAAW,EAAQ,GAEhC;;CAOT,aAAa,GAAa,GAAsB;EAE9C,AADA,eAAe,KAAK,KAAK,GAAK,EAAM,EACpC,KAAK,kBAAkB;;CAOzB,iBAAiB,GAAc,GAA8B;EAE3D,AADA,iBAAiB,KAAK,KAAK,GAAM,EAAM,EACvC,KAAK,kBAAkB;;;;;AC9M3B,SAAgB,EAAmB,GAA+C;CAChF,OAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"install-hybrid-worklet.js","names":[],"sources":["../src/install-hybrid-worklet.ts"],"sourcesContent":["/**\n * Side-effect module that installs the hybrid worklet into upstream's\n * `lynxWorkletImpl._workletMap`.\n *\n * Must be loaded AFTER `@lynx-js/react/worklet-runtime` (which populates\n * `lynxWorkletImpl`) but BEFORE user code runs. The MT bootstrap preamble\n * in `lynx-plugin/src/loaders/worklet-loader-mt.ts` lists it third in the\n * import order:\n *\n * 1. @sigx/lynx-runtime-main/entry-main (sets SystemInfo + globals)\n * 2. @lynx-js/react/worklet-runtime (installs lynxWorkletImpl)\n * 3. @sigx/lynx-runtime-main/install-hybrid (this file)\n * 4. user code (calls registerWorkletInternal)\n *\n * Splitting this out is necessary because vite would otherwise hoist any\n * bare `import` statement above whatever sets up its prerequisites.\n */\n\nimport { installHybridWorklet } from './hybrid-worklet.js';\n\ninstallHybridWorklet();\n\nexport {};\n"],"mappings":";;AAoBA,GAAsB"}