@react-native-oh/react-native-harmony 0.72.96 → 0.72.101

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.
@@ -0,0 +1,366 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ * @format
9
+ */
10
+
11
+ // RNOH patch begin
12
+ import type {RootTag} from 'react-native/Libraries/Types/RootTagTypes';
13
+ import type {IPerformanceLogger} from 'react-native/Libraries/Utilities/createPerformanceLogger';
14
+
15
+ import BatchedBridge from 'react-native/Libraries/BatchedBridge/BatchedBridge';
16
+ import BugReporting from 'react-native/Libraries/BugReporting/BugReporting';
17
+ import createPerformanceLogger from 'react-native/Libraries/Utilities/createPerformanceLogger';
18
+ import infoLog from 'react-native/Libraries/Utilities/infoLog';
19
+ import SceneTracker from 'react-native/Libraries/Utilities/SceneTracker';
20
+ import {coerceDisplayMode} from 'react-native/Libraries/ReactNative/DisplayMode';
21
+ import HeadlessJsTaskError from 'react-native/Libraries/ReactNative/HeadlessJsTaskError';
22
+ import NativeHeadlessJsTaskSupport from 'react-native/Libraries/ReactNative/NativeHeadlessJsTaskSupport';
23
+ import renderApplication from 'react-native/Libraries/ReactNative/renderApplication';
24
+ import {unmountComponentAtNodeAndRemoveContainer} from 'react-native/Libraries/ReactNative/RendererProxy';
25
+ // RNOH patch end
26
+ import invariant from 'invariant';
27
+
28
+ type Task = (taskData: any) => Promise<void>;
29
+ export type TaskProvider = () => Task;
30
+ type TaskCanceller = () => void;
31
+ type TaskCancelProvider = () => TaskCanceller;
32
+
33
+ export type ComponentProvider = () => React$ComponentType<any>;
34
+ export type ComponentProviderInstrumentationHook = (
35
+ component: ComponentProvider,
36
+ scopedPerformanceLogger: IPerformanceLogger,
37
+ ) => React$ComponentType<any>;
38
+ export type AppConfig = {
39
+ appKey: string,
40
+ component?: ComponentProvider,
41
+ run?: Function,
42
+ section?: boolean,
43
+ ...
44
+ };
45
+ export type Runnable = {
46
+ component?: ComponentProvider,
47
+ run: Function,
48
+ ...
49
+ };
50
+ export type Runnables = {[appKey: string]: Runnable, ...};
51
+ export type Registry = {
52
+ sections: Array<string>,
53
+ runnables: Runnables,
54
+ ...
55
+ };
56
+ export type WrapperComponentProvider = (
57
+ appParameters: any,
58
+ ) => React$ComponentType<any>;
59
+
60
+ const runnables: Runnables = {};
61
+ let runCount = 1;
62
+ const sections: Runnables = {};
63
+ const taskProviders: Map<string, TaskProvider> = new Map();
64
+ const taskCancelProviders: Map<string, TaskCancelProvider> = new Map();
65
+ let componentProviderInstrumentationHook: ComponentProviderInstrumentationHook =
66
+ (component: ComponentProvider) => component();
67
+
68
+ let wrapperComponentProvider: ?WrapperComponentProvider;
69
+ let showArchitectureIndicator = false;
70
+
71
+ /**
72
+ * `AppRegistry` is the JavaScript entry point to running all React Native apps.
73
+ *
74
+ * See https://reactnative.dev/docs/appregistry
75
+ */
76
+ const AppRegistry = {
77
+ setWrapperComponentProvider(provider: WrapperComponentProvider) {
78
+ wrapperComponentProvider = provider;
79
+ },
80
+
81
+ enableArchitectureIndicator(enabled: boolean): void {
82
+ showArchitectureIndicator = enabled;
83
+ },
84
+
85
+ registerConfig(config: Array<AppConfig>): void {
86
+ config.forEach(appConfig => {
87
+ if (appConfig.run) {
88
+ AppRegistry.registerRunnable(appConfig.appKey, appConfig.run);
89
+ } else {
90
+ invariant(
91
+ appConfig.component != null,
92
+ 'AppRegistry.registerConfig(...): Every config is expected to set ' +
93
+ 'either `run` or `component`, but `%s` has neither.',
94
+ appConfig.appKey,
95
+ );
96
+ AppRegistry.registerComponent(
97
+ appConfig.appKey,
98
+ appConfig.component,
99
+ appConfig.section,
100
+ );
101
+ }
102
+ });
103
+ },
104
+
105
+ /**
106
+ * Registers an app's root component.
107
+ *
108
+ * See https://reactnative.dev/docs/appregistry#registercomponent
109
+ */
110
+ registerComponent(
111
+ appKey: string,
112
+ componentProvider: ComponentProvider,
113
+ section?: boolean,
114
+ ): string {
115
+ let scopedPerformanceLogger = createPerformanceLogger();
116
+ runnables[appKey] = {
117
+ componentProvider,
118
+ run: (appParameters, displayMode) => {
119
+ const concurrentRootEnabled =
120
+ appParameters.initialProps?.concurrentRoot ||
121
+ appParameters.concurrentRoot;
122
+ renderApplication(
123
+ componentProviderInstrumentationHook(
124
+ componentProvider,
125
+ scopedPerformanceLogger,
126
+ ),
127
+ appParameters.initialProps,
128
+ appParameters.rootTag,
129
+ wrapperComponentProvider && wrapperComponentProvider(appParameters),
130
+ appParameters.fabric,
131
+ showArchitectureIndicator,
132
+ scopedPerformanceLogger,
133
+ appKey === 'LogBox',
134
+ appKey,
135
+ coerceDisplayMode(displayMode),
136
+ concurrentRootEnabled,
137
+ );
138
+ },
139
+ };
140
+ if (section) {
141
+ sections[appKey] = runnables[appKey];
142
+ }
143
+ return appKey;
144
+ },
145
+
146
+ registerRunnable(appKey: string, run: Function): string {
147
+ runnables[appKey] = {run};
148
+ return appKey;
149
+ },
150
+
151
+ registerSection(appKey: string, component: ComponentProvider): void {
152
+ AppRegistry.registerComponent(appKey, component, true);
153
+ },
154
+
155
+ getAppKeys(): Array<string> {
156
+ return Object.keys(runnables);
157
+ },
158
+
159
+ getSectionKeys(): Array<string> {
160
+ return Object.keys(sections);
161
+ },
162
+
163
+ getSections(): Runnables {
164
+ return {
165
+ ...sections,
166
+ };
167
+ },
168
+
169
+ getRunnable(appKey: string): ?Runnable {
170
+ return runnables[appKey];
171
+ },
172
+
173
+ getRegistry(): Registry {
174
+ return {
175
+ sections: AppRegistry.getSectionKeys(),
176
+ runnables: {...runnables},
177
+ };
178
+ },
179
+
180
+ setComponentProviderInstrumentationHook(
181
+ hook: ComponentProviderInstrumentationHook,
182
+ ) {
183
+ componentProviderInstrumentationHook = hook;
184
+ },
185
+
186
+ /**
187
+ * Loads the JavaScript bundle and runs the app.
188
+ *
189
+ * See https://reactnative.dev/docs/appregistry#runapplication
190
+ */
191
+ runApplication(
192
+ appKey: string,
193
+ appParameters: any,
194
+ displayMode?: number,
195
+ ): void {
196
+ // RNOH patch begin
197
+ if (appParameters?.initialProps?.batchToNative !== undefined) {
198
+ global._batch_to_native = appParameters.initialProps.batchToNative;
199
+ } else {
200
+ global._batch_to_native = false;
201
+ }
202
+ // RNOH patch end
203
+ if (appKey !== 'LogBox') {
204
+ const logParams = __DEV__
205
+ ? '" with ' + JSON.stringify(appParameters)
206
+ : '';
207
+ const msg = 'Running "' + appKey + logParams;
208
+ infoLog(msg);
209
+ BugReporting.addSource(
210
+ 'AppRegistry.runApplication' + runCount++,
211
+ () => msg,
212
+ );
213
+ }
214
+ invariant(
215
+ runnables[appKey] && runnables[appKey].run,
216
+ `"${appKey}" has not been registered. This can happen if:\n` +
217
+ '* Metro (the local dev server) is run from the wrong folder. ' +
218
+ 'Check if Metro is running, stop it and restart it in the current project.\n' +
219
+ "* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called.",
220
+ );
221
+
222
+ SceneTracker.setActiveScene({name: appKey});
223
+ runnables[appKey].run(appParameters, displayMode);
224
+ },
225
+
226
+ /**
227
+ * Update initial props for a surface that's already rendered
228
+ */
229
+ setSurfaceProps(
230
+ appKey: string,
231
+ appParameters: any,
232
+ displayMode?: number,
233
+ ): void {
234
+ if (appKey !== 'LogBox') {
235
+ const msg =
236
+ 'Updating props for Surface "' +
237
+ appKey +
238
+ '" with ' +
239
+ JSON.stringify(appParameters);
240
+ infoLog(msg);
241
+ BugReporting.addSource(
242
+ 'AppRegistry.setSurfaceProps' + runCount++,
243
+ () => msg,
244
+ );
245
+ }
246
+ invariant(
247
+ runnables[appKey] && runnables[appKey].run,
248
+ `"${appKey}" has not been registered. This can happen if:\n` +
249
+ '* Metro (the local dev server) is run from the wrong folder. ' +
250
+ 'Check if Metro is running, stop it and restart it in the current project.\n' +
251
+ "* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called.",
252
+ );
253
+
254
+ runnables[appKey].run(appParameters, displayMode);
255
+ },
256
+
257
+ /**
258
+ * Stops an application when a view should be destroyed.
259
+ *
260
+ * See https://reactnative.dev/docs/appregistry#unmountapplicationcomponentatroottag
261
+ */
262
+ unmountApplicationComponentAtRootTag(rootTag: RootTag): void {
263
+ unmountComponentAtNodeAndRemoveContainer(rootTag);
264
+ },
265
+
266
+ /**
267
+ * Register a headless task. A headless task is a bit of code that runs without a UI.
268
+ *
269
+ * See https://reactnative.dev/docs/appregistry#registerheadlesstask
270
+ */
271
+ registerHeadlessTask(taskKey: string, taskProvider: TaskProvider): void {
272
+ // $FlowFixMe[object-this-reference]
273
+ this.registerCancellableHeadlessTask(taskKey, taskProvider, () => () => {
274
+ /* Cancel is no-op */
275
+ });
276
+ },
277
+
278
+ /**
279
+ * Register a cancellable headless task. A headless task is a bit of code that runs without a UI.
280
+ *
281
+ * See https://reactnative.dev/docs/appregistry#registercancellableheadlesstask
282
+ */
283
+ registerCancellableHeadlessTask(
284
+ taskKey: string,
285
+ taskProvider: TaskProvider,
286
+ taskCancelProvider: TaskCancelProvider,
287
+ ): void {
288
+ if (taskProviders.has(taskKey)) {
289
+ console.warn(
290
+ `registerHeadlessTask or registerCancellableHeadlessTask called multiple times for same key '${taskKey}'`,
291
+ );
292
+ }
293
+ taskProviders.set(taskKey, taskProvider);
294
+ taskCancelProviders.set(taskKey, taskCancelProvider);
295
+ },
296
+
297
+ /**
298
+ * Only called from native code. Starts a headless task.
299
+ *
300
+ * See https://reactnative.dev/docs/appregistry#startheadlesstask
301
+ */
302
+ startHeadlessTask(taskId: number, taskKey: string, data: any): void {
303
+ const taskProvider = taskProviders.get(taskKey);
304
+ if (!taskProvider) {
305
+ console.warn(`No task registered for key ${taskKey}`);
306
+ if (NativeHeadlessJsTaskSupport) {
307
+ NativeHeadlessJsTaskSupport.notifyTaskFinished(taskId);
308
+ }
309
+ return;
310
+ }
311
+ taskProvider()(data)
312
+ .then(() => {
313
+ if (NativeHeadlessJsTaskSupport) {
314
+ NativeHeadlessJsTaskSupport.notifyTaskFinished(taskId);
315
+ }
316
+ })
317
+ .catch(reason => {
318
+ console.error(reason);
319
+
320
+ if (
321
+ NativeHeadlessJsTaskSupport &&
322
+ reason instanceof HeadlessJsTaskError
323
+ ) {
324
+ // $FlowFixMe[unused-promise]
325
+ NativeHeadlessJsTaskSupport.notifyTaskRetry(taskId).then(
326
+ retryPosted => {
327
+ if (!retryPosted) {
328
+ NativeHeadlessJsTaskSupport.notifyTaskFinished(taskId);
329
+ }
330
+ },
331
+ );
332
+ }
333
+ });
334
+ },
335
+
336
+ /**
337
+ * Only called from native code. Cancels a headless task.
338
+ *
339
+ * See https://reactnative.dev/docs/appregistry#cancelheadlesstask
340
+ */
341
+ cancelHeadlessTask(taskId: number, taskKey: string): void {
342
+ const taskCancelProvider = taskCancelProviders.get(taskKey);
343
+ if (!taskCancelProvider) {
344
+ throw new Error(`No task canceller registered for key '${taskKey}'`);
345
+ }
346
+ taskCancelProvider()();
347
+ },
348
+ };
349
+
350
+ if (!(global.RN$Bridgeless === true)) {
351
+ BatchedBridge.registerCallableModule('AppRegistry', AppRegistry);
352
+
353
+ AppRegistry.registerComponent('LogBox', () => {
354
+ if (__DEV__) {
355
+ // RNOH patch begin
356
+ return require('react-native/Libraries/LogBox/LogBoxInspectorContainer').default;
357
+ // RNOH patch end
358
+ } else {
359
+ return function NoOp() {
360
+ return null;
361
+ };
362
+ }
363
+ });
364
+ }
365
+
366
+ module.exports = AppRegistry;