@sigx/lynx-runtime-main 0.2.4
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.
- package/LICENSE +21 -0
- package/README.md +28 -0
- package/dist/animated-bridge-mt.d.ts +77 -0
- package/dist/animated-style-mappers.d.ts +38 -0
- package/dist/element-registry.d.ts +14 -0
- package/dist/entry-main-odx1uWxp.js +607 -0
- package/dist/entry-main-odx1uWxp.js.map +1 -0
- package/dist/entry-main.d.ts +11 -0
- package/dist/entry-main.js +1 -0
- package/dist/event-slots.d.ts +31 -0
- package/dist/hybrid-worklet-nTcCh-mA.js +58 -0
- package/dist/hybrid-worklet-nTcCh-mA.js.map +1 -0
- package/dist/hybrid-worklet.d.ts +32 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +64 -0
- package/dist/index.js.map +1 -0
- package/dist/install-hybrid-worklet.d.ts +18 -0
- package/dist/install-hybrid-worklet.js +6 -0
- package/dist/install-hybrid-worklet.js.map +1 -0
- package/dist/mt-element.d.ts +129 -0
- package/dist/ops-apply.d.ts +19 -0
- package/dist/run-on-background-mt.d.ts +23 -0
- package/dist/upstream/processGesture.d.ts +28 -0
- package/dist/worklet-events.d.ts +26 -0
- package/dist/worklet-refs.d.ts +31 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 Andreas Ekdahl
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# @sigx/lynx-runtime-main
|
|
2
|
+
|
|
3
|
+
Main-thread (Lepus) runtime for [SignalX](https://github.com/signalxjs) on Lynx. Receives the op stream from `@sigx/lynx-runtime`, mutates the native render tree via Lynx PAPI, and runs `'main thread'`-marked worklets at the host's display refresh rate.
|
|
4
|
+
|
|
5
|
+
> Application code rarely imports from this package directly. The build pipeline ([`@sigx/lynx-plugin`](../lynx-plugin)) wires it into the main-thread bundle automatically.
|
|
6
|
+
|
|
7
|
+
## Responsibilities
|
|
8
|
+
|
|
9
|
+
- **`entry-main.ts`** — installs `globalThis.processData`, `renderPage`, `updatePage`, `sigxPatchUpdate`, `sigxRunOnMT`, and `runOnBackground`. This is the file the build plugin lists as the first import in the MT bundle so the Lynx runtime finds the global hooks it expects.
|
|
10
|
+
- **`ops-apply.ts`** — the `applyOps` loop that consumes the BG → MT op stream (`CREATE`, `INSERT`, `SET_STYLE`, `SET_WORKLET_EVENT`, `INIT_MT_REF`, `REGISTER_AV_BRIDGE`, ...) and translates them into PAPI calls (`__CreatePage`, `__SetInlineStyles`, `__AddEvent`, etc.).
|
|
11
|
+
- **`MTElementWrapper`** — high-level wrapper your worklets drive via `mainThreadRef.current.method(...)` (`setStyleProperties`, `getComputedStyleProperty`, `animate`, `invoke`, query selectors).
|
|
12
|
+
- **Hybrid worklet dispatch** — the slot machine in `event-slots.ts` plus the hybrid context in `hybrid-worklet.ts` lets a single MT slot carry both a worklet handler *and* a BG-side handler for the same event, dispatching to both.
|
|
13
|
+
- **AnimatedValue bridge** — `animated-bridge-mt.ts` diffs registered AVs against last-published snapshots and dispatches batched `Lynx.Sigx.AvPublish` events to BG once per `__FlushElementTree` boundary. The matching BG sink lives in `@sigx/lynx-runtime`.
|
|
14
|
+
- **`useAnimatedStyle` mapper registry** — `animated-style-mappers.ts` ships built-in mappers (`translateX`, `scale`, `opacity`, ...) and exposes `registerMapper(name, fn)` so MT-side code can add custom ones.
|
|
15
|
+
|
|
16
|
+
## Bootstrap order
|
|
17
|
+
|
|
18
|
+
Three modules must evaluate in this order on the MT thread:
|
|
19
|
+
|
|
20
|
+
1. `entry-main` — sets `globalThis.SystemInfo` and the renderer hooks.
|
|
21
|
+
2. `@lynx-js/react/worklet-runtime` — installs `lynxWorkletImpl`, `registerWorkletInternal`, `runWorklet`.
|
|
22
|
+
3. `install-hybrid-worklet` — registers the hybrid dispatcher into the now-populated worklet map.
|
|
23
|
+
|
|
24
|
+
`@sigx/lynx-plugin` prepends side-effect imports for these three at the top of every file in the MT bundle, so the order is enforced regardless of which user file the Lynx runtime evaluates first.
|
|
25
|
+
|
|
26
|
+
## License
|
|
27
|
+
|
|
28
|
+
MIT
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MT-side SharedValue bridge — publishes MT-thread mutations to BG.
|
|
3
|
+
*
|
|
4
|
+
* Diffs every registered SharedValue against its last-published snapshot
|
|
5
|
+
* and dispatches one batched `Lynx.Sigx.AvPublish` event per flush boundary
|
|
6
|
+
* with the changed `[wvid, value]` tuples. The BG side ingests these via
|
|
7
|
+
* `@sigx/lynx-runtime/src/animated-bridge.ts` and writes them into the
|
|
8
|
+
* mirror signal so any sigx `effect` reading `sv.value` re-runs.
|
|
9
|
+
*
|
|
10
|
+
* Bridge state (`bridgedAvWvids` / `bridgedAvLastValues`) lives in
|
|
11
|
+
* `ops-apply.ts` because the BG→MT op handlers mutate it; this module
|
|
12
|
+
* imports the references and reads them on every flush.
|
|
13
|
+
*
|
|
14
|
+
* Two flush hook points:
|
|
15
|
+
* 1. `ops-apply.ts` calls `flushAvBridgePublishes()` at its tail (covers
|
|
16
|
+
* every BG-driven ops batch).
|
|
17
|
+
* 2. `installAvBridgeFlushHook()` wraps `globalThis.__FlushElementTree`
|
|
18
|
+
* so spontaneous MT writes (e.g. a touchmove worklet that eventually
|
|
19
|
+
* calls `setStyleProperties`) also trigger a publish on the same
|
|
20
|
+
* tick the native tree flushes. Called once from `entry-main.ts`
|
|
21
|
+
* after PAPI globals are present.
|
|
22
|
+
*
|
|
23
|
+
* Coalescing: `===` per-wvid diff. Identical writes are filtered. N writes
|
|
24
|
+
* within one flush window collapse to one BG event with N entries.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Diff registered AVs against their last-published snapshots; dispatch one
|
|
28
|
+
* batched `Lynx.Sigx.AvPublish` event with all changed tuples. No-op when
|
|
29
|
+
* the bridge set is empty or when nothing has changed since the last call.
|
|
30
|
+
*/
|
|
31
|
+
export declare function flushAvBridgePublishes(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Register a binding (called from the OP.REGISTER_AV_STYLE_BINDING op
|
|
34
|
+
* handler in `ops-apply.ts`). Initializes `lastValue` to a sentinel so the
|
|
35
|
+
* first flush always applies the mapper, even when the AV is at its initial.
|
|
36
|
+
*/
|
|
37
|
+
export declare function registerAnimatedStyleBinding(bindingId: number, elementWvid: number, avWvid: number, mapperName: string, params: unknown): void;
|
|
38
|
+
export declare function unregisterAnimatedStyleBinding(bindingId: number): void;
|
|
39
|
+
export declare function resetAnimatedStyleBindings(): void;
|
|
40
|
+
export declare function animatedStyleBindingCount(): number;
|
|
41
|
+
/**
|
|
42
|
+
* For each element with at least one *dirty* binding (AV value changed since
|
|
43
|
+
* the last apply), re-run **all** of that element's bindings, merge their
|
|
44
|
+
* mapper outputs, and apply the result with a single `setStyleProperties`
|
|
45
|
+
* call. Called from the wrapped `__FlushElementTree` *before* the native
|
|
46
|
+
* tree flush.
|
|
47
|
+
*
|
|
48
|
+
* Why "all bindings on a dirty element" rather than "only changed bindings":
|
|
49
|
+
* - Multiple bindings on the same element can write the same style key
|
|
50
|
+
* (e.g. `translateX` + `translateY` both produce `transform`). If we
|
|
51
|
+
* applied only the changed ones, the unchanged-binding's contribution
|
|
52
|
+
* would be lost and the element would visibly snap. By re-running every
|
|
53
|
+
* binding on the dirty element and merging, all contributions land in
|
|
54
|
+
* the same `setStyleProperties` call.
|
|
55
|
+
*
|
|
56
|
+
* Merge semantics:
|
|
57
|
+
* - `transform` values from multiple bindings *concatenate* in registration
|
|
58
|
+
* order (e.g. `translateX(50px)` + `translateY(20px)` ->
|
|
59
|
+
* `translateX(50px) translateY(20px)`).
|
|
60
|
+
* - All other keys merge by last-write-wins; a binding registered later on
|
|
61
|
+
* the same element overwrites an earlier binding's same-key output.
|
|
62
|
+
*
|
|
63
|
+
* Skip cases (silent, by design):
|
|
64
|
+
* - AV ref missing in `_workletRefMap` (race with unregister).
|
|
65
|
+
* - Element ref's `current` is null (component not yet mounted, or
|
|
66
|
+
* unmounted before the binding's UNREGISTER op landed).
|
|
67
|
+
* - Mapper name not registered (typo or missing custom registration).
|
|
68
|
+
*/
|
|
69
|
+
export declare function flushAnimatedStyleBindings(): void;
|
|
70
|
+
/**
|
|
71
|
+
* Wrap `globalThis.__FlushElementTree` once so every flush also runs the AV
|
|
72
|
+
* bridge publish step. Idempotent — safe to call across hot reloads. Test
|
|
73
|
+
* setups that `vi.stubGlobal('__FlushElementTree', ...)` AFTER this hook
|
|
74
|
+
* installs will replace our wrapper, which is the correct behavior for
|
|
75
|
+
* unit tests that drive `flushAvBridgePublishes` directly.
|
|
76
|
+
*/
|
|
77
|
+
export declare function installAvBridgeFlushHook(): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MT-side mapper registry for `useAnimatedStyle`.
|
|
3
|
+
*
|
|
4
|
+
* Maps a `SharedValue`'s current scalar to a partial style object that the
|
|
5
|
+
* binding flush passes to `setStyleProperties` on the bound element. Keyed by
|
|
6
|
+
* a string name (`'translateX'`, `'scale'`, ...) so the SWC worklet transform
|
|
7
|
+
* can capture the selection trivially: a string is a primitive `_c` value
|
|
8
|
+
* with no special lifting required (unlike arbitrary functions, which can't
|
|
9
|
+
* be captured into a worklet's closure).
|
|
10
|
+
*
|
|
11
|
+
* Custom mappers can be registered via `registerMapper(name, fn)` from MT
|
|
12
|
+
* code (e.g. a `'main thread'`-marked module body in a user app). BG-side
|
|
13
|
+
* `useAnimatedStyle` validates the name only against the type union; a
|
|
14
|
+
* lookup mismatch on MT is a silent no-op at flush time.
|
|
15
|
+
*
|
|
16
|
+
* Param shapes are mapper-specific. The `MapperParams` type in
|
|
17
|
+
* `@sigx/lynx-runtime-internal` is the single source of truth — both
|
|
18
|
+
* BG-side `useAnimatedStyle` and the MT runtime import it from there.
|
|
19
|
+
*
|
|
20
|
+
* Range mapping: `translateX` / `translateY` / `scale` / `opacity` accept
|
|
21
|
+
* either their linear `factor`/`offset` shape or a `RangeParams` shape
|
|
22
|
+
* (`{ inputRange, outputRange, extrapolate? }`). The mapper picks the branch
|
|
23
|
+
* by looking for `inputRange` on the params.
|
|
24
|
+
*/
|
|
25
|
+
import type { AnimatedStyleMapper } from '@sigx/lynx-runtime-internal';
|
|
26
|
+
export type { MapperParams, BuiltinMapperName, AnimatedStyleMapper, RangeParams, } from '@sigx/lynx-runtime-internal';
|
|
27
|
+
/**
|
|
28
|
+
* Look up a registered mapper by name. Returns `undefined` if the name
|
|
29
|
+
* isn't registered — the binding flush treats that as a no-op.
|
|
30
|
+
*/
|
|
31
|
+
export declare function lookupMapper(name: string): AnimatedStyleMapper | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Register a custom MT-side mapper. Idempotent on (name, fn) — last
|
|
34
|
+
* registration wins for the same name. Intended for `'main thread'`-marked
|
|
35
|
+
* user modules that ship project-specific styling math.
|
|
36
|
+
*/
|
|
37
|
+
export declare function registerMapper(name: string, mapper: AnimatedStyleMapper): void;
|
|
38
|
+
export declare function resetMappers(): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Element registry — maps BG-thread ShadowElement IDs to Lynx Main Thread
|
|
3
|
+
* element handles.
|
|
4
|
+
*/
|
|
5
|
+
/** Map from BG-thread ShadowElement id to Lynx Main Thread element handle */
|
|
6
|
+
export declare const elements: Map<number, MainThreadElement>;
|
|
7
|
+
/**
|
|
8
|
+
* PAPI unique ID of the root PageElement.
|
|
9
|
+
* Passed as `parentComponentUniqueId` to element creation PAPI calls.
|
|
10
|
+
* `__SetCSSId` sets `css_style_sheet_manager_` directly on each element,
|
|
11
|
+
* so CSS rendering works without a ComponentElement ancestor.
|
|
12
|
+
*/
|
|
13
|
+
export declare let pageUniqueId: number;
|
|
14
|
+
export declare function setPageUniqueId(id: number): void;
|