@symbiote-native/engine 1.3.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/build/accessibility-props.d.ts +0 -11
- package/build/accessibility-props.js +30 -68
- package/build/animated/graph.js +1 -1
- package/build/animated/leaf-lifecycle.js +2 -2
- package/build/asset-source-resolver.d.ts +2 -0
- package/build/asset-source-resolver.js +13 -0
- package/build/back-handler/index.d.ts +1 -5
- package/build/back-handler/index.js +0 -6
- package/build/debug.js +8 -22
- package/build/dispatch.js +3 -9
- package/build/events/index.js +2 -2
- package/build/fabric-props.js +74 -179
- package/build/fabric.d.ts +0 -13
- package/build/fabric.js +18 -38
- package/build/host-access.d.ts +1 -128
- package/build/host-access.js +96 -205
- package/build/host-behavior.d.ts +0 -100
- package/build/host-behavior.js +125 -311
- package/build/image-loader.js +10 -23
- package/build/image-source-resolver.js +3 -7
- package/build/image-source-write.d.ts +0 -11
- package/build/image-source-write.js +14 -34
- package/build/imperative.d.ts +0 -28
- package/build/imperative.js +42 -92
- package/build/index.d.ts +1 -0
- package/build/index.js +24 -37
- 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.js +9 -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 +338 -774
- 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/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/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/package.json +2 -2
package/build/post-commit.js
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// which binds a props node to a view tag — can retry work that ran too early under an
|
|
5
|
-
// async-batched commit (Vue/Svelte schedule completeRoot on a microtask, so lifecycle
|
|
6
|
-
// code can reach a node before its tag exists; React commits synchronously and never
|
|
7
|
-
// queues). A neutral module so commit.ts and animated/props.ts share it without a
|
|
8
|
-
// dependency cycle.
|
|
1
|
+
// Run once after every commit that changed the tree, once fresh Fabric tags exist — lets a
|
|
2
|
+
// consumer needing a node's committed tag (the Animated native driver) retry work that ran too
|
|
3
|
+
// early under an async-batched commit. Shared by commit.ts and animated/props.ts, cycle-free.
|
|
9
4
|
const hooks = new Set();
|
|
10
5
|
export function registerPostCommit(hook) {
|
|
11
6
|
hooks.add(hook);
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
// JS-side port of RN's processAspectRatio (
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// ('16 / 9') is resolved to a number IN JS before native. A plain number (the common,
|
|
5
|
-
// already-working form) passes through untouched; this is a no-op for it.
|
|
6
|
-
//
|
|
7
|
-
// RN throws via invariant() in __DEV__ on a malformed value; we dlog and return undefined.
|
|
1
|
+
// JS-side port of RN's processAspectRatio: resolves a CSS ratio string ('16 / 9') to a number
|
|
2
|
+
// before native, same root cause as boxShadow/filter. A plain number passes through untouched.
|
|
3
|
+
// RN throws via invariant() on a malformed value; here we dlog and return undefined instead.
|
|
8
4
|
import { dlog } from './debug.js';
|
|
9
5
|
// RN processAspectRatio.js:15-63. number → number; ratio string → number; invalid → undefined.
|
|
10
6
|
export function processAspectRatio(aspectRatio) {
|
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
// RN's own processBackgroundSize / processBackgroundPosition / processBackgroundRepeat, imported
|
|
2
2
|
// rather than ported.
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// Why importing is free here even by this repo's strictest reading: all three upstream files
|
|
12
|
-
// contain ONLY `import type` lines. Their value-import closure is empty - no processColor, no
|
|
13
|
-
// Platform, no TurboModule floor, no renderer. There is nothing to weigh.
|
|
14
|
-
//
|
|
15
|
-
// Why no try/catch, unlike the other upstream wrappers: these three do not validate through
|
|
16
|
-
// `invariant`. They answer `[]` for anything they cannot parse, which upstream's own comment calls
|
|
17
|
-
// "do not apply any background" - so refusal is a RETURN here, not a throw.
|
|
3
|
+
// Needed because enableNativeCSSParsing() defaults to false, so RN's stock JS path parses the CSS
|
|
4
|
+
// string into the per-axis structure Fabric's C++ expects. Without it a string for any of these
|
|
5
|
+
// three reached native unparsed: dropped on iOS, cast to the wrong ReadableMap type on Android.
|
|
6
|
+
// Importing is free here: all three upstream files contain only `import type` lines, so their
|
|
7
|
+
// value-import closure is empty — no processColor, no Platform, no TurboModule floor, no renderer.
|
|
8
|
+
// No try/catch, unlike the other upstream wrappers: these three don't validate through invariant,
|
|
9
|
+
// they answer `[]` for anything unparseable — so refusal is a return here, not a throw.
|
|
18
10
|
import { dlog } from './debug.js';
|
|
19
11
|
// @ts-expect-error - untyped Flow source. Metro compiles it; vitest.config.ts strips the types.
|
|
20
12
|
import processBackgroundSizeUpstream from 'react-native/Libraries/StyleSheet/processBackgroundSize';
|
|
@@ -22,10 +14,9 @@ import processBackgroundSizeUpstream from 'react-native/Libraries/StyleSheet/pro
|
|
|
22
14
|
import processBackgroundPositionUpstream from 'react-native/Libraries/StyleSheet/processBackgroundPosition';
|
|
23
15
|
// @ts-expect-error - untyped Flow source. Metro compiles it; vitest.config.ts strips the types.
|
|
24
16
|
import processBackgroundRepeatUpstream from 'react-native/Libraries/StyleSheet/processBackgroundRepeat';
|
|
25
|
-
// An empty result
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
// leaving the declaration unset.
|
|
17
|
+
// An empty result means upstream parsed nothing usable. The payload builder's rule is that a
|
|
18
|
+
// refused processor leaves the key absent — `[]` is a real value, committing it would ask native
|
|
19
|
+
// to apply "no background size" rather than leave the declaration unset.
|
|
29
20
|
function orAbsent(parsed, key, value) {
|
|
30
21
|
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
31
22
|
dlog(`${key}: RN parsed nothing usable from ${JSON.stringify(value)}`);
|
package/build/process-filter.js
CHANGED
|
@@ -1,22 +1,14 @@
|
|
|
1
|
-
// RN's own processFilter, imported rather than ported
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// What changed by importing: a drop-shadow's colour now goes through RN's own `processColor`
|
|
13
|
-
// (upstream imports it directly at processFilter.js:16) instead of our injected
|
|
14
|
-
// `setColorProcessor` seam. On a real host those are the same function - bootstrapHost injects
|
|
15
|
-
// exactly `processColor` - so the seam simply no longer governs the colour inside a filter.
|
|
16
|
-
//
|
|
17
|
-
// Platform caveat worth keeping in view when demoing this: on iOS RN paints only `brightness` and
|
|
18
|
-
// `opacity` unless enableSwiftUIBasedFilters is on, so grayscale/blur/saturate/contrast/hueRotate
|
|
19
|
-
// parse correctly here and still do nothing on screen.
|
|
1
|
+
// RN's own processFilter, imported rather than ported: enableNativeCSSParsing() defaults to
|
|
2
|
+
// false, so the stock path parses the CSS string / structured array in JS and native never sees
|
|
3
|
+
// the raw string.
|
|
4
|
+
// try/catch because upstream throws once (a TypeError for a non-string/array input) and a commit
|
|
5
|
+
// path must never throw; fabric-props narrows first, but processFilter is on the public barrel
|
|
6
|
+
// too, so the guard here stays reachable, not ceremonial.
|
|
7
|
+
// A drop-shadow's color goes through RN's own processColor here, not our injected
|
|
8
|
+
// setColorProcessor seam — the same function on a real host, since bootstrapHost injects exactly
|
|
9
|
+
// processColor, so the seam simply doesn't govern a filter's color.
|
|
10
|
+
// iOS caveat: RN paints only brightness/opacity unless enableSwiftUIBasedFilters is on, so
|
|
11
|
+
// grayscale/blur/saturate/contrast/hueRotate parse fine here and still paint nothing on screen.
|
|
20
12
|
import { dlog } from './debug.js';
|
|
21
13
|
// @ts-expect-error - untyped Flow source. Metro compiles it; vitest.config.ts strips the types.
|
|
22
14
|
import processFilterUpstream from 'react-native/Libraries/StyleSheet/processFilter';
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
// JS-side port of RN's processFontVariant
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// string ('small-caps tabular-nums') is split into the array native expects IN JS. An
|
|
5
|
-
// array (the common, already-working form) passes through untouched; this is a no-op
|
|
6
|
-
// for it.
|
|
7
|
-
// RN processFontVariant.js:15-28. Array → array; space-separated string → array of variants.
|
|
1
|
+
// JS-side port of RN's processFontVariant: splits a space-separated CSS string
|
|
2
|
+
// ('small-caps tabular-nums') into the array native expects, same root cause as
|
|
3
|
+
// boxShadow/filter. An array (the common, already-working form) passes through as a no-op.
|
|
8
4
|
export function processFontVariant(fontVariant) {
|
|
9
5
|
if (Array.isArray(fontVariant)) {
|
|
10
6
|
return fontVariant;
|
package/build/registry.d.ts
CHANGED
|
@@ -29,39 +29,6 @@ export declare function registerComponent(name: string, registration?: IComponen
|
|
|
29
29
|
export declare function isRegisteredEvent(component: string, listener: string): boolean;
|
|
30
30
|
export declare function registeredNativeEvent(component: string, raw: string): INativeEventBinding | undefined;
|
|
31
31
|
export declare function registeredProcessor(component: string, key: string): IPropProcessor | undefined;
|
|
32
|
-
/**
|
|
33
|
-
* A component's ViewConfig processors, as a payload fold — or undefined when it has none.
|
|
34
|
-
*
|
|
35
|
-
* WHY A FOLD AND NOT A LOOKUP AT PAYLOAD-BUILD TIME. The payload is built in C++ on a device
|
|
36
|
-
* (`core/engine/cpp/SymbioteFabricProps.cpp`) and only in JS headless, and this registry cannot
|
|
37
|
-
* cross that boundary: it is populated lazily from an INJECTED `ReactNativeViewConfigRegistry`
|
|
38
|
-
* lookup, holding JS closures. `payloadFold` is the one seam that already runs in JS on both paths
|
|
39
|
-
* — the C++ probes it once per node and calls back — so putting the processors there is what makes
|
|
40
|
-
* a third-party view behave the same on a device as it does in a test.
|
|
41
|
-
*
|
|
42
|
-
* The alternative was a list of prop NAMES in C++, and that is what this replaces. It cost a day:
|
|
43
|
-
* `@symbiote-native/slider` declares `minimumTrackTintColor` / `maximumTrackTintColor` in its own
|
|
44
|
-
* ViewConfig, neither name was in the C++ list, both reached Fabric as CSS strings, and iOS answers
|
|
45
|
-
* a string colour with `clearColor()`. The slider dragged and reported values correctly with no
|
|
46
|
-
* track drawn at all. Any list of names is a list somebody has to extend for a component we have
|
|
47
|
-
* never seen — which would have meant editing C++ to add a native view, and that is exactly the
|
|
48
|
-
* coupling `<native_core_is_untouched>` exists to prevent.
|
|
49
|
-
*
|
|
50
|
-
* Resolved ONCE per component and cached, because `createElement` asks per node. A built-in
|
|
51
|
-
* short-circuits inside `resolve` before any of this.
|
|
52
|
-
*/
|
|
53
|
-
/**
|
|
54
|
-
* The prop names a component's OWN ViewConfig claims a processor for — i.e. exactly the keys
|
|
55
|
-
* `configPayloadFold` has already converted by the time the payload builder's own passes run.
|
|
56
|
-
*
|
|
57
|
-
* It exists so "a colour is converted exactly once" can be a stated rule rather than a lucky one.
|
|
58
|
-
* The overlap is real: `thumbTintColor` is claimed by @symbiote-native/slider's config AND by the
|
|
59
|
-
* engine's built-in COLOR_PROPS, and for a while nothing broke only because a processed colour came
|
|
60
|
-
* back as a NUMBER and the engine skipped numbers. That guard died when a numeric colour became
|
|
61
|
-
* processable in its own right — an author writing `color: 0xff0000ff` means rrggbbaa and owes the
|
|
62
|
-
* same rotation a string owes — and the second conversion then turned an already-correct int into
|
|
63
|
-
* a different colour.
|
|
64
|
-
*/
|
|
65
32
|
export declare function configProcessedKeys(component: string): ReadonlySet<string> | undefined;
|
|
66
33
|
export declare function configPayloadFold(component: string): IPayloadFold | undefined;
|
|
67
34
|
export {};
|
package/build/registry.js
CHANGED
|
@@ -1,33 +1,19 @@
|
|
|
1
|
-
// Runtime metadata for native Fabric views,
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// shared must stay react-native-free (the headless harness runs in plain Node), so
|
|
12
|
-
// the ViewConfig lookup is INJECTED, exactly like the color processor: the adapter
|
|
13
|
-
// wires `setNativeViewConfigSource(ReactNativeViewConfigRegistry.get)` on a real
|
|
14
|
-
// host, where that one source covers BOTH RN core and every library.
|
|
15
|
-
//
|
|
16
|
-
// The ONLY explicit list is OUR OWN built-in primitives (BUILTIN_COMPONENTS): a
|
|
17
|
-
// finite set we own, which keep their hand-tuned tables (view-config events, commit
|
|
18
|
-
// COLOR_PROPS) and are never read from the source, so they can't drift. Everything
|
|
19
|
-
// NOT in that set derives. The list never grows with the community; it grows only
|
|
20
|
-
// when we add a core primitive of our own.
|
|
1
|
+
// Runtime metadata for native Fabric views, derived by default. Any RN library ships its own
|
|
2
|
+
// ViewConfig via codegen, carrying everything the shared engine can't infer — which events a view
|
|
3
|
+
// emits, how to process its props. Nothing is transcribed; read from the config on first use.
|
|
4
|
+
// shared must stay react-native-free (the headless harness runs in plain Node), so the ViewConfig
|
|
5
|
+
// lookup is injected, exactly like the color processor: the adapter wires
|
|
6
|
+
// setNativeViewConfigSource(ReactNativeViewConfigRegistry.get) on a real host.
|
|
7
|
+
// The only explicit list is our own built-in primitives (BUILTIN_COMPONENTS): a finite set we own,
|
|
8
|
+
// which keep their hand-tuned tables and are never read from the source, so they can't drift. It
|
|
9
|
+
// grows only when we add a core primitive of our own, never for a community package.
|
|
21
10
|
import { isRecord } from './type-guards.js';
|
|
22
11
|
const EMPTY = {
|
|
23
12
|
listeners: new Set(),
|
|
24
13
|
byRaw: new Map(),
|
|
25
14
|
processors: new Map(),
|
|
26
15
|
};
|
|
27
|
-
//
|
|
28
|
-
// commit COLOR_PROPS). The source is never consulted for these, so they can't
|
|
29
|
-
// drift. Everything else derives. This list grows only when WE add a core
|
|
30
|
-
// primitive, never for a community package.
|
|
16
|
+
// Our own primitives — see the module header for why the source is never consulted for these.
|
|
31
17
|
const BUILTIN_COMPONENTS = new Set([
|
|
32
18
|
'RCTView',
|
|
33
19
|
'RCTText',
|
|
@@ -156,39 +142,18 @@ export function registeredNativeEvent(component, raw) {
|
|
|
156
142
|
export function registeredProcessor(component, key) {
|
|
157
143
|
return resolve(component).processors.get(key);
|
|
158
144
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
* ViewConfig, neither name was in the C++ list, both reached Fabric as CSS strings, and iOS answers
|
|
172
|
-
* a string colour with `clearColor()`. The slider dragged and reported values correctly with no
|
|
173
|
-
* track drawn at all. Any list of names is a list somebody has to extend for a component we have
|
|
174
|
-
* never seen — which would have meant editing C++ to add a native view, and that is exactly the
|
|
175
|
-
* coupling `<native_core_is_untouched>` exists to prevent.
|
|
176
|
-
*
|
|
177
|
-
* Resolved ONCE per component and cached, because `createElement` asks per node. A built-in
|
|
178
|
-
* short-circuits inside `resolve` before any of this.
|
|
179
|
-
*/
|
|
180
|
-
/**
|
|
181
|
-
* The prop names a component's OWN ViewConfig claims a processor for — i.e. exactly the keys
|
|
182
|
-
* `configPayloadFold` has already converted by the time the payload builder's own passes run.
|
|
183
|
-
*
|
|
184
|
-
* It exists so "a colour is converted exactly once" can be a stated rule rather than a lucky one.
|
|
185
|
-
* The overlap is real: `thumbTintColor` is claimed by @symbiote-native/slider's config AND by the
|
|
186
|
-
* engine's built-in COLOR_PROPS, and for a while nothing broke only because a processed colour came
|
|
187
|
-
* back as a NUMBER and the engine skipped numbers. That guard died when a numeric colour became
|
|
188
|
-
* processable in its own right — an author writing `color: 0xff0000ff` means rrggbbaa and owes the
|
|
189
|
-
* same rotation a string owes — and the second conversion then turned an already-correct int into
|
|
190
|
-
* a different colour.
|
|
191
|
-
*/
|
|
145
|
+
// A component's ViewConfig processors, as a payload fold — or undefined when it has none. Not a
|
|
146
|
+
// lookup at payload-build time: the payload is built in C++ on a device and this registry can't
|
|
147
|
+
// cross that boundary (it's populated lazily from an injected JS-closure-holding lookup).
|
|
148
|
+
// payloadFold is the one seam that already runs in JS on both paths, so putting the processors
|
|
149
|
+
// there is what makes a third-party view behave the same on device as in a test. The alternative,
|
|
150
|
+
// a list of prop names hardcoded in C++, needs editing native code for every new component we see.
|
|
151
|
+
// Resolved once per component and cached, since createElement asks per node. A built-in
|
|
152
|
+
// short-circuits inside resolve before any of this.
|
|
153
|
+
// The prop names a component's own ViewConfig claims a processor for — exactly the keys
|
|
154
|
+
// configPayloadFold has already converted by the time the payload builder's own passes run.
|
|
155
|
+
// Exists so "a colour is converted exactly once" is a stated rule, not a lucky one: an overlap
|
|
156
|
+
// between a third-party config and the engine's own COLOR_PROPS would otherwise double-convert.
|
|
192
157
|
export function configProcessedKeys(component) {
|
|
193
158
|
const cached = keysCache.get(component);
|
|
194
159
|
if (cached !== undefined)
|
package/build/report-error.js
CHANGED
|
@@ -1,21 +1,8 @@
|
|
|
1
1
|
// Hand an error to the host the way React Native itself does, for the seams where an adapter
|
|
2
2
|
// catches something its framework would otherwise have surfaced on its own.
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// Libraries. `global.ErrorUtils` is the same surface through the documented global that
|
|
7
|
-
// @react-native/js-polyfills installs before any module evaluates - RN's own
|
|
8
|
-
// Libraries/vendor/core/ErrorUtils.js is nothing but `export default global.ErrorUtils`. Off a
|
|
9
|
-
// native host (vitest, node smokes) the global is absent and console.error is the whole channel.
|
|
10
|
-
//
|
|
11
|
-
// This is NOT the dlog channel. dlog is DEBUG-gated and therefore the developer's; an error that
|
|
12
|
-
// blanked the screen has to reach the app whether or not anyone turned diagnostics on.
|
|
13
|
-
// Read off globalThis through Reflect rather than named as an identifier, and deliberately NOT
|
|
14
|
-
// declared in an ambient block: react-native ships its own `const ErrorUtils: ErrorUtils` in
|
|
15
|
-
// src/types/globals.d.ts, so a `declare global { var ErrorUtils }` here redeclares it (TS2451) for
|
|
16
|
-
// every package whose tsconfig pulls in RN's types - the engine's own does not, so it typechecks
|
|
17
|
-
// clean here and breaks ngc downstream. RN's declared shape also lists only the two
|
|
18
|
-
// get/setGlobalHandler members, not reportError, which the polyfill does install.
|
|
3
|
+
// Read off globalThis via Reflect, not a named identifier or an ambient declare: react-native
|
|
4
|
+
// ships its own `ErrorUtils` global type, so redeclaring it here breaks any package whose tsconfig
|
|
5
|
+
// pulls in RN's types. RN's declared shape also omits reportError, which the polyfill installs.
|
|
19
6
|
function nativeReporter() {
|
|
20
7
|
const utils = Reflect.get(globalThis, 'ErrorUtils');
|
|
21
8
|
if (typeof utils !== 'object' || utils === null)
|
|
@@ -54,8 +41,7 @@ export function reportUncaughtError(value, info) {
|
|
|
54
41
|
const report = nativeReporter();
|
|
55
42
|
if (report !== null) {
|
|
56
43
|
// Exactly one channel, never both: RN routes console.error into LogBox as well, so logging
|
|
57
|
-
// here too would double-report every error.
|
|
58
|
-
// this same reason (Libraries/Core/ReactFiberErrorDialog.js:57).
|
|
44
|
+
// here too would double-report every error.
|
|
59
45
|
report(error);
|
|
60
46
|
return;
|
|
61
47
|
}
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A style value with its structured keys resolved — the same value by identity when there was
|
|
3
|
-
* nothing to resolve, which is nearly always.
|
|
4
|
-
*
|
|
5
|
-
* Accepts what a style slot can hold: one object, or a (nested) array of them. An array is not
|
|
6
|
-
* memoized — `pushClassStyle` mints a fresh one on every publish, so a cache keyed on it could
|
|
7
|
-
* never hit; its ENTRIES carry the memo instead, and the original array comes back untouched when
|
|
8
|
-
* none of them moved.
|
|
9
|
-
*/
|
|
10
1
|
export declare function resolveStructuredStyle(style: unknown): unknown;
|
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
// The ten style keys RN parses in JS before native, and the one place they are resolved.
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// read.
|
|
11
|
-
//
|
|
12
|
-
// This is the same move `configPayloadFold` makes for a third-party view's own processors, one
|
|
13
|
-
// layer down: anything the C++ half cannot do has to happen before the C++ half sees the value.
|
|
14
|
-
//
|
|
15
|
-
// IDENTITY IS PART OF THE CONTRACT. A style object that needs nothing comes back BY IDENTITY, and
|
|
16
|
-
// so does an array whose every entry did. The host's `OP_SET_PROP` skips a same-identity write, and
|
|
17
|
-
// `pushClassStyle` compares what it is about to publish against what it published last — hand
|
|
18
|
-
// either of them a fresh object per write and an unchanged style becomes a write and a dirty node
|
|
19
|
-
// on every render.
|
|
2
|
+
// They run at write time, not payload-build time: SymbioteFabricProps.cpp doesn't carry these
|
|
3
|
+
// processors, so resolving only in fabric-props.ts leaves the device its raw CSS string, silently
|
|
4
|
+
// dropped (C++ parses a style string only under enableNativeCSSParsing, default false).
|
|
5
|
+
// Same move `configPayloadFold` makes for a third-party view's own processors: anything the C++
|
|
6
|
+
// half can't do has to happen before the C++ half sees the value.
|
|
7
|
+
// Identity is part of the contract: an object/array needing no resolution comes back by identity,
|
|
8
|
+
// since OP_SET_PROP skips a same-identity write and pushClassStyle diffs by reference — a fresh
|
|
9
|
+
// object per call would turn an unchanged style into a write and a dirty node every render.
|
|
20
10
|
import { processAspectRatio } from './process-aspect-ratio.js';
|
|
21
11
|
import { processBackgroundImage } from './process-background-image/index.js';
|
|
22
12
|
import { processBackgroundPosition, processBackgroundRepeat, processBackgroundSize, } from './process-background-longhands.js';
|
|
@@ -80,10 +70,9 @@ function asFontVariantInput(value) {
|
|
|
80
70
|
return value.filter(isString);
|
|
81
71
|
return '';
|
|
82
72
|
}
|
|
83
|
-
// transform accepts a CSS string
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
// [] (which would erase a valid transform).
|
|
73
|
+
// transform accepts a CSS string or an array of single-key records (the hot animated /
|
|
74
|
+
// sticky-header path). A non-string non-array value passes through verbatim — it may already be
|
|
75
|
+
// processed, so coercing it to [] would erase a valid transform.
|
|
87
76
|
function processTransformValue(value) {
|
|
88
77
|
if (typeof value === 'string')
|
|
89
78
|
return processTransform(value);
|
|
@@ -154,15 +143,11 @@ function resolveRecord(style) {
|
|
|
154
143
|
resolvedStyles.set(style, answer);
|
|
155
144
|
return answer;
|
|
156
145
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
* memoized — `pushClassStyle` mints a fresh one on every publish, so a cache keyed on it could
|
|
163
|
-
* never hit; its ENTRIES carry the memo instead, and the original array comes back untouched when
|
|
164
|
-
* none of them moved.
|
|
165
|
-
*/
|
|
146
|
+
// A style value with its structured keys resolved — same value by identity when nothing needed
|
|
147
|
+
// resolving, which is nearly always.
|
|
148
|
+
// Accepts one object or a (nested) array of them. An array itself isn't memoized (pushClassStyle
|
|
149
|
+
// mints a fresh one per publish, so a cache keyed on it would never hit); its entries carry the
|
|
150
|
+
// memo instead.
|
|
166
151
|
export function resolveStructuredStyle(style) {
|
|
167
152
|
if (Array.isArray(style)) {
|
|
168
153
|
let out;
|
package/build/styles.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
// The typed style surface (ViewStyle
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// react-native/Libraries/StyleSheet/StyleSheetTypes): the load-bearing layout / box /
|
|
5
|
-
// shadow / transform / text props, not the full surface. Agnostic types, so they
|
|
6
|
-
// live in the engine next to the style processors; every adapter re-exports them.
|
|
1
|
+
// The typed style surface (ViewStyle/TextStyle and friends). Maps onto Yoga layout props and RN's
|
|
2
|
+
// view/text props, which Fabric's C++ reads off the props payload. A correctly-typed subset of
|
|
3
|
+
// RN's StyleSheet surface — agnostic types, so every adapter re-exports them from the engine.
|
|
7
4
|
export {};
|
package/build/surface.d.ts
CHANGED
|
@@ -6,38 +6,12 @@ export declare class SymbioteSurface {
|
|
|
6
6
|
private readonly node;
|
|
7
7
|
private commitScheduled;
|
|
8
8
|
constructor(rootTag: IRootTag);
|
|
9
|
-
/**
|
|
10
|
-
* Every OTHER live surface, so one commit names every root — see `commitSurfaceOps`.
|
|
11
|
-
*
|
|
12
|
-
* Static because it reads a sibling instance's private handle, which only a member of this class
|
|
13
|
-
* may do. One surface — the universal case — allocates nothing.
|
|
14
|
-
*
|
|
15
|
-
* `self` may already be OUT of the registry: a teardown unregisters and then commits, and that
|
|
16
|
-
* commit is the one carrying the removals. So the fast path cannot be a size check — with one
|
|
17
|
-
* live surface left, `size === 1` means either "only me" or "only the other one", and taking the
|
|
18
|
-
* shortcut on the second reading is how a surface loses the very batch that empties it.
|
|
19
|
-
*/
|
|
20
9
|
private static others;
|
|
21
|
-
/**
|
|
22
|
-
* The top-level nodes, asked of the host.
|
|
23
|
-
*
|
|
24
|
-
* A getter rather than an array this class maintains: a second copy of a child list is the thing
|
|
25
|
-
* this design removes, and `nextSiblingOf` (host-access.ts) needs the same answer the host gives
|
|
26
|
-
* for a parented node.
|
|
27
|
-
*/
|
|
28
10
|
get children(): readonly ISymbioteNode[];
|
|
29
11
|
appendChild(child: ISymbioteNode): void;
|
|
30
12
|
insertBefore(child: ISymbioteNode, beforeChild: ISymbioteNode): void;
|
|
31
13
|
removeChild(child: ISymbioteNode): void;
|
|
32
14
|
clear(): void;
|
|
33
|
-
/**
|
|
34
|
-
* Release every host behavior still standing under this surface, at unmount.
|
|
35
|
-
*
|
|
36
|
-
* The sweep above cannot answer this: it only sees nodes a `removeChild` NOMINATED, and an
|
|
37
|
-
* unmount removes nothing — the adapter drops the whole surface. Without it every node keeps its
|
|
38
|
-
* `afterCommit` registration and its timers, and a restarted surface's commits drain the dead
|
|
39
|
-
* one's hooks forever.
|
|
40
|
-
*/
|
|
41
15
|
teardown(): void;
|
|
42
16
|
commit(): void;
|
|
43
17
|
requestCommit(): void;
|