react-native-list 1.0.0 → 2.0.0-alpha.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 (200) hide show
  1. package/README.md +190 -32
  2. package/ReactNativeList.podspec +39 -0
  3. package/android/CMakeLists.txt +48 -0
  4. package/android/build.gradle +151 -0
  5. package/android/fix-prefab.gradle +51 -0
  6. package/android/gradle.properties +5 -0
  7. package/android/src/main/AndroidManifest.xml +2 -0
  8. package/android/src/main/cpp/JHybridUiListModule.cpp +192 -0
  9. package/android/src/main/cpp/JHybridUiListModule.h +50 -0
  10. package/android/src/main/cpp/cpp-adapter.cpp +12 -0
  11. package/android/src/main/java/com/hannojg/reactnativelist/ReactNativeListPackage.kt +27 -0
  12. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridNativeListDataSource.kt +146 -0
  13. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridNativeListLayout.kt +86 -0
  14. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridUiListModule.kt +116 -0
  15. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridUiListView.kt +410 -0
  16. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridViewHolder.kt +9 -0
  17. package/android/src/main/java/com/margelo/nitro/reactnativelist/NativeListAdapter.kt +217 -0
  18. package/ios/DataSource/HybridNativeListDataSource.swift +213 -0
  19. package/ios/HybridObjects/HybridUiListModule.swift +49 -0
  20. package/ios/HybridObjects/HybridViewHolder.swift +16 -0
  21. package/ios/Layout/HybridNativeListLayout.swift +128 -0
  22. package/ios/Utils/ErrorUtils.h +26 -0
  23. package/ios/Utils/HybridIOSWorkletsModuleProxyHolder.swift +10 -0
  24. package/ios/Utils/SurfaceHelper.h +20 -0
  25. package/ios/Utils/SurfaceHelper.mm +144 -0
  26. package/ios/Utils/SurfacePresenterRegistry.h +17 -0
  27. package/ios/Utils/SurfacePresenterRegistry.m +31 -0
  28. package/ios/Utils/TurboModuleInstaller.h +18 -0
  29. package/ios/Utils/TurboModuleInstaller.mm +267 -0
  30. package/ios/Views/HostCell.swift +216 -0
  31. package/ios/Views/HybridUiListView.swift +695 -0
  32. package/metro/RendererProxyThreadSwitch.js +66 -0
  33. package/metro-config.d.ts +1 -0
  34. package/metro-config.js +52 -0
  35. package/nitro.json +47 -0
  36. package/nitrogen/generated/.gitattributes +1 -0
  37. package/nitrogen/generated/android/ReactNativeList+autolinking.cmake +99 -0
  38. package/nitrogen/generated/android/ReactNativeList+autolinking.gradle +27 -0
  39. package/nitrogen/generated/android/ReactNativeListOnLoad.cpp +156 -0
  40. package/nitrogen/generated/android/ReactNativeListOnLoad.hpp +34 -0
  41. package/nitrogen/generated/android/c++/JFunc_bool_NativeListItem_NativeListItem.hpp +83 -0
  42. package/nitrogen/generated/android/c++/JFunc_bool_double_NativeListItem_double.hpp +83 -0
  43. package/nitrogen/generated/android/c++/JFunc_double_std__string.hpp +78 -0
  44. package/nitrogen/generated/android/c++/JHybridIOSWorkletsModuleProxyHolderSpec.cpp +49 -0
  45. package/nitrogen/generated/android/c++/JHybridIOSWorkletsModuleProxyHolderSpec.hpp +63 -0
  46. package/nitrogen/generated/android/c++/JHybridNativeLinearListLayoutSpec.cpp +63 -0
  47. package/nitrogen/generated/android/c++/JHybridNativeLinearListLayoutSpec.hpp +65 -0
  48. package/nitrogen/generated/android/c++/JHybridNativeListDataSourceSpec.cpp +101 -0
  49. package/nitrogen/generated/android/c++/JHybridNativeListDataSourceSpec.hpp +70 -0
  50. package/nitrogen/generated/android/c++/JHybridNativeListLayoutSpec.cpp +49 -0
  51. package/nitrogen/generated/android/c++/JHybridNativeListLayoutSpec.hpp +63 -0
  52. package/nitrogen/generated/android/c++/JHybridUiListModuleSpec.cpp +65 -0
  53. package/nitrogen/generated/android/c++/JHybridUiListModuleSpec.hpp +64 -0
  54. package/nitrogen/generated/android/c++/JHybridUiListViewSpec.cpp +92 -0
  55. package/nitrogen/generated/android/c++/JHybridUiListViewSpec.hpp +67 -0
  56. package/nitrogen/generated/android/c++/JHybridViewHolderSpec.cpp +49 -0
  57. package/nitrogen/generated/android/c++/JHybridViewHolderSpec.hpp +63 -0
  58. package/nitrogen/generated/android/c++/JNativeItemSizeEstimate.hpp +61 -0
  59. package/nitrogen/generated/android/c++/JNativeLinearListLayoutConfig.hpp +81 -0
  60. package/nitrogen/generated/android/c++/JNativeLinearListLayoutIOSConfig.hpp +59 -0
  61. package/nitrogen/generated/android/c++/JNativeListItem.hpp +76 -0
  62. package/nitrogen/generated/android/c++/JVariant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.cpp +26 -0
  63. package/nitrogen/generated/android/c++/JVariant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.hpp +72 -0
  64. package/nitrogen/generated/android/c++/views/JHybridUiListViewStateUpdater.cpp +53 -0
  65. package/nitrogen/generated/android/c++/views/JHybridUiListViewStateUpdater.hpp +49 -0
  66. package/nitrogen/generated/android/c++/views/JHybridViewHolderStateUpdater.cpp +53 -0
  67. package/nitrogen/generated/android/c++/views/JHybridViewHolderStateUpdater.hpp +49 -0
  68. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_bool_NativeListItem_NativeListItem.kt +80 -0
  69. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_bool_double_NativeListItem_double.kt +80 -0
  70. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_double_std__string.kt +80 -0
  71. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridIOSWorkletsModuleProxyHolderSpec.kt +52 -0
  72. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeLinearListLayoutSpec.kt +54 -0
  73. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeListDataSourceSpec.kt +87 -0
  74. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeListLayoutSpec.kt +52 -0
  75. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridUiListModuleSpec.kt +59 -0
  76. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridUiListViewSpec.kt +76 -0
  77. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridViewHolderSpec.kt +53 -0
  78. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeItemSizeEstimate.kt +56 -0
  79. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeLinearListLayoutConfig.kt +76 -0
  80. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeLinearListLayoutIOSConfig.kt +51 -0
  81. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeListItem.kt +71 -0
  82. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/ReactNativeListOnLoad.kt +35 -0
  83. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Variant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.kt +62 -0
  84. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridUiListViewManager.kt +80 -0
  85. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridUiListViewStateUpdater.kt +23 -0
  86. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridViewHolderManager.kt +80 -0
  87. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridViewHolderStateUpdater.kt +23 -0
  88. package/nitrogen/generated/ios/ReactNativeList+autolinking.rb +62 -0
  89. package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Bridge.cpp +162 -0
  90. package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Bridge.hpp +368 -0
  91. package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Umbrella.hpp +92 -0
  92. package/nitrogen/generated/ios/ReactNativeListAutolinking.mm +83 -0
  93. package/nitrogen/generated/ios/ReactNativeListAutolinking.swift +86 -0
  94. package/nitrogen/generated/ios/c++/HybridIOSWorkletsModuleProxyHolderSpecSwift.cpp +11 -0
  95. package/nitrogen/generated/ios/c++/HybridIOSWorkletsModuleProxyHolderSpecSwift.hpp +75 -0
  96. package/nitrogen/generated/ios/c++/HybridNativeLinearListLayoutSpecSwift.cpp +11 -0
  97. package/nitrogen/generated/ios/c++/HybridNativeLinearListLayoutSpecSwift.hpp +92 -0
  98. package/nitrogen/generated/ios/c++/HybridNativeListDataSourceSpecSwift.cpp +11 -0
  99. package/nitrogen/generated/ios/c++/HybridNativeListDataSourceSpecSwift.hpp +132 -0
  100. package/nitrogen/generated/ios/c++/HybridNativeListLayoutSpecSwift.cpp +11 -0
  101. package/nitrogen/generated/ios/c++/HybridNativeListLayoutSpecSwift.hpp +75 -0
  102. package/nitrogen/generated/ios/c++/HybridUiListModuleSpecSwift.cpp +11 -0
  103. package/nitrogen/generated/ios/c++/HybridUiListModuleSpecSwift.hpp +93 -0
  104. package/nitrogen/generated/ios/c++/HybridUiListViewSpecSwift.cpp +11 -0
  105. package/nitrogen/generated/ios/c++/HybridUiListViewSpecSwift.hpp +121 -0
  106. package/nitrogen/generated/ios/c++/HybridViewHolderSpecSwift.cpp +11 -0
  107. package/nitrogen/generated/ios/c++/HybridViewHolderSpecSwift.hpp +75 -0
  108. package/nitrogen/generated/ios/c++/views/HybridUiListViewComponent.mm +118 -0
  109. package/nitrogen/generated/ios/c++/views/HybridViewHolderComponent.mm +118 -0
  110. package/nitrogen/generated/ios/swift/Func_bool_NativeListItem_NativeListItem.swift +47 -0
  111. package/nitrogen/generated/ios/swift/Func_bool_double_NativeListItem_double.swift +47 -0
  112. package/nitrogen/generated/ios/swift/Func_double_std__string.swift +47 -0
  113. package/nitrogen/generated/ios/swift/HybridIOSWorkletsModuleProxyHolderSpec.swift +55 -0
  114. package/nitrogen/generated/ios/swift/HybridIOSWorkletsModuleProxyHolderSpec_cxx.swift +128 -0
  115. package/nitrogen/generated/ios/swift/HybridNativeLinearListLayoutSpec.swift +55 -0
  116. package/nitrogen/generated/ios/swift/HybridNativeLinearListLayoutSpec_cxx.swift +140 -0
  117. package/nitrogen/generated/ios/swift/HybridNativeListDataSourceSpec.swift +62 -0
  118. package/nitrogen/generated/ios/swift/HybridNativeListDataSourceSpec_cxx.swift +222 -0
  119. package/nitrogen/generated/ios/swift/HybridNativeListLayoutSpec.swift +55 -0
  120. package/nitrogen/generated/ios/swift/HybridNativeListLayoutSpec_cxx.swift +128 -0
  121. package/nitrogen/generated/ios/swift/HybridUiListModuleSpec.swift +56 -0
  122. package/nitrogen/generated/ios/swift/HybridUiListModuleSpec_cxx.swift +175 -0
  123. package/nitrogen/generated/ios/swift/HybridUiListViewSpec.swift +59 -0
  124. package/nitrogen/generated/ios/swift/HybridUiListViewSpec_cxx.swift +227 -0
  125. package/nitrogen/generated/ios/swift/HybridViewHolderSpec.swift +55 -0
  126. package/nitrogen/generated/ios/swift/HybridViewHolderSpec_cxx.swift +147 -0
  127. package/nitrogen/generated/ios/swift/NativeItemSizeEstimate.swift +60 -0
  128. package/nitrogen/generated/ios/swift/NativeLinearListLayoutConfig.swift +60 -0
  129. package/nitrogen/generated/ios/swift/NativeLinearListLayoutIOSConfig.swift +35 -0
  130. package/nitrogen/generated/ios/swift/NativeListItem.swift +75 -0
  131. package/nitrogen/generated/ios/swift/Variant_NullType__any_HybridIOSWorkletsModuleProxyHolderSpec_.swift +30 -0
  132. package/nitrogen/generated/shared/c++/HybridIOSWorkletsModuleProxyHolderSpec.cpp +21 -0
  133. package/nitrogen/generated/shared/c++/HybridIOSWorkletsModuleProxyHolderSpec.hpp +62 -0
  134. package/nitrogen/generated/shared/c++/HybridNativeLinearListLayoutSpec.cpp +22 -0
  135. package/nitrogen/generated/shared/c++/HybridNativeLinearListLayoutSpec.hpp +67 -0
  136. package/nitrogen/generated/shared/c++/HybridNativeListDataSourceSpec.cpp +28 -0
  137. package/nitrogen/generated/shared/c++/HybridNativeListDataSourceSpec.hpp +72 -0
  138. package/nitrogen/generated/shared/c++/HybridNativeListLayoutSpec.cpp +21 -0
  139. package/nitrogen/generated/shared/c++/HybridNativeListLayoutSpec.hpp +62 -0
  140. package/nitrogen/generated/shared/c++/HybridUiListModuleSpec.cpp +22 -0
  141. package/nitrogen/generated/shared/c++/HybridUiListModuleSpec.hpp +68 -0
  142. package/nitrogen/generated/shared/c++/HybridUiListViewSpec.cpp +25 -0
  143. package/nitrogen/generated/shared/c++/HybridUiListViewSpec.hpp +79 -0
  144. package/nitrogen/generated/shared/c++/HybridUiManagerHelperSpec.cpp +23 -0
  145. package/nitrogen/generated/shared/c++/HybridUiManagerHelperSpec.hpp +65 -0
  146. package/nitrogen/generated/shared/c++/HybridViewHolderSpec.cpp +21 -0
  147. package/nitrogen/generated/shared/c++/HybridViewHolderSpec.hpp +62 -0
  148. package/nitrogen/generated/shared/c++/NativeItemSizeEstimate.hpp +87 -0
  149. package/nitrogen/generated/shared/c++/NativeLinearListLayoutConfig.hpp +105 -0
  150. package/nitrogen/generated/shared/c++/NativeLinearListLayoutIOSConfig.hpp +85 -0
  151. package/nitrogen/generated/shared/c++/NativeListItem.hpp +101 -0
  152. package/nitrogen/generated/shared/c++/views/HybridUiListViewComponent.cpp +72 -0
  153. package/nitrogen/generated/shared/c++/views/HybridUiListViewComponent.hpp +109 -0
  154. package/nitrogen/generated/shared/c++/views/HybridViewHolderComponent.cpp +72 -0
  155. package/nitrogen/generated/shared/c++/views/HybridViewHolderComponent.hpp +109 -0
  156. package/nitrogen/generated/shared/json/UiListViewConfig.json +9 -0
  157. package/nitrogen/generated/shared/json/ViewHolderConfig.json +9 -0
  158. package/package.json +152 -5
  159. package/react-native.config.js +16 -0
  160. package/src/ListDataSource.ts +232 -0
  161. package/src/ListLayout.ts +95 -0
  162. package/src/UiListModule.ts +5 -0
  163. package/src/hooks/useChangeEffect.ts +50 -0
  164. package/src/index.tsx +49 -0
  165. package/src/privateGlobals.ts +20 -0
  166. package/src/renderer/fabric/RenderHelper.ts +29 -0
  167. package/src/renderer/fabric/UiManagerHelper.ts +5 -0
  168. package/src/renderer/react/ReactFabricMirror.bundle.js +1984 -0
  169. package/src/renderer/react/ReactFabricMirror.ts +766 -0
  170. package/src/renderer/react/ReactFabricRenderer.ts +11 -0
  171. package/src/specs/IOSWorkletsModuleProxyHolder.nitro.ts +6 -0
  172. package/src/specs/NativeLinearListLayout.nitro.ts +23 -0
  173. package/src/specs/NativeListDataSource.nitro.ts +28 -0
  174. package/src/specs/NativeListLayout.nitro.ts +6 -0
  175. package/src/specs/UIListModule.nitro.ts +13 -0
  176. package/src/specs/UIManagerHelper.nitro.ts +34 -0
  177. package/src/specs/UiListView.nitro.ts +31 -0
  178. package/src/specs/ViewHolder.nitro.ts +11 -0
  179. package/src/views/List.tsx +525 -0
  180. package/src/views/UiListHostComponent.ts +8 -0
  181. package/FillRateHelper.js +0 -179
  182. package/FlatList.js +0 -494
  183. package/LICENSE.md +0 -31
  184. package/ListView/__mocks__/ListViewMock.js +0 -55
  185. package/MetroListView.js +0 -166
  186. package/SectionList.js +0 -291
  187. package/ViewabilityHelper.js +0 -260
  188. package/VirtualizeUtils.js +0 -163
  189. package/VirtualizedList.js +0 -861
  190. package/VirtualizedSectionList.js +0 -397
  191. package/__flowtests__/FlatList-flowtest.js +0 -90
  192. package/__flowtests__/SectionList-flowtest.js +0 -89
  193. package/__tests__/FillRateHelper-test.js +0 -106
  194. package/__tests__/FlatList-test.js +0 -64
  195. package/__tests__/SectionList-test.js +0 -67
  196. package/__tests__/ViewabilityHelper-test.js +0 -359
  197. package/__tests__/VirtualizeUtils-test.js +0 -74
  198. package/__tests__/__snapshots__/FlatList-test.js.snap +0 -251
  199. package/__tests__/__snapshots__/SectionList-test.js.snap +0 -283
  200. package/index.js +0 -5
