@symbiote-native/engine 1.2.0 → 1.3.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.
- package/android/CMakeLists.txt +31 -1
- package/android/build.gradle +4 -1
- package/build/accessibility-info/index.android.js +21 -17
- package/build/accessibility-info/index.ios.js +2 -0
- package/build/accessibility-info/shared.d.ts +1 -1
- package/build/accessibility-props.d.ts +0 -11
- package/build/accessibility-props.js +30 -68
- package/build/alert/shared.d.ts +1 -1
- package/build/alert/shared.js +3 -7
- package/build/animated/graph.js +1 -1
- package/build/animated/leaf-lifecycle.js +2 -2
- package/build/app-state/index.d.ts +1 -1
- package/build/app-state/index.js +35 -27
- package/build/asset-source-resolver.d.ts +2 -0
- package/build/asset-source-resolver.js +13 -0
- package/build/back-handler/index.d.ts +7 -6
- package/build/back-handler/index.js +19 -16
- package/build/debug.js +8 -22
- package/build/dispatch.js +3 -9
- package/build/events/index.js +12 -3
- package/build/fabric-props.js +75 -180
- package/build/fabric.d.ts +2 -8
- package/build/fabric.js +27 -33
- package/build/host-access.d.ts +1 -128
- package/build/host-access.js +96 -205
- package/build/host-behavior.d.ts +1 -100
- package/build/host-behavior.js +125 -311
- package/build/image-loader.d.ts +4 -2
- package/build/image-loader.js +24 -48
- package/build/image-source-resolver.js +3 -7
- package/build/image-source-write.d.ts +1 -12
- package/build/image-source-write.js +28 -36
- package/build/imperative.d.ts +0 -28
- package/build/imperative.js +42 -92
- package/build/index.d.ts +3 -2
- package/build/index.js +30 -43
- package/build/invariant.d.ts +1 -0
- package/build/invariant.js +10 -0
- package/build/keyboard/index.js +11 -32
- package/build/linking/index.android.js +5 -3
- package/build/linking/shared.d.ts +1 -1
- package/build/linking/shared.js +16 -19
- package/build/mutation-buffer.d.ts +0 -177
- package/build/mutation-buffer.js +137 -308
- package/build/native-engine.d.ts +0 -102
- package/build/native-engine.js +38 -98
- package/build/native-events.d.ts +5 -0
- package/build/native-events.js +30 -18
- package/build/native-tree-host.d.ts +0 -21
- package/build/native-tree-host.js +14 -31
- package/build/node.d.ts +0 -212
- package/build/node.js +354 -774
- package/build/permissions-android/index.android.d.ts +59 -0
- package/build/permissions-android/index.android.js +47 -0
- package/build/permissions-android/index.d.ts +1 -115
- package/build/permissions-android/index.ios.d.ts +59 -0
- package/build/permissions-android/index.ios.js +31 -0
- package/build/permissions-android/index.js +3 -184
- package/build/permissions-android/shared.d.ts +63 -0
- package/build/permissions-android/shared.js +66 -0
- package/build/platform/index.android.js +3 -5
- package/build/platform/index.ios.js +3 -3
- package/build/platform/shared.d.ts +4 -0
- package/build/platform/shared.js +9 -0
- package/build/platform-color/index.android.d.ts +4 -0
- package/build/platform-color/index.android.js +7 -0
- package/build/platform-color/index.d.ts +2 -20
- package/build/platform-color/index.js +1 -45
- package/build/platform-color/shared.d.ts +21 -0
- package/build/platform-color/shared.js +41 -0
- package/build/post-commit.js +3 -8
- package/build/process-aspect-ratio.js +3 -7
- package/build/process-background-longhands.js +10 -19
- package/build/process-filter.js +11 -19
- package/build/process-font-variant.js +3 -7
- package/build/registry.d.ts +0 -33
- package/build/registry.js +22 -57
- package/build/report-error.js +4 -18
- package/build/settings/index.android.d.ts +6 -0
- package/build/settings/index.android.js +21 -0
- package/build/settings/index.d.ts +1 -8
- package/build/settings/index.ios.d.ts +8 -0
- package/build/settings/index.ios.js +122 -0
- package/build/settings/index.js +3 -122
- package/build/share/index.android.js +9 -32
- package/build/share/index.ios.js +14 -15
- package/build/share/shared.d.ts +4 -2
- package/build/share/shared.js +7 -10
- package/build/status-bar/index.android.js +1 -1
- package/build/status-bar/index.ios.js +4 -3
- package/build/structured-style.d.ts +0 -9
- package/build/structured-style.js +16 -31
- package/build/styles.js +3 -6
- package/build/surface.d.ts +0 -26
- package/build/surface.js +29 -76
- package/build/text-input-state.js +4 -8
- package/build/toast-android/index.android.d.ts +10 -0
- package/build/toast-android/index.android.js +108 -0
- package/build/toast-android/index.d.ts +1 -10
- package/build/toast-android/index.ios.d.ts +10 -0
- package/build/toast-android/index.ios.js +19 -0
- package/build/toast-android/index.js +3 -108
- package/build/touch-history.js +5 -11
- package/build/tree-host.d.ts +0 -270
- package/build/tree-host.js +63 -153
- package/build/view-config.js +17 -37
- package/cpp/SymbioteFabricProps.cpp +204 -120
- package/cpp/SymbioteFabricProps.h +5 -0
- package/cpp/SymbioteTree.cpp +20 -6
- package/package.json +2 -2
package/build/tree-host.js
CHANGED
|
@@ -1,28 +1,12 @@
|
|
|
1
|
-
// The
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// `mutation-buffer.ts`, and turning that buffer into a tree is the HOST's job: native on device, and
|
|
5
|
-
// headlessly the TypeScript applier in `@symbiote-native/test-utils`, installed by `installFabric()`.
|
|
6
|
-
// That applier lives there for the same reason the fake `nativeFabricUIManager` does — it is a JS
|
|
7
|
-
// stand-in for a native thing, and `core/test-utils` is a devDependency of the adapters rather than a
|
|
8
|
-
// runtime one, so nothing an app loads contains a JS tree.
|
|
9
|
-
//
|
|
10
|
-
// Shaped after `fabric.ts`'s slot seam on purpose: a resolver plus a test-time installer.
|
|
11
|
-
//
|
|
12
|
-
// `undefined` / empty is an ORDINARY answer from every read here, not an error — the same contract
|
|
13
|
-
// `committedRecordOf` already carried. A runtime with no host, a node the host has not seen, and a
|
|
14
|
-
// genuinely absent value are indistinguishable to a caller, and all three degrade.
|
|
1
|
+
// The tree host seam — the one place JS asks about a tree it does not hold. @symbiote-native/engine
|
|
2
|
+
// keeps no tree: every adapter mutation appends an opcode (mutation-buffer.ts), and turning that
|
|
3
|
+
// into a tree is the host's job — native on device, a TypeScript applier headlessly (test-utils).
|
|
15
4
|
import { hasChangedSinceCommit, hasPendingOps, noteCommitDrained, recordCommit, takeBatch, } from './mutation-buffer.js';
|
|
16
5
|
import { nativeEngine } from './native-engine.js';
|
|
17
6
|
import { takePropStats } from './node.js';
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
*
|
|
22
|
-
* Not exported from the package barrel: it is a HOST-author constant, and an app reading a census
|
|
23
|
-
* asserts against a mounted tree, where a zero from here cannot be mistaken for a zero from a real
|
|
24
|
-
* empty tree.
|
|
25
|
-
*/
|
|
7
|
+
// The census of a tree nobody counted — what a host with no walk answers, and what
|
|
8
|
+
// censusRetainedTree answers with no host installed. Not exported from the package barrel: an app
|
|
9
|
+
// reading a census asserts against a mounted tree, so a zero from here must not read as a real one.
|
|
26
10
|
export const EMPTY_CENSUS = {
|
|
27
11
|
nodes: 0,
|
|
28
12
|
anchors: 0,
|
|
@@ -31,45 +15,25 @@ export const EMPTY_CENSUS = {
|
|
|
31
15
|
flattenWidths: [],
|
|
32
16
|
};
|
|
33
17
|
let host;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*
|
|
38
|
-
* Passing `undefined` uninstalls, so a fixture can prove a path degrades rather than throws.
|
|
39
|
-
*/
|
|
18
|
+
// Install the tree host. installFabric() (test-utils) calls this with the TypeScript applier; the
|
|
19
|
+
// native module installs itself the same way. Passing undefined uninstalls, so a fixture can prove
|
|
20
|
+
// a path degrades rather than throws.
|
|
40
21
|
export function setTreeHost(next) {
|
|
41
22
|
host = next;
|
|
42
23
|
}
|
|
43
|
-
|
|
24
|
+
// The installed host, or undefined on a runtime that has none.
|
|
44
25
|
export function treeHost() {
|
|
45
26
|
return host;
|
|
46
27
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
*/
|
|
57
|
-
/**
|
|
58
|
-
* Adapters that COALESCE writes, given the last moment to record what they are holding.
|
|
59
|
-
*
|
|
60
|
-
* An adapter cannot always publish a write the instant its framework hands it over. Angular's
|
|
61
|
-
* styling engine has no whole-value call — `ɵɵstyleMap` delivers one key per `Renderer2.setStyle`
|
|
62
|
-
* — so the renderer accumulates the run and writes RN's one `style` prop once. That accumulator has
|
|
63
|
-
* to be emptied before anything can observe the tree, and the adapter cannot know when that is: a
|
|
64
|
-
* read and a commit both arrive from elsewhere.
|
|
65
|
-
*
|
|
66
|
-
* Both of them come through `flushOps`, which is what makes this the right seam and a cheap one — it
|
|
67
|
-
* is the single door in front of every drain, `commit` included.
|
|
68
|
-
*
|
|
69
|
-
* NOT A COMMIT HOOK. It fires before every read as well, so a listener must be idempotent and must
|
|
70
|
-
* do nothing when it holds nothing. It runs BEFORE the `hasPendingOps` check on purpose: a listener
|
|
71
|
-
* holding a write has ops that are not in the buffer yet, so an empty buffer is no reason to skip it.
|
|
72
|
-
*/
|
|
28
|
+
// Push everything recorded since the last apply into the host. Every read goes through here first
|
|
29
|
+
// — a reconciler navigates the tree mid-build (Vue/Solid/Svelte/Angular all ask for a parent or
|
|
30
|
+
// sibling before commit), so a host only told at completeRoot would answer about a stale tree.
|
|
31
|
+
// Adapters that coalesce writes, given the last moment to record what they're holding. Angular's
|
|
32
|
+
// styling engine has no whole-value call (ɵɵstyleMap delivers one key per setStyle), so the
|
|
33
|
+
// renderer accumulates a run and writes RN's one style prop only once — flushed from here.
|
|
34
|
+
// Not a commit hook: fires before every read too, so a listener must be idempotent and must do
|
|
35
|
+
// nothing when it holds nothing. Runs before the hasPendingOps check, since a listener holding a
|
|
36
|
+
// write has ops not in the buffer yet.
|
|
73
37
|
const beforeFlush = new Set();
|
|
74
38
|
export function registerBeforeFlush(listener) {
|
|
75
39
|
beforeFlush.add(listener);
|
|
@@ -79,13 +43,9 @@ export function registerBeforeFlush(listener) {
|
|
|
79
43
|
// and ask the same listener for what it has already handed over. One flag rather than per-listener
|
|
80
44
|
// bookkeeping: the whole set is being drained, and re-entering any of it is the same mistake.
|
|
81
45
|
let settling = false;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
* Separate from `flushOps` because a read may legitimately decide it needs no drain — `parentOf`
|
|
86
|
-
* skips one for a node whose placement is not pending — and skipping the drain must not also skip
|
|
87
|
-
* asking. A held write is still a write, and a reader that cannot see it is reading a stale tree.
|
|
88
|
-
*/
|
|
46
|
+
// Collect what the listeners are holding, without draining. Separate from flushOps because a read
|
|
47
|
+
// may legitimately decide it needs no drain (parentOf skips one for a node whose placement isn't
|
|
48
|
+
// pending), but skipping the drain must not also skip asking a held write.
|
|
89
49
|
export function settleBeforeFlush() {
|
|
90
50
|
if (settling || beforeFlush.size === 0)
|
|
91
51
|
return;
|
|
@@ -106,63 +66,38 @@ export function flushOps() {
|
|
|
106
66
|
}
|
|
107
67
|
// Commits this window, for readCommitProfile below.
|
|
108
68
|
let commits = 0;
|
|
109
|
-
// A surface to ask for this window's node counts
|
|
110
|
-
//
|
|
111
|
-
// `SymbioteTree.cpp`, shared by every surface and drained on read, so asking a second surface in the
|
|
69
|
+
// A surface to ask for this window's node counts, exactly one: walkCost_ is file-scope in
|
|
70
|
+
// SymbioteTree.cpp, shared by every surface and drained on read, so asking a second surface in the
|
|
112
71
|
// same window reads zeroes and a sum would be wrong rather than merely redundant.
|
|
113
72
|
let lastCommittedTag;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
* names ONE root. A framework can mutate a tree that belongs to a different surface than the one
|
|
123
|
-
* whose renderer it is holding — a portal, a tunnel, any cross-surface move — and every adapter
|
|
124
|
-
* then asks its OWN surface to commit. The ops reach the host either way, so the other surface is
|
|
125
|
-
* left correctly updated in the tree and never handed to `completeRoot`: a stale Fabric root that
|
|
126
|
-
* nothing will refresh until something unrelated dirties it. Naming every root here is what makes a
|
|
127
|
-
* commit mean "flush what changed" rather than "flush the surface I happen to be bound to".
|
|
128
|
-
*
|
|
129
|
-
* A single-surface app — every example, and the overwhelming case — passes an empty list and the
|
|
130
|
-
* behaviour is byte-identical to naming only itself.
|
|
131
|
-
*/
|
|
73
|
+
// Record a surface's commit and drain the buffer into the host. A surface is an anchor: its
|
|
74
|
+
// children belong to the root child set the same way an anchor's belong to its parent's list,
|
|
75
|
+
// which is why OP_COMMIT names one node and the host needs no rootTag -> map.
|
|
76
|
+
// `others` is every other live surface, needed because the buffer is global while a commit names
|
|
77
|
+
// one root — a portal or cross-surface move can mutate a different surface than the one
|
|
78
|
+
// committing, and naming every root here is what flushes what actually changed.
|
|
79
|
+
// A single-surface app (the overwhelming case) passes an empty list, byte-identical to naming
|
|
80
|
+
// only itself.
|
|
132
81
|
export function commitSurfaceOps(rootTag, surface, others = []) {
|
|
133
82
|
commits += 1;
|
|
134
|
-
// No host:
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
// throw when it comes names the commit rather than the discard.
|
|
138
|
-
//
|
|
139
|
-
// The commit op is not recorded either, for the same reason: it would sit at the head of the next
|
|
140
|
-
// batch, ahead of the creates it depends on.
|
|
83
|
+
// No host: ops stay pending, not drained — a surface created before a host installs would have
|
|
84
|
+
// its own createElement thrown away, and the next commit that does reach a host would name a
|
|
85
|
+
// node that host never saw. The commit op itself is skipped too, for the same reason.
|
|
141
86
|
if (host === undefined)
|
|
142
87
|
return;
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
// for a commit that publishes nothing.
|
|
150
|
-
//
|
|
151
|
-
// Who pays it: any frame where a framework re-ran an effect and produced no change, which for a
|
|
152
|
-
// reactive adapter is most frames.
|
|
153
|
-
//
|
|
154
|
-
// The post-commit hooks are NOT affected. `notifyCommitted`, `runPostCommitHooks`,
|
|
155
|
-
// `runDeferredAttaches` and the `afterCommit` drain all run in `surface.ts` AFTER this call and
|
|
156
|
-
// are deliberately not gated on the commit having made native calls — a fold that strips a prop
|
|
157
|
-
// makes its own commit byte-identical, and the hook reacting to that flip must still fire.
|
|
88
|
+
// Nothing to publish — return before the host does anything. The host already declines
|
|
89
|
+
// completeRoot on an identical child set, but only after rebuilding it: every child is
|
|
90
|
+
// revisited to discover none moved, linear cost for a commit that publishes nothing.
|
|
91
|
+
// Post-commit hooks are NOT affected: notifyCommitted/runPostCommitHooks/runDeferredAttaches/
|
|
92
|
+
// afterCommit all run after this call in surface.ts, deliberately ungated on native calls — a
|
|
93
|
+
// fold that strips a prop makes its commit byte-identical, and the hook must still fire.
|
|
158
94
|
if (!hasChangedSinceCommit())
|
|
159
95
|
return;
|
|
160
96
|
for (const [otherTag, otherSurface] of others) {
|
|
161
97
|
recordCommit(otherTag, otherSurface);
|
|
162
98
|
}
|
|
163
|
-
//
|
|
164
|
-
// it. Its ops still drain,
|
|
165
|
-
// would hand Fabric the dead surface's emptied tree over the live one's.
|
|
99
|
+
// undefined means this surface no longer owns its root — a re-mount on the same rootTag took
|
|
100
|
+
// it. Its ops still drain, since a teardown is what carries the removals.
|
|
166
101
|
if (rootTag !== undefined) {
|
|
167
102
|
recordCommit(rootTag, surface);
|
|
168
103
|
lastCommittedTag = rootTag;
|
|
@@ -170,20 +105,15 @@ export function commitSurfaceOps(rootTag, surface, others = []) {
|
|
|
170
105
|
host.applyOps(takeBatch());
|
|
171
106
|
noteCommitDrained();
|
|
172
107
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
* therefore empties what a later `readSurfaceTelemetry` call would have reported.
|
|
177
|
-
*/
|
|
108
|
+
// Reading this now drains the surface telemetry too — nodesCreated is folded in from
|
|
109
|
+
// readSurfaceTelemetry, which zeroes on read in C++, so a sampler polling this on an interval
|
|
110
|
+
// empties what a later readSurfaceTelemetry call would have reported.
|
|
178
111
|
export function readCommitProfile() {
|
|
179
|
-
//
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
//
|
|
183
|
-
// `
|
|
184
|
-
// surface that has not committed since the last read aborts the process in a debug build and
|
|
185
|
-
// reads an undefined time point in a release one. The window's own `commits` is the only thing
|
|
186
|
-
// that answers "is there anything to ask about" without asking.
|
|
112
|
+
// One read, not two: readSurfaceTelemetry zeroes the C++ accumulator, so asking twice hands the
|
|
113
|
+
// second caller zeroes and the field would read as "the buffer never crossed".
|
|
114
|
+
// Gated on a commit having landed this window, not merely a tag being known: Fabric's telemetry
|
|
115
|
+
// asserts a commit has started, so asking an uncommitted surface aborts in debug and reads
|
|
116
|
+
// garbage in release. `commits` answers "anything to ask about" without asking.
|
|
187
117
|
const telemetry = commits === 0 || lastCommittedTag === undefined
|
|
188
118
|
? undefined
|
|
189
119
|
: readSurfaceTelemetry(lastCommittedTag);
|
|
@@ -198,44 +128,24 @@ export function readCommitProfile() {
|
|
|
198
128
|
commits = 0;
|
|
199
129
|
return snapshot;
|
|
200
130
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
* accumulates inside our own commit, so it can only ever describe a tree we built, and the standing
|
|
207
|
-
* open question is whether a tree-wide text re-measure is something we cause or something a Fabric
|
|
208
|
-
* commit costs whoever drives it. Point this at a surface React Native's OWN renderer committed and
|
|
209
|
-
* the two numbers are directly comparable — same device, same RN, same tree.
|
|
210
|
-
*
|
|
211
|
-
* `undefined` rather than zeroes on a runtime without the binding, deliberately: zeroes would read
|
|
212
|
-
* as "the other renderer measures no text", which is precisely the claim under test.
|
|
213
|
-
*/
|
|
131
|
+
// RN's own commit telemetry for a surface this host need not have driven, or undefined when the
|
|
132
|
+
// runtime cannot answer. Exists for one comparison: point this at a surface RN's own renderer
|
|
133
|
+
// committed and the two numbers are directly comparable — same device, same RN, same tree.
|
|
134
|
+
// undefined rather than zeroes on a runtime without the binding, deliberately: zeroes would read
|
|
135
|
+
// as "the other renderer measures no text", which is precisely the claim under test.
|
|
214
136
|
export function readSurfaceTelemetry(surfaceId) {
|
|
215
137
|
return nativeEngine()?.readSurfaceTelemetry?.(surfaceId);
|
|
216
138
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
*
|
|
221
|
-
* This is for the LATER toggle — the runtime escape hatch `debug.ts` documents for hosts where the
|
|
222
|
-
* env is not reachable. Without it a `globalThis.__SYMBIOTE_DEBUG__ = true` typed into a running app
|
|
223
|
-
* would flip the JS half and silently leave the engine's own half dark, which is the surprise worth
|
|
224
|
-
* the six lines.
|
|
225
|
-
*/
|
|
139
|
+
// Arm the C++ half's diagnostics (SymbioteDebug.h), already done by installBindings from DEBUG=1 /
|
|
140
|
+
// globalThis.__SYMBIOTE_DEBUG__ at install. This is for the LATER toggle: without it, flipping the
|
|
141
|
+
// runtime escape hatch would flip the JS half and silently leave the engine's half dark.
|
|
226
142
|
export function setNativeDebug(enabled) {
|
|
227
143
|
nativeEngine()?.setDebugEnabled?.(enabled);
|
|
228
144
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
* can assert on is one that rots. This is what lets a test say "the engine warned about that" —
|
|
234
|
-
* see `core/engine/cpp/tests/js/native-debug-log.itest.ts`.
|
|
235
|
-
*
|
|
236
|
-
* An empty array on a runtime without the binding, not `undefined`: the question "what was logged"
|
|
237
|
-
* has an honest empty answer, unlike the telemetry read above, where a zero would be a false claim.
|
|
238
|
-
*/
|
|
145
|
+
// Drain what the C++ half has logged since the last call. Retained rather than only written to
|
|
146
|
+
// stderr so a test can assert "the engine warned about that" (native-debug-log.itest.ts).
|
|
147
|
+
// An empty array on a runtime without the binding, not undefined: "what was logged" has an honest
|
|
148
|
+
// empty answer, unlike the telemetry read above, where a zero would be a false claim.
|
|
239
149
|
export function takeNativeDebugLog() {
|
|
240
150
|
return nativeEngine()?.takeDebugLog?.() ?? [];
|
|
241
151
|
}
|
package/build/view-config.js
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
// Per-native-component event declarations: symbiote's slimmed ViewConfigRegistry.
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// Flat-bag adapters (React / Vue / Solid) hand props and handlers mixed together
|
|
8
|
-
// and must split them. They consult this registry to tell an event handler
|
|
9
|
-
// (`onChange` -> `change`, a declared event) from a native prop that merely looks
|
|
10
|
-
// like one (`onTintColor` -> `tintColor`, NOT a declared event -> stays a prop and
|
|
11
|
-
// reaches Fabric). Structural adapters (Svelte `addEventListener`, Angular
|
|
12
|
-
// `Renderer2.listen`) deliver events pre-separated and call `setEventListener`
|
|
13
|
-
// directly, bypassing this entirely.
|
|
1
|
+
// Per-native-component event declarations: symbiote's slimmed ViewConfigRegistry. Mirrors RN's
|
|
2
|
+
// ViewConfig — each Fabric component declares which event names it can emit — shared by every
|
|
3
|
+
// adapter, so it lives here rather than in any one framework adapter.
|
|
4
|
+
// Flat-bag adapters (React/Vue/Solid) hand props and handlers mixed together and must split them:
|
|
5
|
+
// they consult this registry to tell an event handler (onChange -> change) from a native prop that
|
|
6
|
+
// merely looks like one. Structural adapters (Svelte, Angular) deliver events pre-separated.
|
|
14
7
|
import { isRegisteredEvent } from './registry.js';
|
|
15
8
|
// Accessibility events from RN's base ViewConfig: every view can emit them.
|
|
16
9
|
// accessibilityAction fires on iOS + Android; the other three are iOS-only and inert
|
|
@@ -21,20 +14,15 @@ const A11Y_EVENTS = [
|
|
|
21
14
|
'magicTap',
|
|
22
15
|
'accessibilityEscape',
|
|
23
16
|
];
|
|
24
|
-
// Events every view can emit, from RN's base ViewConfig.
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
// (ViewPropTypes.js FocusEventProps), so any view can emit them; the accessibility
|
|
28
|
-
// events are base too, so they reach every component.
|
|
17
|
+
// Events every view can emit, from RN's base ViewConfig. press/pressIn/pressOut/longPress are
|
|
18
|
+
// synthesized from the touch stream (events.ts); layout is universal; focus/blur are RN's bubbling
|
|
19
|
+
// focus events on the base View, so any view can emit them; the accessibility events are base too.
|
|
29
20
|
const BASE_EVENTS = [
|
|
30
21
|
'press',
|
|
31
22
|
'pressIn',
|
|
32
23
|
'pressOut',
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
// prop to `setEventListener` (and thus to the behavior's stash) only for a registered event, so
|
|
36
|
-
// `onPressMove` landed in `node.props` where nothing reads it. The wrapper that used to pass the
|
|
37
|
-
// same callback to the machine directly hid this.
|
|
24
|
+
// Must be registered like its four siblings: routeProp hands an on* prop to setEventListener
|
|
25
|
+
// only for a registered event, so an unregistered onPressMove lands in node.props unread.
|
|
38
26
|
'pressMove',
|
|
39
27
|
'longPress',
|
|
40
28
|
'layout',
|
|
@@ -42,15 +30,9 @@ const BASE_EVENTS = [
|
|
|
42
30
|
'blur',
|
|
43
31
|
...A11Y_EVENTS,
|
|
44
32
|
];
|
|
45
|
-
// An event set is platform-invariant: a text input emits `change` on iOS and Android
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
// events are declared ONCE and keyed under BOTH platform names below. The table is
|
|
49
|
-
// consulted by the resolved native name (SymbioteNode.component), and only one
|
|
50
|
-
// platform's names ever exist at runtime, so the other platform's keys are inert (no
|
|
51
|
-
// Platform.OS branch), the names simply coexist. Missing the Android keys is what made
|
|
52
|
-
// onValueChange (and Switch/Modal/RefreshControl events) silently dead on Android: the
|
|
53
|
-
// onX prop failed isEventFor, fell to setProp, and no listener was ever registered.
|
|
33
|
+
// An event set is platform-invariant: a text input emits `change` on iOS and Android alike, only
|
|
34
|
+
// the native component name differs. Each primitive's events are declared once and keyed under
|
|
35
|
+
// both platform names — consulted by the resolved name, so only one side is ever live at runtime.
|
|
54
36
|
const TEXT_INPUT_EVENTS = [
|
|
55
37
|
'change',
|
|
56
38
|
'focus',
|
|
@@ -67,11 +49,9 @@ const MODAL_EVENTS = [
|
|
|
67
49
|
'requestClose',
|
|
68
50
|
'orientationChange',
|
|
69
51
|
];
|
|
70
|
-
// A scroll view's events are the same on both axes and both platforms; only the native
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
// Android horizontal name was missing, so a horizontal FlatList's onScroll never fired and
|
|
74
|
-
// its windowing stalled: same failure mode as the text-input keys.
|
|
52
|
+
// A scroll view's events are the same on both axes and both platforms; only the native name
|
|
53
|
+
// differs (Android RCTScrollView vertical vs AndroidHorizontalScrollView horizontal). Declared
|
|
54
|
+
// once, keyed under each name below — same shape as the text-input keys above.
|
|
75
55
|
const SCROLL_EVENTS = [
|
|
76
56
|
'scroll',
|
|
77
57
|
'scrollBeginDrag',
|