@symbiote-native/engine 0.2.0 → 0.4.0

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 (75) hide show
  1. package/README.md +24 -11
  2. package/build/accessibility-props.d.ts +19 -0
  3. package/build/accessibility-props.js +209 -0
  4. package/build/action-sheet-ios/index.js +4 -1
  5. package/build/animated/animations/composition.js +3 -1
  6. package/build/animated/animations/spring-config.js +4 -1
  7. package/build/animated/animations/spring.js +23 -9
  8. package/build/animated/animations/timing.js +3 -2
  9. package/build/animated/bezier.js +2 -1
  10. package/build/animated/color.js +4 -2
  11. package/build/animated/event.js +7 -3
  12. package/build/animated/graph.js +8 -3
  13. package/build/animated/index.d.ts +2 -2
  14. package/build/animated/index.js +2 -2
  15. package/build/animated/interpolation.js +7 -2
  16. package/build/animated/mock.js +1 -1
  17. package/build/animated/native/native-animated.js +1 -1
  18. package/build/animated/operators.js +27 -6
  19. package/build/animated/props.js +1 -1
  20. package/build/animated/rgba.js +18 -3
  21. package/build/animated/style.js +13 -3
  22. package/build/animated/value-xy.d.ts +8 -5
  23. package/build/animated/value-xy.js +4 -1
  24. package/build/app-registry/index.d.ts +1 -0
  25. package/build/app-registry/index.js +15 -5
  26. package/build/appearance/index.js +4 -1
  27. package/build/commit.d.ts +35 -0
  28. package/build/commit.js +613 -74
  29. package/build/debug.js +10 -4
  30. package/build/events/index.js +142 -88
  31. package/build/fabric-props.js +171 -11
  32. package/build/fabric.d.ts +10 -3
  33. package/build/fabric.js +11 -2
  34. package/build/host-behavior.d.ts +47 -0
  35. package/build/host-behavior.js +262 -0
  36. package/build/host-instance/index.d.ts +2 -10
  37. package/build/host-instance/index.js +13 -46
  38. package/build/image-loader.js +3 -2
  39. package/build/index.d.ts +24 -17
  40. package/build/index.js +27 -13
  41. package/build/interaction-manager/index.js +2 -1
  42. package/build/layout-animation/index.js +12 -4
  43. package/build/native-events.js +2 -1
  44. package/build/native-modules/index.js +3 -1
  45. package/build/node.d.ts +121 -2
  46. package/build/node.js +623 -41
  47. package/build/pan-responder/index.js +20 -9
  48. package/build/permissions-android/index.js +3 -1
  49. package/build/platform/index.android.d.ts +1 -1
  50. package/build/platform/index.android.js +1 -1
  51. package/build/platform/index.ios.d.ts +1 -1
  52. package/build/platform-color/index.js +3 -1
  53. package/build/post-commit.d.ts +1 -0
  54. package/build/post-commit.js +6 -0
  55. package/build/process-background-image/index.js +30 -9
  56. package/build/process-filter.js +11 -4
  57. package/build/registry.js +10 -2
  58. package/build/report-error.js +4 -1
  59. package/build/share/index.android.js +1 -1
  60. package/build/share/index.ios.js +1 -1
  61. package/build/status-bar/index.android.js +3 -4
  62. package/build/status-bar/index.ios.js +1 -1
  63. package/build/style-registry/index.d.ts +11 -2
  64. package/build/style-registry/index.js +223 -169
  65. package/build/style-registry/scope.d.ts +15 -1
  66. package/build/style-registry/scope.js +29 -27
  67. package/build/styles.d.ts +11 -1
  68. package/build/surface.d.ts +1 -1
  69. package/build/surface.js +8 -0
  70. package/build/tags.d.ts +1 -0
  71. package/build/tags.js +31 -1
  72. package/build/touch-history.js +9 -2
  73. package/build/vibration/index.ios.js +1 -1
  74. package/build/view-config.js +20 -2
  75. package/package.json +12 -2
