@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.
Files changed (110) hide show
  1. package/android/CMakeLists.txt +31 -1
  2. package/android/build.gradle +4 -1
  3. package/build/accessibility-info/index.android.js +21 -17
  4. package/build/accessibility-info/index.ios.js +2 -0
  5. package/build/accessibility-info/shared.d.ts +1 -1
  6. package/build/accessibility-props.d.ts +0 -11
  7. package/build/accessibility-props.js +30 -68
  8. package/build/alert/shared.d.ts +1 -1
  9. package/build/alert/shared.js +3 -7
  10. package/build/animated/graph.js +1 -1
  11. package/build/animated/leaf-lifecycle.js +2 -2
  12. package/build/app-state/index.d.ts +1 -1
  13. package/build/app-state/index.js +35 -27
  14. package/build/asset-source-resolver.d.ts +2 -0
  15. package/build/asset-source-resolver.js +13 -0
  16. package/build/back-handler/index.d.ts +7 -6
  17. package/build/back-handler/index.js +19 -16
  18. package/build/debug.js +8 -22
  19. package/build/dispatch.js +3 -9
  20. package/build/events/index.js +12 -3
  21. package/build/fabric-props.js +75 -180
  22. package/build/fabric.d.ts +2 -8
  23. package/build/fabric.js +27 -33
  24. package/build/host-access.d.ts +1 -128
  25. package/build/host-access.js +96 -205
  26. package/build/host-behavior.d.ts +1 -100
  27. package/build/host-behavior.js +125 -311
  28. package/build/image-loader.d.ts +4 -2
  29. package/build/image-loader.js +24 -48
  30. package/build/image-source-resolver.js +3 -7
  31. package/build/image-source-write.d.ts +1 -12
  32. package/build/image-source-write.js +28 -36
  33. package/build/imperative.d.ts +0 -28
  34. package/build/imperative.js +42 -92
  35. package/build/index.d.ts +3 -2
  36. package/build/index.js +30 -43
  37. package/build/invariant.d.ts +1 -0
  38. package/build/invariant.js +10 -0
  39. package/build/keyboard/index.js +11 -32
  40. package/build/linking/index.android.js +5 -3
  41. package/build/linking/shared.d.ts +1 -1
  42. package/build/linking/shared.js +16 -19
  43. package/build/mutation-buffer.d.ts +0 -177
  44. package/build/mutation-buffer.js +137 -308
  45. package/build/native-engine.d.ts +0 -102
  46. package/build/native-engine.js +38 -98
  47. package/build/native-events.d.ts +5 -0
  48. package/build/native-events.js +30 -18
  49. package/build/native-tree-host.d.ts +0 -21
  50. package/build/native-tree-host.js +14 -31
  51. package/build/node.d.ts +0 -212
  52. package/build/node.js +354 -774
  53. package/build/permissions-android/index.android.d.ts +59 -0
  54. package/build/permissions-android/index.android.js +47 -0
  55. package/build/permissions-android/index.d.ts +1 -115
  56. package/build/permissions-android/index.ios.d.ts +59 -0
  57. package/build/permissions-android/index.ios.js +31 -0
  58. package/build/permissions-android/index.js +3 -184
  59. package/build/permissions-android/shared.d.ts +63 -0
  60. package/build/permissions-android/shared.js +66 -0
  61. package/build/platform/index.android.js +3 -5
  62. package/build/platform/index.ios.js +3 -3
  63. package/build/platform/shared.d.ts +4 -0
  64. package/build/platform/shared.js +9 -0
  65. package/build/platform-color/index.android.d.ts +4 -0
  66. package/build/platform-color/index.android.js +7 -0
  67. package/build/platform-color/index.d.ts +2 -20
  68. package/build/platform-color/index.js +1 -45
  69. package/build/platform-color/shared.d.ts +21 -0
  70. package/build/platform-color/shared.js +41 -0
  71. package/build/post-commit.js +3 -8
  72. package/build/process-aspect-ratio.js +3 -7
  73. package/build/process-background-longhands.js +10 -19
  74. package/build/process-filter.js +11 -19
  75. package/build/process-font-variant.js +3 -7
  76. package/build/registry.d.ts +0 -33
  77. package/build/registry.js +22 -57
  78. package/build/report-error.js +4 -18
  79. package/build/settings/index.android.d.ts +6 -0
  80. package/build/settings/index.android.js +21 -0
  81. package/build/settings/index.d.ts +1 -8
  82. package/build/settings/index.ios.d.ts +8 -0
  83. package/build/settings/index.ios.js +122 -0
  84. package/build/settings/index.js +3 -122
  85. package/build/share/index.android.js +9 -32
  86. package/build/share/index.ios.js +14 -15
  87. package/build/share/shared.d.ts +4 -2
  88. package/build/share/shared.js +7 -10
  89. package/build/status-bar/index.android.js +1 -1
  90. package/build/status-bar/index.ios.js +4 -3
  91. package/build/structured-style.d.ts +0 -9
  92. package/build/structured-style.js +16 -31
  93. package/build/styles.js +3 -6
  94. package/build/surface.d.ts +0 -26
  95. package/build/surface.js +29 -76
  96. package/build/text-input-state.js +4 -8
  97. package/build/toast-android/index.android.d.ts +10 -0
  98. package/build/toast-android/index.android.js +108 -0
  99. package/build/toast-android/index.d.ts +1 -10
  100. package/build/toast-android/index.ios.d.ts +10 -0
  101. package/build/toast-android/index.ios.js +19 -0
  102. package/build/toast-android/index.js +3 -108
  103. package/build/touch-history.js +5 -11
  104. package/build/tree-host.d.ts +0 -270
  105. package/build/tree-host.js +63 -153
  106. package/build/view-config.js +17 -37
  107. package/cpp/SymbioteFabricProps.cpp +204 -120
  108. package/cpp/SymbioteFabricProps.h +5 -0
  109. package/cpp/SymbioteTree.cpp +20 -6
  110. package/package.json +2 -2