@@ -0,0 +1,766 @@
1
+ /* eslint-disable @react-native/no-deep-imports, @typescript-eslint/no-unused-vars, no-dupe-keys, prettier/prettier */
2
+ // @ts-nocheck
3
+
4
+ import type * as ReactModule from 'react'
5
+
6
+ function nativeLog(...args: unknown[]): void {
7
+ global._log?.(
8
+ '[ReactFabricMirror] ' +
9
+ args
10
+ .map((a) => {
11
+ try {
12
+ return JSON.stringify(a)
13
+ } catch (e) {
14
+ return '<failed to parse> ' + String(a)
15
+ }
16
+ })
17
+ .join(' ')
18
+ )
19
+ }
20
+ global.log = nativeLog
21
+
22
+ const Reconciler = require('react-reconciler')
23
+
24
+ // FabricUIManager is basically a wrapper around global.nativeFabricUIManager
25
+ // but caches each function to avoid recreating a jsi::HostFunction on each call.
26
+ const {
27
+ getFabricUIManager,
28
+ } = require('react-native/Libraries/ReactNative/FabricUIManager')
29
+ const uiManager = getFabricUIManager()
30
+
31
+ const {
32
+ create: createAttributePayload,
33
+ diff: diffAttributePayloads,
34
+ } = require('react-native/Libraries/ReactNative/ReactFabricPublicInstance/ReactNativeAttributePayload')
35
+
36
+ const ReactNativeViewConfigRegistry = require('react-native/Libraries/Renderer/shims/ReactNativeViewConfigRegistry')
37
+
38
+ global.rootHostContext = {}
39
+ global.childHostContext = {}
40
+
41
+ const {
42
+ NoEventPriority,
43
+ DefaultEventPriority,
44
+ DiscreteEventPriority,
45
+ ContinuousEventPriority,
46
+ IdleEventPriority,
47
+ } = require('react-reconciler/constants')
48
+ global.currentUpdatePriority = NoEventPriority
49
+ let currentCompleteRootSync: null | ((surfaceId: number, childSet: unknown) => void) =
50
+ null
51
+
52
+ global.rootContainersBySurfaceId = global.rootContainersBySurfaceId ?? {}
53
+
54
+ const {
55
+ getPublicInstance,
56
+ } = require('../../../shims/react-fiber-config-fabric.js')
57
+
58
+ //#region Event handling
59
+ const EventPluginUtilsModule = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/EventPluginUtils')
60
+ const { setComponentTree } = EventPluginUtilsModule
61
+ const {
62
+ injectEventPluginOrder,
63
+ injectEventPluginsByName,
64
+ plugins: legacyPlugins,
65
+ } = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/EventPluginRegistry')
66
+ const ResponderEventPluginModule = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/ResponderEventPlugin')
67
+ const ReactNativeEventPluginOrderModule = require('../../../../third_party/react/packages/react-native-renderer/src/ReactNativeEventPluginOrder')
68
+ const ReactFabricGlobalResponderHandlerModule = require('../../../../third_party/react/packages/react-native-renderer/src/ReactFabricGlobalResponderHandler')
69
+ const SyntheticEventModule = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/SyntheticEvent')
70
+ const accumulateIntoModule = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/accumulateInto')
71
+ const forEachAccumulatedModule = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/forEachAccumulated')
72
+ const {
73
+ batchedUpdates,
74
+ } = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/ReactGenericBatching')
75
+ const {
76
+ runEventsInBatch,
77
+ } = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/EventBatching')
78
+ const { HostComponent } = require('react-reconciler/src/ReactWorkTags')
79
+
80
+ const ResponderEventPlugin =
81
+ ResponderEventPluginModule.default ?? ResponderEventPluginModule
82
+ const ReactNativeEventPluginOrder =
83
+ ReactNativeEventPluginOrderModule.default ?? ReactNativeEventPluginOrderModule
84
+ const ReactFabricGlobalResponderHandler =
85
+ ReactFabricGlobalResponderHandlerModule.default ??
86
+ ReactFabricGlobalResponderHandlerModule
87
+
88
+ const SyntheticEvent = SyntheticEventModule.default ?? SyntheticEventModule
89
+ const accumulateInto = accumulateIntoModule.default ?? accumulateIntoModule
90
+ const forEachAccumulated =
91
+ forEachAccumulatedModule.default ?? forEachAccumulatedModule
92
+
93
+ const { customBubblingEventTypes, customDirectEventTypes } =
94
+ ReactNativeViewConfigRegistry
95
+
96
+ function getParent(inst) {
97
+ do {
98
+ inst = inst.return
99
+ } while (inst && inst.tag !== HostComponent)
100
+ return inst || null
101
+ }
102
+
103
+ function traverseTwoPhase(inst, fn, arg, skipBubbling) {
104
+ const path = []
105
+ while (inst) {
106
+ path.push(inst)
107
+ inst = getParent(inst)
108
+ }
109
+
110
+ for (let i = path.length - 1; i >= 0; i--) {
111
+ fn(path[i], 'captured', arg)
112
+ }
113
+
114
+ if (skipBubbling) {
115
+ fn(path[0], 'bubbled', arg)
116
+ } else {
117
+ for (let i = 0; i < path.length; i++) {
118
+ fn(path[i], 'bubbled', arg)
119
+ }
120
+ }
121
+ }
122
+
123
+ function getListener(inst, registrationName) {
124
+ const stateNode = inst.stateNode
125
+ if (stateNode == null) {
126
+ return null
127
+ }
128
+
129
+ const props = EventPluginUtilsModule.getFiberCurrentPropsFromNode(stateNode)
130
+ if (props == null) {
131
+ return null
132
+ }
133
+
134
+ const listener = props[registrationName]
135
+ if (listener != null && typeof listener !== 'function') {
136
+ throw new Error(
137
+ `Expected \`${registrationName}\` listener to be a function, got \`${typeof listener}\`.`
138
+ )
139
+ }
140
+ return listener
141
+ }
142
+
143
+ function listenerAtPhase(inst, event, propagationPhase) {
144
+ const registrationName =
145
+ event.dispatchConfig.phasedRegistrationNames[propagationPhase]
146
+ return getListener(inst, registrationName)
147
+ }
148
+
149
+ function accumulateDirectionalDispatches(inst, phase, event) {
150
+ const listener = listenerAtPhase(inst, event, phase)
151
+ if (listener) {
152
+ event._dispatchListeners = accumulateInto(
153
+ event._dispatchListeners,
154
+ listener
155
+ )
156
+ event._dispatchInstances = accumulateInto(event._dispatchInstances, inst)
157
+ }
158
+ }
159
+
160
+ function accumulateTwoPhaseDispatchesSingle(event) {
161
+ if (event && event.dispatchConfig.phasedRegistrationNames) {
162
+ traverseTwoPhase(
163
+ event._targetInst,
164
+ accumulateDirectionalDispatches,
165
+ event,
166
+ false
167
+ )
168
+ }
169
+ }
170
+
171
+ function accumulateTwoPhaseDispatches(events) {
172
+ forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle)
173
+ }
174
+
175
+ function accumulateCapturePhaseDispatches(event) {
176
+ if (event && event.dispatchConfig.phasedRegistrationNames) {
177
+ traverseTwoPhase(
178
+ event._targetInst,
179
+ accumulateDirectionalDispatches,
180
+ event,
181
+ true
182
+ )
183
+ }
184
+ }
185
+
186
+ function accumulateDispatches(inst, _ignoredDirection, event) {
187
+ if (inst && event && event.dispatchConfig.registrationName) {
188
+ const registrationName = event.dispatchConfig.registrationName
189
+ const listener = getListener(inst, registrationName)
190
+ if (listener) {
191
+ event._dispatchListeners = accumulateInto(
192
+ event._dispatchListeners,
193
+ listener
194
+ )
195
+ event._dispatchInstances = accumulateInto(event._dispatchInstances, inst)
196
+ }
197
+ }
198
+ }
199
+
200
+ function accumulateDirectDispatchesSingle(event) {
201
+ if (event && event.dispatchConfig.registrationName) {
202
+ accumulateDispatches(event._targetInst, null, event)
203
+ }
204
+ }
205
+
206
+ function accumulateDirectDispatches(events) {
207
+ forEachAccumulated(events, accumulateDirectDispatchesSingle)
208
+ }
209
+
210
+ const ReactNativeBridgeEventPlugin = {
211
+ eventTypes: {},
212
+ extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
213
+ if (targetInst == null) {
214
+ return null
215
+ }
216
+
217
+ const bubbleDispatchConfig = customBubblingEventTypes[topLevelType]
218
+ const directDispatchConfig = customDirectEventTypes[topLevelType]
219
+
220
+ if (!bubbleDispatchConfig && !directDispatchConfig) {
221
+ throw new Error(
222
+ `Unsupported top level event type "${topLevelType}" dispatched`
223
+ )
224
+ }
225
+
226
+ const event = SyntheticEvent.getPooled(
227
+ bubbleDispatchConfig || directDispatchConfig,
228
+ targetInst,
229
+ nativeEvent,
230
+ nativeEventTarget
231
+ )
232
+
233
+ if (bubbleDispatchConfig) {
234
+ const skipBubbling =
235
+ event != null &&
236
+ event.dispatchConfig.phasedRegistrationNames != null &&
237
+ event.dispatchConfig.phasedRegistrationNames.skipBubbling
238
+ if (skipBubbling) {
239
+ accumulateCapturePhaseDispatches(event)
240
+ } else {
241
+ accumulateTwoPhaseDispatches(event)
242
+ }
243
+ } else if (directDispatchConfig) {
244
+ accumulateDirectDispatches(event)
245
+ } else {
246
+ return null
247
+ }
248
+
249
+ return event
250
+ },
251
+ }
252
+
253
+ function extractPluginEvents(
254
+ topLevelType,
255
+ targetInst,
256
+ nativeEvent,
257
+ nativeEventTarget
258
+ ) {
259
+ let events = null
260
+ for (let i = 0; i < legacyPlugins.length; i++) {
261
+ const plugin = legacyPlugins[i]
262
+ if (plugin) {
263
+ const extractedEvents = plugin.extractEvents(
264
+ topLevelType,
265
+ targetInst,
266
+ nativeEvent,
267
+ nativeEventTarget
268
+ )
269
+ if (extractedEvents) {
270
+ events = accumulateInto(events, extractedEvents)
271
+ }
272
+ }
273
+ }
274
+ return events
275
+ }
276
+
277
+ function runExtractedPluginEventsInBatch(
278
+ topLevelType,
279
+ targetInst,
280
+ nativeEvent,
281
+ nativeEventTarget
282
+ ) {
283
+ const events = extractPluginEvents(
284
+ topLevelType,
285
+ targetInst,
286
+ nativeEvent,
287
+ nativeEventTarget
288
+ )
289
+ runEventsInBatch(events)
290
+ }
291
+
292
+ function ensureLegacyEventPluginsInjected() {
293
+ try {
294
+ injectEventPluginOrder(ReactNativeEventPluginOrder)
295
+ } catch (error) {
296
+ // The plugin order can only be injected once for a given registry instance.
297
+ if (
298
+ !String(error).includes(
299
+ 'Cannot inject event plugin ordering more than once'
300
+ )
301
+ ) {
302
+ throw error
303
+ }
304
+ }
305
+
306
+ injectEventPluginsByName({
307
+ ResponderEventPlugin,
308
+ ReactNativeBridgeEventPlugin,
309
+ })
310
+
311
+ setComponentTree(
312
+ // Equivalent to ReactFabricComponentTree.getFiberCurrentPropsFromNode
313
+ (instance) => instance?.canonical?.currentProps ?? null,
314
+ // Equivalent to ReactFabricComponentTree.getInstanceFromNode
315
+ (node) => {
316
+ if (
317
+ node?.canonical != null &&
318
+ node.canonical.internalInstanceHandle != null
319
+ ) {
320
+ return node.canonical.internalInstanceHandle
321
+ }
322
+ return node ?? null
323
+ },
324
+ // Equivalent to ReactFabricComponentTree.getNodeFromInstance
325
+ (fiber) => {
326
+ const publicInstance = getPublicInstance(fiber.stateNode)
327
+ if (publicInstance == null) {
328
+ throw new Error('Could not find host instance from fiber')
329
+ }
330
+ return publicInstance
331
+ }
332
+ )
333
+
334
+ ResponderEventPlugin.injection.injectGlobalResponderHandler(
335
+ ReactFabricGlobalResponderHandler
336
+ )
337
+ }
338
+
339
+ ensureLegacyEventPluginsInjected()
340
+
341
+ function dispatchEvent(target, topLevelType, nativeEvent) {
342
+ const targetFiber = target
343
+ let eventTarget = null
344
+ if (targetFiber != null) {
345
+ const stateNode = targetFiber.stateNode
346
+ if (stateNode != null) {
347
+ eventTarget = getPublicInstance(stateNode)
348
+ }
349
+ }
350
+
351
+ batchedUpdates(() => {
352
+ runExtractedPluginEventsInBatch(
353
+ topLevelType,
354
+ targetFiber,
355
+ nativeEvent,
356
+ eventTarget
357
+ )
358
+ })
359
+ }
360
+
361
+ // This will be retrieved on the native side in JSI ... hm or we call and set it?
362
+ global.handleEvent = dispatchEvent
363
+ //#endregion
364
+
365
+ // Counter for uniquely identifying views.
366
+ // % 10 === 1 means it is a rootTag.
367
+ // % 2 === 0 means it is a Fabric tag.
368
+ // This means that they never overlap.
369
+ global.nextReactTag = 200_000_000
370
+ // ^ Why is this number so high?
371
+ // We share the ReactInstance (ie we don't create a seperate one)
372
+ // That means our surface shares the RCTComponentViewRegistry on iOS with the main React Native renderer.
373
+ // When creating new views its checking if the tag already exists, meaning we can't use the same tags that react is using. Bummer!\
374
+ // TODO: find a better solution for this
375
+
376
+ const HostConfig = {
377
+ now: performance.now,
378
+ getRootHostContext(rootContainerInstance) {
379
+ return global.rootHostContext
380
+ },
381
+ getChildHostContext() {
382
+ return global.childHostContext
383
+ },
384
+ // prepareForCommit(containerInfo) {},
385
+ // resetAfterCommit(containerInfo) {},
386
+ supportsPersistence: true,
387
+ createInstance: (
388
+ type,
389
+ props,
390
+ rootContainerInstance,
391
+ _currentHostContext,
392
+ workInProgress
393
+ ) => {
394
+ const tag = global.nextReactTag
395
+ global.nextReactTag += 2
396
+
397
+ const viewConfig = ReactNativeViewConfigRegistry.get(type)
398
+ const updatePayload = createAttributePayload(
399
+ props,
400
+ viewConfig.validAttributes
401
+ )
402
+
403
+ let node
404
+ try {
405
+ node = uiManager.createNode(
406
+ tag, // reactTag
407
+ viewConfig.uiViewClassName, // viewName
408
+ rootContainerInstance.containerTag, // rootTag
409
+ updatePayload, // props
410
+ workInProgress // internalInstanceHandle
411
+ )
412
+ } catch (e) {
413
+ nativeLog(
414
+ '[createInstance] ERROR in createNode:',
415
+ e.message || String(e)
416
+ )
417
+ nativeLog('Stack:', new Error().stack)
418
+ throw e
419
+ }
420
+
421
+ return {
422
+ node: node,
423
+ canonical: {
424
+ nativeTag: tag,
425
+ viewConfig, // TODO: is this needed? for what
426
+ currentProps: props, // funny, react is passing here props instead of updatePayload, is this okay?
427
+ internalInstanceHandle: workInProgress,
428
+ publicInstance: null,
429
+ publicRootInstance: rootContainerInstance.publicInstance,
430
+ },
431
+ }
432
+ },
433
+
434
+ finalizeInitialChildren(parentInstance, type, props, hostContext) {
435
+ return false
436
+ },
437
+
438
+ cloneInstance(instance, type, oldProps, newProps, keepChildren, newChildSet) {
439
+
440
+ const viewConfig = instance.canonical.viewConfig
441
+ const updatePayload = diffAttributePayloads(
442
+ oldProps,
443
+ newProps,
444
+ viewConfig.validAttributes
445
+ )
446
+ // TODO: If the event handlers have changed, we need to update the current props
447
+ // in the commit phase but there is no host config hook to do it yet.
448
+ // So instead we hack it by updating it in the render phase.
449
+ instance.canonical.currentProps = newProps
450
+
451
+ const node = instance.node
452
+ let clone
453
+ if (keepChildren) {
454
+ if (updatePayload !== null) {
455
+ clone = uiManager.cloneNodeWithNewProps(node, updatePayload)
456
+ } else {
457
+ // No changes
458
+ return instance
459
+ }
460
+ } else {
461
+ // If passChildrenWhenCloningPersistedNodes is enabled, children will be non-null
462
+ if (newChildSet != null) {
463
+ if (updatePayload !== null) {
464
+ clone = uiManager.cloneNodeWithNewChildrenAndProps(
465
+ node,
466
+ newChildSet,
467
+ updatePayload
468
+ )
469
+ } else {
470
+ clone = uiManager.cloneNodeWithNewChildren(node, newChildSet)
471
+ }
472
+ } else {
473
+ if (updatePayload !== null) {
474
+ clone = uiManager.cloneNodeWithNewChildrenAndProps(
475
+ node,
476
+ updatePayload
477
+ )
478
+ } else {
479
+ clone = uiManager.cloneNodeWithNewChildren(node)
480
+ }
481
+ }
482
+ }
483
+
484
+ return {
485
+ node: clone,
486
+ canonical: instance.canonical,
487
+ }
488
+ },
489
+ createTextInstance(
490
+ text,
491
+ rootContainerInstance,
492
+ hostContext,
493
+ internalInstanceHandle
494
+ ) {
495
+ const tag = global.nextReactTag
496
+ global.nextReactTag += 2
497
+
498
+ const node = uiManager.createNode(
499
+ tag, // reactTag
500
+ 'RCTRawText', // viewName
501
+ rootContainerInstance.containerTag, // rootTag
502
+ { text: text }, // props
503
+ internalInstanceHandle // instance handle
504
+ )
505
+
506
+ return {
507
+ node: node,
508
+ }
509
+ },
510
+ createContainerChildSet() {
511
+ return uiManager.createChildSet()
512
+ },
513
+ appendChildToContainerChildSet(childSet, child) {
514
+ uiManager.appendChildToSet(childSet, child.node)
515
+ },
516
+ finalizeContainerChildren(container, newChildren) {
517
+ // Noop - children will be replaced in replaceContainerChildren
518
+ },
519
+ appendInitialChild(parentInstance, child) {
520
+ uiManager.appendChild(parentInstance.node, child.node)
521
+ },
522
+ replaceContainerChildren(container, newChildren) {
523
+ const completeRootSync = currentCompleteRootSync
524
+ if (completeRootSync == null) {
525
+ throw new Error('completeRootSync callback is required.')
526
+ }
527
+
528
+ completeRootSync(container.containerTag, newChildren)
529
+ },
530
+
531
+ // TODO: hm, this could get problematic, to share event priorities between the fabric ui manager.
532
+ // Maybe we need to create a clone of the ui manager? the important thing is that all view managers are resolved when we do so.
533
+ // However that would concern me if commitHooks from reanimated would work.
534
+ setCurrentUpdatePriority(priority) {
535
+ global.currentUpdatePriority = priority
536
+ },
537
+ getCurrentUpdatePriority() {
538
+ return global.currentUpdatePriority
539
+ },
540
+ resolveUpdatePriority() {
541
+ if (global.currentUpdatePriority !== NoEventPriority) {
542
+ return global.currentUpdatePriority
543
+ } else {
544
+ return DefaultEventPriority
545
+ }
546
+ // TODO:
547
+ /* const currentEventPriority = fabricGetCurrentEventPriority
548
+ ? fabricGetCurrentEventPriority()
549
+ : null;
550
+
551
+ if (currentEventPriority != null) {
552
+ switch (currentEventPriority) {
553
+ case FabricDiscretePriority:
554
+ return DiscreteEventPriority;
555
+ case FabricContinuousPriority:
556
+ return ContinuousEventPriority;
557
+ case FabricIdlePriority:
558
+ return IdleEventPriority;
559
+ case FabricDefaultPriority:
560
+ default:
561
+ return DefaultEventPriority;
562
+ }
563
+ }
564
+
565
+ return DefaultEventPriority; */
566
+ },
567
+
568
+ getPublicInstance(instance) {
569
+ return getPublicInstance(instance)
570
+ },
571
+
572
+ // getPublicTextInstance(textInstance, internalInstanceHandle) {
573
+ // if (textInstance.publicInstance == null) {
574
+ // textInstance.publicInstance = createPublicTextInstance(
575
+ // internalInstanceHandle
576
+ // )
577
+ // }
578
+ // return textInstance.publicInstance
579
+ // },
580
+ // getPublicInstanceFromInternalInstanceHandle(internalInstanceHandle) {
581
+ // const instance = internalInstanceHandle.stateNode
582
+
583
+ // // React resets all the fields in the fiber when the component is unmounted
584
+ // // to prevent memory leaks.
585
+ // if (instance == null) {
586
+ // return null
587
+ // }
588
+
589
+ // if (internalInstanceHandle.tag === HostText) {
590
+ // const textInstance = instance
591
+ // return this.getPublicTextInstance(textInstance, internalInstanceHandle)
592
+ // }
593
+
594
+ // const elementInstance = internalInstanceHandle.stateNode
595
+ // return this.getPublicInstance(elementInstance)
596
+ // },
597
+
598
+ prepareForCommit(containerInfo) {
599
+ return null
600
+ },
601
+ resetAfterCommit(containerInfo) {},
602
+
603
+ trackSchedulerEvent() {},
604
+ resolveEventType() {
605
+ return null
606
+ },
607
+ resolveEventTimeStamp() {
608
+ return -1.1
609
+ },
610
+ shouldAttemptEagerTransition() {
611
+ return false
612
+ },
613
+ shouldSetTextContent(type, props) {
614
+ return false
615
+ },
616
+ // TODO: microtask scheduling, should work with worklets on the UI thread i believe! not sure though if even RN implements this?
617
+ supportsMicrotasks: false,
618
+
619
+ detachDeletedInstance(node) {},
620
+ beforeActiveInstanceBlur(internalInstanceHandle) {
621
+ // noop
622
+ },
623
+
624
+ afterActiveInstanceBlur() {
625
+ // noop
626
+ },
627
+
628
+ preparePortalMount(portalInstance) {
629
+ // noop
630
+ },
631
+
632
+ detachDeletedInstance(node) {
633
+ // noop
634
+ },
635
+
636
+ requestPostPaintCallback(callback) {
637
+ // noop
638
+ },
639
+
640
+ maySuspendCommit(type, props) {
641
+ return false
642
+ },
643
+
644
+ maySuspendCommitOnUpdate(type, oldProps, newProps) {
645
+ return false
646
+ },
647
+ maySuspendCommitInSyncRender(type, props) {
648
+ return false
649
+ },
650
+
651
+ preloadInstance(instance, type, props) {
652
+ return true
653
+ },
654
+ startSuspendingCommit() {
655
+ return null
656
+ },
657
+ suspendInstance(state, instance, type, props) {},
658
+
659
+ suspendOnActiveViewTransition(state, container) {},
660
+
661
+ waitForCommitToBeReady(state, timeoutOffset) {
662
+ return null
663
+ },
664
+
665
+ getSuspendedCommitReason(state, rootContainer) {
666
+ return null
667
+ },
668
+
669
+ isPrimaryRenderer: false,
670
+ }
671
+
672
+ const Renderer = Reconciler(HostConfig)
673
+ global.React = require('react')
674
+
675
+ function createRootContainer(surfaceId: number) {
676
+ const rootInstance = {
677
+ containerTag: surfaceId,
678
+ publicInstance: null,
679
+ }
680
+
681
+ return Renderer.createContainer(
682
+ rootInstance,
683
+ 0, // concurrentRoot ? 1 : 0
684
+ null,
685
+ false,
686
+ null,
687
+ 'ui-renderer-' + surfaceId,
688
+ function onUncaughtError(error, info) {
689
+ nativeLog(
690
+ '[Error][ReactFabricMirror] Uncaught error in React renderer: ',
691
+ error,
692
+ info
693
+ )
694
+ },
695
+ function onCaughtError(error, info) {
696
+ nativeLog(
697
+ '[Error][ReactFabricMirror] Caught error in React renderer: ',
698
+ error,
699
+ info
700
+ )
701
+ },
702
+ function onRecoverableError(error, info) {
703
+ nativeLog(
704
+ '[Error][ReactFabricMirror] Recoverable error in React renderer: ',
705
+ error,
706
+ info
707
+ )
708
+ },
709
+ function nativeOnDefaultTransitionIndicator() {
710
+ // Native doesn't have a default indicator.
711
+ }
712
+ )
713
+ }
714
+
715
+ function getRootContainer(surfaceId: number) {
716
+ let rootContainer = global.rootContainersBySurfaceId[surfaceId]
717
+ if (rootContainer == null) {
718
+ rootContainer = createRootContainer(surfaceId)
719
+ global.rootContainersBySurfaceId[surfaceId] = rootContainer
720
+ }
721
+
722
+ return rootContainer
723
+ }
724
+
725
+ function reactRender(
726
+ surfaceId: number,
727
+ element: ReactModule.ReactElement,
728
+ callback?: () => void,
729
+ completeRootSync?: (surfaceId: number, childSet: unknown) => void
730
+ ): void {
731
+ const rootContainer = getRootContainer(surfaceId)
732
+ const previousCompleteRootSync = currentCompleteRootSync
733
+ currentCompleteRootSync = completeRootSync ?? null
734
+
735
+ // updateContainerSync + flushSyncWork is making the renderer work immediately/blocking/…sync
736
+ try {
737
+ Renderer.updateContainerSync(element, rootContainer, null, callback)
738
+ // Renderer.flushPassiveEffects();
739
+ Renderer.flushSyncWork()
740
+ } finally {
741
+ currentCompleteRootSync = previousCompleteRootSync
742
+ }
743
+ }
744
+
745
+ function disposeReactRoot(
746
+ surfaceId: number,
747
+ completeRootSync: (surfaceId: number, childSet: unknown) => void
748
+ ): void {
749
+ const rootContainer = global.rootContainersBySurfaceId[surfaceId]
750
+ if (rootContainer == null) {
751
+ return
752
+ }
753
+
754
+ const previousCompleteRootSync = currentCompleteRootSync
755
+ currentCompleteRootSync = completeRootSync
756
+ try {
757
+ Renderer.updateContainerSync(null, rootContainer, null, null)
758
+ Renderer.flushSyncWork()
759
+ delete global.rootContainersBySurfaceId[surfaceId]
760
+ } finally {
761
+ currentCompleteRootSync = previousCompleteRootSync
762
+ }
763
+ }
764
+ nativeLog('[ReactFabricMirror] ReactFabricMirror initialized')
765
+
766
+ export { disposeReactRoot, nativeLog, reactRender }