package/build/tags.js CHANGED
@@ -2,9 +2,39 @@
2
2
  // for root tags). A tag is minted once when a node is first created and then
3
3
  // stays with it across clone-on-write commits (the clone keeps the family), so
4
4
  // this counter only ever moves forward: one tag per node, not per commit.
5
- let next = 2;
5
+ import { dlog } from './debug.js';
6
+ // WHY IT DOES NOT START AT 2. React's own Fabric renderer allocates tags the exact same way and
7
+ // from the exact same seed — `let nextReactTag = 2; ... nextReactTag += 2` in
8
+ // react-native-renderer/src/ReactFiberConfigFabric.js. We replace React as the APP's renderer, but
9
+ // React is still in the bundle and still drives one Fabric surface of its own: **LogBox**. So the
10
+ // first JS error in a symbiote app opens a redbox, React mints tag 2 for it, and Fabric aborts the
11
+ // process on a Create for a tag the engine registered at app start:
12
+ //
13
+ // *** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
14
+ // reason: 'RCTComponentViewRegistry: Attempt to dequeue already registered component.'
15
+ // -[RCTComponentViewRegistry dequeueComponentViewWithComponentHandle:tag:]
16
+ // RCTPerformMountInstructions(...)
17
+ //
18
+ // `RCTComponentViewRegistry` is process-wide, not per-surface, so the two allocators must not
19
+ // overlap. Diagnosed 2026-08-20 on examples/svelte: an `effect_update_depth_exceeded` on the API
20
+ // Playground screen turned into a SIGABRT with no JS stack, because the redbox that would have
21
+ // named the file killed the app instead of showing. Starting a whole surface's worth of tags above
22
+ // React's seed keeps the redbox a redbox: LogBox needs a few hundred nodes, so it can never walk
23
+ // 500k allocations up into this range.
24
+ const REACT_LOGBOX_TAG_RESERVE = 1_000_000;
25
+ let next = REACT_LOGBOX_TAG_RESERVE + 2;
26
+ let announced = false;
6
27
  export function nextTag() {
28
+ if (!announced) {
29
+ announced = true;
30
+ // Printed once, next to the first `commit ... createNode tag=` line: a device log that shows a
31
+ // Fabric tag below this base was minted by React (LogBox), not by us.
32
+ dlog(`tag allocator base=${next} (React's own Fabric tags stay below it)`);
33
+ }
7
34
  const tag = next;
8
35
  next += 2;
9
36
  return tag;
10
37
  }
38
+ // The lowest tag this allocator can ever hand out. Exported for the regression test that pins the
39
+ // no-overlap invariant against React's own allocator; nothing at runtime reads it.
40
+ export const FIRST_TAG = REACT_LOGBOX_TAG_RESERVE + 2;
@@ -21,7 +21,9 @@ export const touchHistory = {
21
21
  mostRecentTimeStamp: 0,
22
22
  };
23
23
  function toFiniteNumber(value) {
24
- return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
24
+ return typeof value === 'number' && Number.isFinite(value)
25
+ ? value
26
+ : undefined;
25
27
  }
26
28
  // Pull a recordable touch out of an untyped entry. RN's getTouchIdentifier throws on
27
29
  // a null id; we skip instead, so events without touch geometry leave the bank untouched.
@@ -35,7 +37,12 @@ function normalizeTouch(raw) {
35
37
  return undefined;
36
38
  if (identifier < 0 || identifier > MAX_TOUCH_BANK)
37
39
  return undefined;
38
- return { identifier, pageX, pageY, timestamp: toFiniteNumber(raw.timestamp) ?? 0 };
40
+ return {
41
+ identifier,
42
+ pageX,
43
+ pageY,
44
+ timestamp: toFiniteNumber(raw.timestamp) ?? 0,
45
+ };
39
46
  }
40
47
  // The changed touches for this frame (start/move/end), defensively read.