@@ -1,13 +1,6 @@
1
1
  import type { IMeasureInWindowOnSuccess, IMeasureLayoutOnSuccess, IMeasureOnSuccess, IRootTag } from './fabric';
2
2
  import { type IMutationBatch, type IMutationHandle } from './mutation-buffer';
3
- /** What Fabric currently holds for one node — the three fields every imperative call is aimed at. */
4
3
  export type ICommittedRecord = {
5
- /**
6
- * OPAQUE, and typed that way because it is: each host puts its own thing here — the native host a
7
- * `ShadowNode`, a headless one whatever it committed — and the field's only contract is identity.
8
- * It used to say `IFabricNode`, which promised a Fabric node from every host and was true of one.
9
- * `IFabricNode` is a brand with no members, so nothing a caller could do with it is lost.
10
- */
11
4
  handle: object;
12
5
  tag: number;
13
6
  rootTag: IRootTag;
@@ -16,88 +9,24 @@ export interface ITreeCensus {
16
9
  nodes: number;
17
10
  anchors: number;
18
11
  emptyRawTexts: number;
19
- /** Nodes that actually become a Fabric view: `nodes` minus everything the commit skips. */
20
12
  renderable: number;
21
- /** children.length of every parent holding at least one skipped child, widest first. */
22
13
  flattenWidths: number[];
23
14
  }
24
- /**
25
- * The census of a tree nobody counted — what a host with no walk of its own answers, and what
26
- * `censusRetainedTree` answers when no host is installed at all.
27
- *
28
- * Not exported from the package barrel: it is a HOST-author constant, and an app reading a census
29
- * asserts against a mounted tree, where a zero from here cannot be mistaken for a zero from a real
30
- * empty tree.
31
- */
32
15
  export declare const EMPTY_CENSUS: ITreeCensus;
33
- /**
34
- * Everything JS asks of the tree it no longer owns.
35
- *
36
- * No read here is on a commit path — they run at GESTURE or lifecycle rate (a host behavior seeing
37
- * the props it reacts to, an app measuring a ref, a framework seam navigating what it just built).
38
- * This comment used to conclude from that that the crossing cost was irrelevant, at "~10 reads per
39
- * touch". Counted, it was 18 per EVENT and 19 per drag FRAME — 60 times a second for as long as a
40
- * finger is down — because a gesture is not one touch and a walk that asks per level pays per
41
- * level. Both are 1 now.
42
- *
43
- * `parentsOf`, `subtreesOf` and `ancestorsOf` are what that cost: each answers exactly what its
44
- * singular twin answers, in ONE crossing, for the three walks whose size is the TREE's rather than
45
- * a node's — teardown down, dispatch and responder negotiation up.
46
- */
47
16
  export type ITreeHost = {
48
17
  applyOps: (batch: IMutationBatch) => void;
49
18
  propOf: (handle: object, key: string) => unknown;
50
19
  propsOf: (handle: object) => Readonly<Record<string, unknown>>;
51
20
  markPropsDirty: (handle: object) => void;
52
21
  committedRecordOf: (handle: object) => ICommittedRecord | undefined;
53
- /**
54
- * A TEST read: the PAYLOAD the last commit handed Fabric for this node, `undefined` before one.
55
- *
56
- * It exists because the alternative reads are both blind. `Props::getDebugProps()` is a
57
- * hand-written selection per component — `RCTSinglelineTextInputView` reports `testID` and nothing
58
- * else — and RN's complete `Props::rawProps` needs `RN_SERIALIZABLE_STATE`, which pulls fbjni into
59
- * `State` and does not compile on a host build. So the rules in `SymbioteFabricProps.cpp` were
60
- * verifiable only through their TypeScript twins, which is the drift this read closes.
61
- *
62
- * Not on any commit path, and it adds no bookkeeping: the bag is already retained per node as the
63
- * next commit's diff baseline.
64
- *
65
- * It answers what we SENT, not what Fabric parsed — a key no ViewConfig declares is still in here.
66
- */
67
22
  committedPayloadOf: (handle: object) => Readonly<Record<string, unknown>> | undefined;
68
23
  parentOf: (handle: object) => object | undefined;
69
24
  childrenOf: (handle: object) => readonly object[];
70
25
  firstChildOf: (handle: object) => object | undefined;
71
26
  nextSiblingOf: (handle: object) => object | undefined;
72
27
  parentsOf: (handles: readonly object[]) => readonly (object | undefined)[];
73
- /** Each root and every descendant, PRE-ORDER, concatenated in root order. */
74
28
  subtreesOf: (roots: readonly object[]) => readonly object[];
75
- /**
76
- * The same walk, narrowed to the nodes a TEARDOWN has work for — each root, every node carrying
77
- * an intrinsic tag, and every node between the two.
78
- *
79
- * It exists because the sweep's whole cost is how WIDE this walk is: a thousand-row clear crossed
80
- * ten thousand handles to release a thousand machines, and eight in ten of those nodes were plain
81
- * views the sweep marked and did nothing else with. An ancestor of a tagged node has to come back
82
- * too, or a framework that returns an interior node on its own would never re-arm what hangs
83
- * beneath it (`host-behavior.test.ts` guards exactly that shape).
84
- *
85
- * Not a replacement for `subtreesOf`: an animated binding is per node and carries no tag, so
86
- * `host-access.ts` asks for the full walk whenever one exists.
87
- */
88
29
  teardownSubtreesOf: (roots: readonly object[]) => readonly object[];
89
- /**
90
- * The node itself and every ancestor above it, DEEPEST FIRST.
91
- *
92
- * The upward twin of `subtreesOf`, and it exists for the same reason: a walk that asks per LEVEL
93
- * pays a crossing per level. Event dispatch needs this chain for every event — capture reads it
94
- * reversed, bubble reads it forward — and the responder negotiation needs it again on every frame
95
- * of every drag. Measured before it existed: 18 crossings per event on a depth-8 chain, then 9
96
- * once the two phases shared one walk, against the 1 an answer from here costs.
97
- *
98
- * A SURFACE is included, exactly as `parentOf`'s answer is — stopping at one is
99
- * `host-access.ts`'s job, and it does it by reading the answer's `component`.
100
- */
101
30
  ancestorsOf: (handle: object) => readonly object[];
102
31
  census: (roots: readonly object[]) => ITreeCensus;
103
32
  dispatchCommand: (handle: object, commandName: string, args: readonly unknown[]) => void;
@@ -107,137 +36,32 @@ export type ITreeHost = {
107
36
  measureLayout: (handle: object, relativeTo: object, onFail: () => void, onSuccess: IMeasureLayoutOnSuccess) => void;
108
37
  setIsJSResponder: (handle: object, isResponder: boolean, blockNativeResponder: boolean) => void;
109
38
  };
110
- /**
111
- * Install the tree host. `installFabric()` (test-utils) calls this with the TypeScript applier; the
112
- * native module installs itself the same way once its bindings carry these reads.
113
- *
114
- * Passing `undefined` uninstalls, so a fixture can prove a path degrades rather than throws.
115
- */
116
39
  export declare function setTreeHost(next: ITreeHost | undefined): void;
117
- /** The installed host, or `undefined` on a runtime that has none. */
118
40
  export declare function treeHost(): ITreeHost | undefined;
119
41
  export declare function registerBeforeFlush(listener: () => void): () => void;
120
- /**
121
- * Collect what the listeners are holding, WITHOUT draining.
122
- *
123
- * Separate from `flushOps` because a read may legitimately decide it needs no drain — `parentOf`
124
- * skips one for a node whose placement is not pending — and skipping the drain must not also skip
125
- * asking. A held write is still a write, and a reader that cannot see it is reading a stale tree.
126
- */
127
42
  export declare function settleBeforeFlush(): void;
128
43
  export declare function flushOps(): void;
129
- /**
130
- * Record a surface's commit and drain the buffer into the host.
131
- *
132
- * A SURFACE IS AN ANCHOR: an anchor is a node whose children belong to its parent's list, and a
133
- * surface is a node whose children belong to the root child set. Same shape, which is why `OP_COMMIT`
134
- * names one node and the host needs no `rootTag -> map`.
135
- *
136
- * `others` is every OTHER live surface, and it exists because the buffer is GLOBAL while a commit
137
- * names ONE root. A framework can mutate a tree that belongs to a different surface than the one
138
- * whose renderer it is holding — a portal, a tunnel, any cross-surface move — and every adapter
139
- * then asks its OWN surface to commit. The ops reach the host either way, so the other surface is
140
- * left correctly updated in the tree and never handed to `completeRoot`: a stale Fabric root that
141
- * nothing will refresh until something unrelated dirties it. Naming every root here is what makes a
142
- * commit mean "flush what changed" rather than "flush the surface I happen to be bound to".
143
- *
144
- * A single-surface app — every example, and the overwhelming case — passes an empty list and the
145
- * behaviour is byte-identical to naming only itself.
146
- */
147
44
  export declare function commitSurfaceOps(rootTag: IRootTag | undefined, surface: IMutationHandle, others?: readonly (readonly [IRootTag, IMutationHandle])[]): void;
148
45
  export interface ICommitProfile {
149
46
  commits: number;
150
47
  propWrites: number;
151
- /**
152
- * Fresh Fabric families minted in this window — the SAME quantity a stock React Native app counts
153
- * by wrapping `global.nativeFabricUIManager.createNode`, and the only like-for-like census left
154
- * between the two stacks: our creates are issued from C++ (`SymbioteTree.cpp`,
155
- * `uiManager.createNode`) and never touch that global, so a JS wrapper over it reads zero here by
156
- * construction. Two arms whose node counts differ are not one workload, whatever their
157
- * milliseconds say, so this belongs next to the writes rather than behind a surface id.
158
- */
159
48
  nodesCreated: number;
160
- /**
161
- * How many times `applyOps` was ENTERED for this window — the number of JSI crossings the buffer
162
- * actually cost, as against the one the architecture promises.
163
- *
164
- * A whole create should read 2. It reads more when something READS the tree while the tree is
165
- * being built, because a read is a batch boundary: the buffer has to drain before the answer can
166
- * be given, so a framework navigating what it is inserting enters `applyOps` once per mutation.
167
- * `small-batch-crossing-cost.itest.ts` prices an empty prologue at 1.5-4.4 us, so ten thousand
168
- * boundaries is tens of milliseconds that no node count and no write count can see — which is
169
- * exactly the shape of a cost that shows up on a device and not in a fixture.
170
- */
171
49
  applyCalls: number;
172
- /**
173
- * `applyOps` end to end, and the part of it that reads the buffer out of JS.
174
- *
175
- * THE ONE QUESTION A DEVICE HAS TO ANSWER and a fixture cannot. Our crossing is a single call
176
- * carrying a 12 000-entry array that C++ walks element by element through JSI; stock's is ten
177
- * thousand calls carrying scalars. On the harness's JavaScriptCore that walk is ~4 ms of a ~48 ms
178
- * `applyOps`. Hermes is a different JSI implementation with different array-read costs and nothing
179
- * headless can price it, so the number has to be read on a phone — near 4 ms and the buffer is
180
- * innocent, tens of milliseconds and it is most of the gap the device reports.
181
- */
182
50
  applyMs: number;
183
51
  decodeMs: number;
184
52
  }
185
- /**
186
- * NOTE: reading this now DRAINS the surface telemetry too — `nodesCreated` is folded in from
187
- * `readSurfaceTelemetry`, which zeroes on read in C++. A sampler polling this on an interval
188
- * therefore empties what a later `readSurfaceTelemetry` call would have reported.
189
- */
190
53
  export declare function readCommitProfile(): ICommitProfile;
191
54
  export type ISurfaceTelemetry = {
192
55
  layoutMs: number;
193
56
  textMs: number;
194
- /**
195
- * `ShadowTree::commit`'s own window — and **NOT** `materialize`'s.
196
- *
197
- * This field's doc used to claim it was the clone-on-write walk, and F-80/F-81/F-82 each read it
198
- * that way and concluded the native pipeline was too small to matter. `materialize` runs inside
199
- * `kOpCommit` BEFORE `completeSurface` is called, so it is outside both this window and layout's.
200
- * Pricing our own walk means timing `applyOps` from JS and subtracting these two.
201
- */
202
57
  commitMs: number;
203
58
  layoutNodes: number;
204
59
  textMeasures: number;
205
- /**
206
- * How many parents took the targeted-replace path since the last read, zeroed on read.
207
- *
208
- * OURS, not React Native's. It is a LIVENESS signal, not a performance one: every test in this
209
- * repository stays green when `canReplaceInPlace` is off, which is how it spent eighteen months
210
- * disabled. Assert it is non-zero wherever the fast path is the point of the test.
211
- */
212
60
  targetedReplaces: number;
213
- /**
214
- * `materialize`'s own walk, and the fields below break it down. OURS, zeroed on read.
215
- *
216
- * The doc above says the walk falls outside every window React Native times, which left it
217
- * priceable only by subtraction — and a subtraction gives a budget, not an address. Measured
218
- * 2026-09-17: ~200 ms of a 327 ms headless create sat here with nothing inside it named.
219
- *
220
- * `walkMs` is the single entry point in `kOpCommit`; `propsMs` / `rawPropsMs` / `createNodeMs` /
221
- * `appendChildMs` / `diffPropsMs` are per-node sums inside it and do NOT add up to it — what is
222
- * left over is the walk's own bookkeeping.
223
- */
224
61
  walkMs: number;
225
- /** `fabricProps` alone, on both the create and the clone path. The fold LOOKUP is billed apart. */
226
62
  propsMs: number;
227
- /**
228
- * Asking a node whether it carries a `payloadFold`: a JSI property read, and on a hit a
229
- * `jsi::Function` allocation. The fold's own CALL is inside `propsMs`, where `fabricProps` makes
230
- * it. Separated because the two answer different questions — how big the payload is, against how
231
- * much the seam to JS costs to reach.
232
- */
233
63
  foldLookupMs: number;
234
- /** How many nodes the lookup found one on. Zero makes `foldLookupMs` pure probe cost. */
235
64
  foldsFound: number;
236
- /**
237
- * Inside a fold that runs, split three ways because a fold's CONTRACT is bag in, bag out: both
238
- * conversions walk every key of the node whatever the fold actually reads. If the conversions
239
- * dominate, the fix is a narrower contract; if `foldCallMs` does, the fix is not having a fold.
240
- */
241
65
  foldToJsMs: number;
242
66
  foldCallMs: number;
243
67
  foldFromJsMs: number;
@@ -246,124 +70,30 @@ export type ISurfaceTelemetry = {
246
70
  createNodeMs: number;
247
71
  appendChildMs: number;
248
72
  diffPropsMs: number;
249
- /** Nodes that minted a fresh Fabric family, were cloned, or were returned untouched. */
250
73
  nodesCreated: number;
251
74
  nodesCloned: number;
252
75
  nodesReused: number;
253
- /**
254
- * `applyOps`' own decode, per created element, and its three biggest parts.
255
- *
256
- * A different question from the walk's. The walk asks what Fabric charges; this asks what it costs
257
- * US to turn one op into one node — and the buffer architecture only pays for itself if that is
258
- * well under the per-node JSI call it replaces. On `build-release` it was not, which is why these
259
- * exist. `publishMs` contains `nativeStateMs`; neither contains `instanceHandleMs`.
260
- */
261
76
  decodeMs: number;
262
77
  instanceHandleMs: number;
263
78
  publishMs: number;
264
79
  nativeStateMs: number;
265
80
  nodesDecoded: number;
266
- /**
267
- * `kOpSetProp` and, inside it, the JS value -> `folly::dynamic` conversion.
268
- *
269
- * `setPropMs` skips the two early exits (deleting an absent key, and a value equal to the one
270
- * standing), so it under-counts exactly the cheap paths; `propConvertMs` has no such hole.
271
- */
272
81
  setPropMs: number;
273
82
  propConvertMs: number;
274
83
  setProps: number;
275
- /**
276
- * The two `setProp` ops that changed nothing, counted apart because they are not the same waste.
277
- *
278
- * `deletesOfAbsent` leaves before the value conversion and costs a hash lookup. `writesOfUnchanged`
279
- * leaves AFTER it, so the adapter has already paid the JSI -> `folly::dynamic` crossing for a value
280
- * that changes nothing — that is the expensive one, and it is what the device benchmark's
281
- * `WRITES n/m` second figure reports.
282
- */
283
84
  deletesOfAbsent: number;
284
85
  writesOfUnchanged: number;
285
- /**
286
- * How well the buffer's value interning worked: entries in the batch's value table, and how many
287
- * of them an op actually reached and converted.
288
- *
289
- * `setProps / valueEntries` is the dedup achieved. A ratio near 1 means the values are unique —
290
- * which is a fact about what the caller HANDS the buffer, not about the interning: a style slot
291
- * rebuilt per node arrives as a fresh reference and cannot be folded with anything.
292
- */
293
86
  valueEntries: number;
294
87
  valueConversions: number;
295
- /**
296
- * `applyOps` end to end, plus the two parts of it that are neither a create nor a prop write.
297
- *
298
- * `applyMs` is the whole native call, so `applyMs` minus `decodeMs` / `setPropMs` /
299
- * `stringDecodeMs` / `structureMs` is what the op loop itself costs — the books close here.
300
- */
301
88
  applyMs: number;
302
- /**
303
- * How many nodes the C++ tree is holding right now — a LEVEL, not a total, and the one counter
304
- * here that is not drained on read.
305
- *
306
- * What it is for: JS ownership anchors the C++ side (a node lives while a parent holds it or while
307
- * JS names it through `NativeState`), so a heap reading proves the JS half was released and only
308
- * infers the other. This is the other half as a reading.
309
- */
310
89
  liveNodes: number;
311
90
  stringDecodeMs: number;
312
- /** Every append / insert / remove op together. */
313
91
  structureMs: number;
314
- /** Inside `structureMs`: promoting a node's weak handle reference to a strong one. */
315
92
  holdHandleMs: number;
316
- /**
317
- * `subtreesOf` — the batched host read the teardown sweep makes, and how many handles it returned.
318
- *
319
- * Not on a commit path and timed anyway: it hands JS a handle for every node in every removed
320
- * subtree, which on a 1 000-row clear is ten thousand. Whether that time is the crossing or the JS
321
- * loop above it decides whether the torn-down mark is worth moving into C++.
322
- */
323
93
  hostReadMs: number;
324
94
  hostReadHandles: number;
325
- /**
326
- * How many times `applyOps` was entered since the last read.
327
- *
328
- * The string and value tables are interned PER BATCH, so a driver that flushes in many small
329
- * batches cannot fold a repeated value across them. This is what distinguishes "this adapter sends
330
- * more values" from "this adapter sends the same values in more batches" — two very different
331
- * findings that look identical in `valueEntries` alone.
332
- */
333
95
  applyCalls: number;
334
96
  };
335
- /**
336
- * RN's own commit telemetry for a surface THIS HOST NEED NOT HAVE DRIVEN, or `undefined` when the
337
- * runtime cannot answer.
338
- *
339
- * It exists for one comparison and should not be reached for anything else: `readCommitProfile`
340
- * accumulates inside our own commit, so it can only ever describe a tree we built, and the standing
341
- * open question is whether a tree-wide text re-measure is something we cause or something a Fabric
342
- * commit costs whoever drives it. Point this at a surface React Native's OWN renderer committed and
343
- * the two numbers are directly comparable — same device, same RN, same tree.
344
- *
345
- * `undefined` rather than zeroes on a runtime without the binding, deliberately: zeroes would read
346
- * as "the other renderer measures no text", which is precisely the claim under test.
347
- */
348
97
  export declare function readSurfaceTelemetry(surfaceId: number): ISurfaceTelemetry | undefined;
349
- /**
350
- * Arm the C++ half's diagnostics (`SymbioteDebug.h`), which `installBindings` already did from
351
- * `DEBUG=1` / `globalThis.__SYMBIOTE_DEBUG__` at install.
352
- *
353
- * This is for the LATER toggle — the runtime escape hatch `debug.ts` documents for hosts where the
354
- * env is not reachable. Without it a `globalThis.__SYMBIOTE_DEBUG__ = true` typed into a running app
355
- * would flip the JS half and silently leave the engine's own half dark, which is the surprise worth
356
- * the six lines.
357
- */
358
98
  export declare function setNativeDebug(enabled: boolean): void;
359
- /**
360
- * Drain what the C++ half has logged since the last call.
361
- *
362
- * The reason those lines are retained at all rather than only written to stderr: a diagnostic nobody
363
- * can assert on is one that rots. This is what lets a test say "the engine warned about that" —
364
- * see `core/engine/cpp/tests/js/native-debug-log.itest.ts`.
365
- *
366
- * An empty array on a runtime without the binding, not `undefined`: the question "what was logged"
367
- * has an honest empty answer, unlike the telemetry read above, where a zero would be a false claim.
368
- */
369
99
  export declare function takeNativeDebugLog(): readonly string[];