41
48
  function changedTouchesOf(nativeEvent) {
@@ -3,7 +3,7 @@
3
3
  // Everything else (the single-number buzz, cancel, the module resolver) is the shared
4
4
  // core. Metro picks this file on an iOS host; the base vibration.ts re-exports it for
5
5
  // web/headless.
6
- import { createVibration, DEFAULT_VIBRATION_LENGTH } from './shared.js';
6
+ import { createVibration, DEFAULT_VIBRATION_LENGTH, } from './shared.js';
7
7
  // JS scheduler state, mirroring RN's _vibrating / _id. `scheduleId` guards against a
8
8
  // stale timer from a previous run firing into a new one.
9
9
  let vibrating = false;
@@ -30,6 +30,12 @@ const BASE_EVENTS = [
30
30
  'press',
31
31
  'pressIn',
32
32
  'pressOut',
33
+ // Synthesized from the touch stream like its four siblings, and omitted here until 2026-09-02.
34
+ // A name the press machine OWNS but the engine does not route is dead on the lowered path only:
35
+ // `routeProp` hands an `on*` prop to `setEventListener` (and thus to the behavior's stash) only
36
+ // for a registered event, so `onPressMove` landed in `node.props` where nothing reads it, while
37
+ // a wrapper passes the same callback to the machine directly and stayed correct.
38
+ 'pressMove',
33
39
  'longPress',
34
40
  'layout',
35
41
  'focus',
@@ -55,7 +61,12 @@ const TEXT_INPUT_EVENTS = [
55
61
  'selectionChange',
56
62
  'contentSizeChange',
57
63
  ];
58
- const MODAL_EVENTS = ['show', 'dismiss', 'requestClose', 'orientationChange'];
64
+ const MODAL_EVENTS = [
65
+ 'show',
66
+ 'dismiss',
67
+ 'requestClose',
68
+ 'orientationChange',
69
+ ];
59
70
  // A scroll view's events are the same on both axes and both platforms; only the native
60
71
  // NAME differs (iOS RCTScrollView for both; Android RCTScrollView vertical vs
61
72
  // AndroidHorizontalScrollView horizontal). Declared once, keyed under each name below. The
@@ -78,7 +89,14 @@ const TEXT_EVENTS = ['textLayout'];
78
89
  // SymbioteNode.component (what createNode is called with). A component absent here
79
90
  // still gets BASE_EVENTS, so a new primitive has working press/layout for free.
80
91
  const COMPONENT_EVENTS = {
81
- RCTImageView: ['loadStart', 'load', 'loadEnd', 'error', 'progress', 'partialLoad'],
92
+ RCTImageView: [
93
+ 'loadStart',
94
+ 'load',
95
+ 'loadEnd',
96
+ 'error',
97
+ 'progress',
98
+ 'partialLoad',
99
+ ],
82
100
  RCTScrollView: SCROLL_EVENTS,
83
101
  AndroidHorizontalScrollView: SCROLL_EVENTS,
84
102
  RCTSinglelineTextInputView: TEXT_INPUT_EVENTS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbiote-native/engine",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "SymbioteNative's retained shadow-tree engine — clone-on-write commit path + event normalization over React Native Fabric, shared by every framework adapter.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -17,6 +17,16 @@
17
17
  "main": "./build/index.js",
18
18
  "module": "./build/index.js",
19
19
  "types": "./build/index.d.ts",
20
+ "keywords": [
21
+ "react-native",
22
+ "symbiote-native",
23
+ "fabric",
24
+ "shadow-tree",
25
+ "renderer-core",
26
+ "jsi",
27
+ "yoga",
28
+ "cross-platform"
29
+ ],
20
30
  "exports": {
21
31
  ".": {
22
32
  "types": "./build/index.d.ts",
@@ -33,7 +43,7 @@
33
43
  "react-native": ">=0.86"
34
44
  },
35
45
  "devDependencies": {
36
- "@symbiote-native/test-utils": "0.1.6"
46
+ "@symbiote-native/test-utils": "0.3.0"
37
47
  },
38
48
  "scripts": {
39
49
  "typecheck": "tsc --build",