react-native-windows 0.82.0 → 0.82.3

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 (36) hide show
  1. package/Microsoft.ReactNative/Base/CxxReactIncludes.h +11 -0
  2. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +52 -2
  3. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +70 -49
  4. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +4 -1
  5. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/WindowsTextLayoutManager.cpp +7 -2
  6. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +1 -1
  7. package/Microsoft.ReactNative/Pch/pch.h +2 -0
  8. package/Microsoft.ReactNative/ReactHost/CrashManager.cpp +5 -0
  9. package/Microsoft.ReactNative/ReactHost/ReactNativeHeaders.h +1 -0
  10. package/PropertySheets/CIBuildOptimizations.props +29 -0
  11. package/PropertySheets/External/Microsoft.ReactNative.Composition.CppLib.props +10 -0
  12. package/PropertySheets/External/Microsoft.ReactNative.Uwp.CppLib.props +10 -0
  13. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  14. package/README.md +1 -1
  15. package/ReactCommon/ReactCommon.vcxproj +10 -10
  16. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/Instance.cpp +379 -0
  17. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.cpp +47 -0
  18. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSIndexedRAMBundle.cpp +143 -0
  19. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/MethodCall.cpp +98 -0
  20. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/ModuleRegistry.cpp +254 -0
  21. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/NativeToJsBridge.cpp +9 -0
  22. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/RAMBundleRegistry.cpp +91 -0
  23. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/ReactMarker.cpp +147 -0
  24. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsiexecutor/jsireact/JSIExecutor.cpp +622 -0
  25. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsiexecutor/jsireact/JSINativeModules.cpp +121 -0
  26. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/webperformance/NativePerformance.cpp +409 -0
  27. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/BaseViewProps.cpp +628 -0
  28. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/core/EventDispatcher.cpp +79 -0
  29. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/core/EventQueueProcessor.cpp +138 -0
  30. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/uimanager/UIManager.cpp +732 -0
  31. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/ReactInstance.cpp +687 -0
  32. package/Scripts/OfficeReact.Win32.nuspec +0 -11
  33. package/Shared/Networking/WinRTWebSocketResource.cpp +5 -4
  34. package/Shared/Shared.vcxitems +9 -9
  35. package/package.json +1 -1
  36. package/templates/cpp-app/windows/MyApp/MyApp.vcxproj +2 -0
@@ -0,0 +1,687 @@
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
+
8
+ #if _MSC_VER
9
+ #pragma warning(push)
10
+ #pragma warning(disable : 4996) // deprecated APIs
11
+ #endif
12
+ #include "ReactInstance.h"
13
+
14
+ #include <ReactCommon/RuntimeExecutor.h>
15
+ #include <cxxreact/ErrorUtils.h>
16
+ #include <cxxreact/JSBigString.h>
17
+ #include <cxxreact/JSExecutor.h>
18
+ #include <cxxreact/ReactMarker.h>
19
+ #include <cxxreact/TraceSection.h>
20
+ #include <glog/logging.h>
21
+ #include <jsi/JSIDynamic.h>
22
+ #include <jsi/instrumentation.h>
23
+ #include <jsinspector-modern/HostTarget.h>
24
+ #include <jsireact/JSIExecutor.h>
25
+ #include <react/featureflags/ReactNativeFeatureFlags.h>
26
+ #include <react/renderer/core/ShadowNode.h>
27
+ #include <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h>
28
+ #include <react/timing/primitives.h>
29
+ #include <react/utils/jsi-utils.h>
30
+ #include <iostream>
31
+ #include <memory>
32
+ #include <utility>
33
+
34
+ namespace facebook::react {
35
+
36
+ namespace {
37
+
38
+ std::shared_ptr<RuntimeScheduler> createRuntimeScheduler(
39
+ RuntimeExecutor runtimeExecutor,
40
+ RuntimeSchedulerTaskErrorHandler taskErrorHandler) {
41
+ std::shared_ptr<RuntimeScheduler> scheduler =
42
+ std::make_shared<RuntimeScheduler>(
43
+ std::move(runtimeExecutor),
44
+ HighResTimeStamp::now,
45
+ std::move(taskErrorHandler));
46
+ scheduler->setPerformanceEntryReporter(
47
+ // FIXME: Move creation of PerformanceEntryReporter to here and
48
+ // guarantee that its lifetime is the same as the runtime.
49
+ PerformanceEntryReporter::getInstance().get());
50
+
51
+ return scheduler;
52
+ }
53
+
54
+ } // namespace
55
+
56
+ ReactInstance::ReactInstance(
57
+ std::unique_ptr<JSRuntime> runtime,
58
+ std::shared_ptr<MessageQueueThread> jsMessageQueueThread,
59
+ std::shared_ptr<TimerManager> timerManager,
60
+ JsErrorHandler::OnJsError onJsError,
61
+ jsinspector_modern::HostTarget* parentInspectorTarget)
62
+ : runtime_(std::move(runtime)),
63
+ jsMessageQueueThread_(std::move(jsMessageQueueThread)),
64
+ timerManager_(std::move(timerManager)),
65
+ jsErrorHandler_(std::make_shared<JsErrorHandler>(std::move(onJsError))),
66
+ parentInspectorTarget_(parentInspectorTarget) {
67
+ RuntimeExecutor runtimeExecutor =
68
+ [weakRuntime = std::weak_ptr(runtime_),
69
+ weakTimerManager = std::weak_ptr(timerManager_),
70
+ weakJsThread = std::weak_ptr(jsMessageQueueThread_),
71
+ jsErrorHandler = jsErrorHandler_](auto callback) {
72
+ if (weakRuntime.expired()) {
73
+ return;
74
+ }
75
+
76
+ if (auto jsThread = weakJsThread.lock()) {
77
+ jsThread->runOnQueue([jsErrorHandler,
78
+ weakRuntime,
79
+ weakTimerManager,
80
+ callback = std::move(callback)]() {
81
+ auto runtime = weakRuntime.lock();
82
+ if (!runtime) {
83
+ return;
84
+ }
85
+
86
+ jsi::Runtime& jsiRuntime = runtime->getRuntime();
87
+ TraceSection s("ReactInstance::_runtimeExecutor[Callback]");
88
+ try {
89
+ ShadowNode::setUseRuntimeShadowNodeReferenceUpdateOnThread(true);
90
+ callback(jsiRuntime);
91
+ } catch (jsi::JSError& originalError) {
92
+ jsErrorHandler->handleError(jsiRuntime, originalError, true);
93
+ } catch (std::exception& ex) {
94
+ jsi::JSError error(
95
+ jsiRuntime, std::string("Non-js exception: ") + ex.what());
96
+ jsErrorHandler->handleError(jsiRuntime, error, true);
97
+ }
98
+ });
99
+ }
100
+ };
101
+
102
+ if (parentInspectorTarget_ != nullptr) {
103
+ auto executor = parentInspectorTarget_->executorFromThis();
104
+
105
+ auto bufferedRuntimeExecutorThatWaitsForInspectorSetup =
106
+ std::make_shared<BufferedRuntimeExecutor>(runtimeExecutor);
107
+ auto runtimeExecutorThatExecutesAfterInspectorSetup =
108
+ [bufferedRuntimeExecutorThatWaitsForInspectorSetup](
109
+ std::function<void(jsi::Runtime & runtime)>&& callback) {
110
+ bufferedRuntimeExecutorThatWaitsForInspectorSetup->execute(
111
+ std::move(callback));
112
+ };
113
+
114
+ runtimeScheduler_ = createRuntimeScheduler(
115
+ runtimeExecutorThatExecutesAfterInspectorSetup,
116
+ [jsErrorHandler = jsErrorHandler_](
117
+ jsi::Runtime& runtime, jsi::JSError& error) {
118
+ jsErrorHandler->handleError(runtime, error, true);
119
+ });
120
+
121
+ auto runtimeExecutorThatGoesThroughRuntimeScheduler =
122
+ [runtimeScheduler = runtimeScheduler_.get()](
123
+ std::function<void(jsi::Runtime & runtime)>&& callback) {
124
+ runtimeScheduler->scheduleWork(std::move(callback));
125
+ };
126
+
127
+ // This code can execute from any thread, so we need to make sure we set up
128
+ // the inspector logic in the right one. The callback executes immediately
129
+ // if we are already in the right thread.
130
+ executor([this,
131
+ runtimeExecutorThatGoesThroughRuntimeScheduler,
132
+ bufferedRuntimeExecutorThatWaitsForInspectorSetup](
133
+ jsinspector_modern::HostTarget& hostTarget) {
134
+ // Callbacks scheduled through the page target executor are generally
135
+ // not guaranteed to run (e.g.: if the page target is destroyed)
136
+ // but in this case it is because the page target cannot be destroyed
137
+ // before the instance finishes its setup:
138
+ // * On iOS it's because we do the setup synchronously.
139
+ // * On Android it's because we explicitly wait for the instance
140
+ // creation task to finish before starting the destruction.
141
+ inspectorTarget_ = &hostTarget.registerInstance(*this);
142
+ runtimeInspectorTarget_ = &inspectorTarget_->registerRuntime(
143
+ runtime_->getRuntimeTargetDelegate(),
144
+ runtimeExecutorThatGoesThroughRuntimeScheduler);
145
+ bufferedRuntimeExecutorThatWaitsForInspectorSetup->flush();
146
+ });
147
+ } else {
148
+ runtimeScheduler_ = createRuntimeScheduler(
149
+ runtimeExecutor,
150
+ [jsErrorHandler = jsErrorHandler_](
151
+ jsi::Runtime& runtime, jsi::JSError& error) {
152
+ jsErrorHandler->handleError(runtime, error, true);
153
+ });
154
+ }
155
+
156
+ bufferedRuntimeExecutor_ = std::make_shared<BufferedRuntimeExecutor>(
157
+ [runtimeScheduler = runtimeScheduler_.get()](
158
+ std::function<void(jsi::Runtime & runtime)>&& callback) {
159
+ runtimeScheduler->scheduleWork(std::move(callback));
160
+ });
161
+ }
162
+
163
+ void ReactInstance::unregisterFromInspector() {
164
+ if (inspectorTarget_ != nullptr) {
165
+ assert(runtimeInspectorTarget_);
166
+ inspectorTarget_->unregisterRuntime(*runtimeInspectorTarget_);
167
+
168
+ assert(parentInspectorTarget_);
169
+ parentInspectorTarget_->unregisterInstance(*inspectorTarget_);
170
+
171
+ inspectorTarget_ = nullptr;
172
+ }
173
+ }
174
+
175
+ RuntimeExecutor ReactInstance::getUnbufferedRuntimeExecutor() noexcept {
176
+ return [runtimeScheduler = runtimeScheduler_.get()](
177
+ std::function<void(jsi::Runtime & runtime)>&& callback) {
178
+ runtimeScheduler->scheduleWork(std::move(callback));
179
+ };
180
+ }
181
+
182
+ // This BufferedRuntimeExecutor ensures that the main JS bundle finished
183
+ // execution before any JS queued into it from C++ are executed. Use
184
+ // getUnbufferedRuntimeExecutor() instead if you do not need the main JS bundle
185
+ // to have finished. e.g. setting global variables into JS runtime.
186
+ RuntimeExecutor ReactInstance::getBufferedRuntimeExecutor() noexcept {
187
+ return [weakBufferedRuntimeExecutor_ =
188
+ std::weak_ptr<BufferedRuntimeExecutor>(bufferedRuntimeExecutor_)](
189
+ std::function<void(jsi::Runtime & runtime)>&& callback) {
190
+ if (auto strongBufferedRuntimeExecutor_ =
191
+ weakBufferedRuntimeExecutor_.lock()) {
192
+ strongBufferedRuntimeExecutor_->execute(std::move(callback));
193
+ }
194
+ };
195
+ }
196
+
197
+ // TODO(T184010230): Should the RuntimeScheduler returned from this method be
198
+ // buffered?
199
+ std::shared_ptr<RuntimeScheduler>
200
+ ReactInstance::getRuntimeScheduler() noexcept {
201
+ return runtimeScheduler_;
202
+ }
203
+
204
+ namespace {
205
+
206
+ // Copied from JSIExecutor.cpp
207
+ // basename_r isn't in all iOS SDKs, so use this simple version instead.
208
+ std::string simpleBasename(const std::string& path) {
209
+ size_t pos = path.rfind('/');
210
+ return (pos != std::string::npos) ? path.substr(pos) : path;
211
+ }
212
+
213
+ } // namespace
214
+
215
+ /**
216
+ * Load the JS bundle and flush buffered JS calls, future JS calls won't be
217
+ * buffered after calling this.
218
+ * Note that this method is asynchronous. However, a completion callback
219
+ * isn't needed because all calls into JS should be dispatched to the JSThread,
220
+ * preferably via the runtimeExecutor_.
221
+ */
222
+ void ReactInstance::loadScript(
223
+ std::unique_ptr<const JSBigString> script,
224
+ const std::string& sourceURL,
225
+ std::function<void(jsi::Runtime& runtime)>&& beforeLoad,
226
+ std::function<void(jsi::Runtime& runtime)>&& afterLoad) {
227
+ auto buffer = std::make_shared<BigStringBuffer>(std::move(script));
228
+ std::string scriptName = simpleBasename(sourceURL);
229
+
230
+ runtimeScheduler_->scheduleWork([this,
231
+ scriptName,
232
+ sourceURL,
233
+ buffer = std::move(buffer),
234
+ weakBufferedRuntimeExecuter =
235
+ std::weak_ptr<BufferedRuntimeExecutor>(
236
+ bufferedRuntimeExecutor_),
237
+ beforeLoad,
238
+ afterLoad](jsi::Runtime& runtime) {
239
+ if (beforeLoad) {
240
+ beforeLoad(runtime);
241
+ }
242
+ TraceSection s("ReactInstance::loadScript");
243
+ bool hasLogger(ReactMarker::logTaggedMarkerBridgelessImpl != nullptr);
244
+ if (hasLogger) {
245
+ ReactMarker::logTaggedMarkerBridgeless(
246
+ ReactMarker::RUN_JS_BUNDLE_START, scriptName.c_str());
247
+ }
248
+
249
+ runtime.evaluateJavaScript(buffer, sourceURL);
250
+
251
+ /**
252
+ * TODO(T183610671): We need a safe/reliable way to enable the js
253
+ * pipeline from javascript. Remove this after we figure that out, or
254
+ * after we just remove the js pipeline.
255
+ */
256
+ if (!jsErrorHandler_->hasHandledFatalError()) {
257
+ jsErrorHandler_->setRuntimeReady();
258
+ }
259
+
260
+ if (hasLogger) {
261
+ ReactMarker::logTaggedMarkerBridgeless(
262
+ ReactMarker::RUN_JS_BUNDLE_STOP, scriptName.c_str());
263
+ ReactMarker::logMarkerBridgeless(ReactMarker::INIT_REACT_RUNTIME_STOP);
264
+ ReactMarker::logMarkerBridgeless(ReactMarker::APP_STARTUP_STOP);
265
+ }
266
+ if (auto strongBufferedRuntimeExecuter =
267
+ weakBufferedRuntimeExecuter.lock()) {
268
+ strongBufferedRuntimeExecuter->flush();
269
+ }
270
+ if (afterLoad) {
271
+ afterLoad(runtime);
272
+ }
273
+ });
274
+ }
275
+
276
+ /*
277
+ * Calls a method on a JS module that has been registered with
278
+ * `registerCallableModule`. Used to invoke a JS function from platform code.
279
+ */
280
+ void ReactInstance::callFunctionOnModule(
281
+ const std::string& moduleName,
282
+ const std::string& methodName,
283
+ folly::dynamic&& args) {
284
+ if (bufferedRuntimeExecutor_ == nullptr) {
285
+ LOG(ERROR)
286
+ << "Calling callFunctionOnModule with null BufferedRuntimeExecutor";
287
+ return;
288
+ }
289
+
290
+ bufferedRuntimeExecutor_->execute([this,
291
+ moduleName = moduleName,
292
+ methodName = methodName,
293
+ args = std::move(args)](
294
+ jsi::Runtime& runtime) {
295
+ TraceSection s(
296
+ "ReactInstance::callFunctionOnModule",
297
+ "moduleName",
298
+ moduleName,
299
+ "methodName",
300
+ methodName);
301
+ auto it = callableModules_.find(moduleName);
302
+ if (it == callableModules_.end()) {
303
+ std::ostringstream knownModules;
304
+ int i = 0;
305
+ for (it = callableModules_.begin(); it != callableModules_.end();
306
+ it++, i++) {
307
+ const char* space = (i > 0 ? ", " : " ");
308
+ knownModules << space << it->first;
309
+ }
310
+ throw jsi::JSError(
311
+ runtime,
312
+ "Failed to call into JavaScript module method " + moduleName + "." +
313
+ methodName +
314
+ "(). Module has not been registered as callable. Registered callable JavaScript modules (n = " +
315
+ std::to_string(callableModules_.size()) +
316
+ "):" + knownModules.str() +
317
+ ". Did you forget to call `registerCallableModule`?");
318
+ }
319
+
320
+ if (std::holds_alternative<jsi::Function>(it->second)) {
321
+ auto module =
322
+ std::get<jsi::Function>(it->second).call(runtime).asObject(runtime);
323
+ it->second = std::move(module);
324
+ }
325
+
326
+ auto& module = std::get<jsi::Object>(it->second);
327
+ auto method = module.getPropertyAsFunction(runtime, methodName.c_str());
328
+
329
+ std::vector<jsi::Value> jsArgs;
330
+ for (auto& arg : args) {
331
+ jsArgs.push_back(jsi::valueFromDynamic(runtime, arg));
332
+ }
333
+ method.callWithThis(
334
+ runtime, module, (const jsi::Value*)jsArgs.data(), jsArgs.size());
335
+ });
336
+ }
337
+
338
+ void ReactInstance::registerSegment(
339
+ uint32_t segmentId,
340
+ const std::string& segmentPath) {
341
+ LOG(WARNING) << "Starting to run ReactInstance::registerSegment with segment "
342
+ << segmentId;
343
+ runtimeScheduler_->scheduleWork([=](jsi::Runtime& runtime) {
344
+ TraceSection s("ReactInstance::registerSegment");
345
+ auto tag = std::to_string(segmentId);
346
+ auto script = JSBigFileString::fromPath(segmentPath);
347
+ if (script->size() == 0) {
348
+ throw std::invalid_argument(
349
+ "Empty segment registered with ID " + tag + " from " + segmentPath);
350
+ }
351
+ auto buffer = std::make_shared<BigStringBuffer>(std::move(script));
352
+
353
+ bool hasLogger(ReactMarker::logTaggedMarkerBridgelessImpl != nullptr);
354
+ if (hasLogger) {
355
+ ReactMarker::logTaggedMarkerBridgeless(
356
+ ReactMarker::REGISTER_JS_SEGMENT_START, tag.c_str());
357
+ }
358
+ LOG(WARNING) << "Starting to evaluate segment " << segmentId
359
+ << " in ReactInstance::registerSegment";
360
+ #pragma clang diagnostic push
361
+ #pragma clang diagnostic ignored "-Wdeprecated-declarations"
362
+ runtime.evaluateJavaScript(
363
+ buffer, JSExecutor::getSyntheticBundlePath(segmentId, segmentPath));
364
+ #pragma clang diagnostic pop
365
+ LOG(WARNING) << "Finished evaluating segment " << segmentId
366
+ << " in ReactInstance::registerSegment";
367
+ if (hasLogger) {
368
+ ReactMarker::logTaggedMarkerBridgeless(
369
+ ReactMarker::REGISTER_JS_SEGMENT_STOP, tag.c_str());
370
+ }
371
+ });
372
+ }
373
+
374
+ namespace {
375
+ void defineReactInstanceFlags(
376
+ jsi::Runtime& runtime,
377
+ const ReactInstance::JSRuntimeFlags& options) noexcept {
378
+ defineReadOnlyGlobal(runtime, "RN$Bridgeless", jsi::Value(true));
379
+
380
+ if (options.isProfiling) {
381
+ defineReadOnlyGlobal(runtime, "__RCTProfileIsProfiling", jsi::Value(true));
382
+ }
383
+
384
+ if (options.runtimeDiagnosticFlags.length() > 0) {
385
+ defineReadOnlyGlobal(
386
+ runtime,
387
+ "RN$DiagnosticFlags",
388
+ jsi::String::createFromUtf8(runtime, options.runtimeDiagnosticFlags));
389
+ }
390
+ }
391
+
392
+ bool isTruthy(jsi::Runtime& runtime, const jsi::Value& value) {
393
+ auto Boolean = runtime.global().getPropertyAsFunction(runtime, "Boolean");
394
+ return Boolean.call(runtime, value).getBool();
395
+ }
396
+
397
+ } // namespace
398
+
399
+ void ReactInstance::initializeRuntime(
400
+ JSRuntimeFlags options,
401
+ BindingsInstallFunc bindingsInstallFunc) noexcept {
402
+ runtimeScheduler_->scheduleWork([this,
403
+ options = std::move(options),
404
+ bindingsInstallFunc =
405
+ std::move(bindingsInstallFunc)](
406
+ jsi::Runtime& runtime) {
407
+ TraceSection s("ReactInstance::initializeRuntime");
408
+
409
+ bindNativePerformanceNow(runtime);
410
+
411
+ RuntimeSchedulerBinding::createAndInstallIfNeeded(
412
+ runtime, runtimeScheduler_);
413
+
414
+ runtime_->unstable_initializeOnJsThread();
415
+
416
+ defineReactInstanceFlags(runtime, options);
417
+
418
+ defineReadOnlyGlobal(
419
+ runtime,
420
+ "RN$useAlwaysAvailableJSErrorHandling",
421
+ jsi::Value(
422
+ ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling()));
423
+
424
+ defineReadOnlyGlobal(
425
+ runtime,
426
+ "RN$isRuntimeReady",
427
+ jsi::Function::createFromHostFunction(
428
+ runtime,
429
+ jsi::PropNameID::forAscii(runtime, "isRuntimeReady"),
430
+ 0,
431
+ [jsErrorHandler = jsErrorHandler_](
432
+ jsi::Runtime& /*runtime*/,
433
+ const jsi::Value& /*unused*/,
434
+ const jsi::Value* /*args*/,
435
+ size_t /*count*/) {
436
+ return jsErrorHandler->isRuntimeReady();
437
+ }));
438
+
439
+ defineReadOnlyGlobal(
440
+ runtime,
441
+ "RN$hasHandledFatalException",
442
+ jsi::Function::createFromHostFunction(
443
+ runtime,
444
+ jsi::PropNameID::forAscii(runtime, "hasHandledFatalException"),
445
+ 0,
446
+ [jsErrorHandler = jsErrorHandler_](
447
+ jsi::Runtime& /*runtime*/,
448
+ const jsi::Value& /*unused*/,
449
+ const jsi::Value* /*args*/,
450
+ size_t /*count*/) {
451
+ return jsErrorHandler->hasHandledFatalError();
452
+ }));
453
+
454
+ defineReadOnlyGlobal(
455
+ runtime,
456
+ "RN$notifyOfFatalException",
457
+ jsi::Function::createFromHostFunction(
458
+ runtime,
459
+ jsi::PropNameID::forAscii(runtime, "notifyOfFatalException"),
460
+ 0,
461
+ [jsErrorHandler = jsErrorHandler_](
462
+ jsi::Runtime& /*runtime*/,
463
+ const jsi::Value& /*unused*/,
464
+ const jsi::Value* /*args*/,
465
+ size_t /*count*/) {
466
+ jsErrorHandler->notifyOfFatalError();
467
+ return jsi::Value::undefined();
468
+ }));
469
+
470
+ defineReadOnlyGlobal(
471
+ runtime,
472
+ "RN$inExceptionHandler",
473
+ jsi::Function::createFromHostFunction(
474
+ runtime,
475
+ jsi::PropNameID::forAscii(runtime, "inExceptionHandler"),
476
+ 0,
477
+ [jsErrorHandler = jsErrorHandler_](
478
+ jsi::Runtime& /*runtime*/,
479
+ const jsi::Value& /*unused*/,
480
+ const jsi::Value* /*args*/,
481
+ size_t /*count*/) {
482
+ return jsErrorHandler->inErrorHandler();
483
+ }));
484
+
485
+ // TODO(T196834299): We should really use a C++ turbomodule for this
486
+ defineReadOnlyGlobal(
487
+ runtime,
488
+ "RN$handleException",
489
+ jsi::Function::createFromHostFunction(
490
+ runtime,
491
+ jsi::PropNameID::forAscii(runtime, "handleException"),
492
+ 3,
493
+ [jsErrorHandler = jsErrorHandler_](
494
+ jsi::Runtime& runtime,
495
+ const jsi::Value& /*unused*/,
496
+ const jsi::Value* args,
497
+ size_t count) {
498
+ if (count < 2) {
499
+ throw jsi::JSError(
500
+ runtime,
501
+ "handleException requires 3 arguments: error, isFatal, logToConsole (optional)");
502
+ }
503
+
504
+ auto isFatal = isTruthy(runtime, args[1]);
505
+
506
+ if (!ReactNativeFeatureFlags::
507
+ useAlwaysAvailableJSErrorHandling()) {
508
+ if (jsErrorHandler->isRuntimeReady()) {
509
+ return jsi::Value(false);
510
+ }
511
+ }
512
+
513
+ auto jsError =
514
+ jsi::JSError(runtime, jsi::Value(runtime, args[0]));
515
+
516
+ if (count == 2) {
517
+ jsErrorHandler->handleError(runtime, jsError, isFatal);
518
+ } else {
519
+ auto logToConsole = isTruthy(runtime, args[2]);
520
+ jsErrorHandler->handleError(
521
+ runtime, jsError, isFatal, logToConsole);
522
+ }
523
+
524
+ return jsi::Value(true);
525
+ }));
526
+
527
+ defineReadOnlyGlobal(
528
+ runtime,
529
+ "RN$registerExceptionListener",
530
+ jsi::Function::createFromHostFunction(
531
+ runtime,
532
+ jsi::PropNameID::forAscii(runtime, "registerExceptionListener"),
533
+ 1,
534
+ [errorListeners = std::vector<std::shared_ptr<jsi::Function>>(),
535
+ jsErrorHandler = jsErrorHandler_](
536
+ jsi::Runtime& runtime,
537
+ const jsi::Value& /*unused*/,
538
+ const jsi::Value* args,
539
+ size_t count) mutable {
540
+ if (count < 1) {
541
+ throw jsi::JSError(
542
+ runtime,
543
+ "registerExceptionListener: requires 1 argument: fn");
544
+ }
545
+
546
+ if (!args[0].isObject() ||
547
+ !args[0].getObject(runtime).isFunction(runtime)) {
548
+ throw jsi::JSError(
549
+ runtime,
550
+ "registerExceptionListener: The first argument must be a function");
551
+ }
552
+
553
+ auto errorListener = std::make_shared<jsi::Function>(
554
+ args[0].getObject(runtime).getFunction(runtime));
555
+ errorListeners.emplace_back(errorListener);
556
+
557
+ jsErrorHandler->registerErrorListener(
558
+ [weakErrorListener = std::weak_ptr<jsi::Function>(
559
+ errorListener)](jsi::Runtime& runtime, jsi::Value data) {
560
+ if (auto strongErrorListener = weakErrorListener.lock()) {
561
+ strongErrorListener->call(runtime, data);
562
+ }
563
+ });
564
+
565
+ return jsi::Value::undefined();
566
+ }));
567
+
568
+ defineReadOnlyGlobal(
569
+ runtime,
570
+ "RN$registerCallableModule",
571
+ jsi::Function::createFromHostFunction(
572
+ runtime,
573
+ jsi::PropNameID::forAscii(runtime, "registerCallableModule"),
574
+ 2,
575
+ [this](
576
+ jsi::Runtime& runtime,
577
+ const jsi::Value& /*unused*/,
578
+ const jsi::Value* args,
579
+ size_t count) {
580
+ if (count != 2) {
581
+ throw jsi::JSError(
582
+ runtime,
583
+ "registerCallableModule requires exactly 2 arguments");
584
+ }
585
+ if (!args[0].isString()) {
586
+ throw jsi::JSError(
587
+ runtime,
588
+ "The first argument to registerCallableModule must be a string (the name of the JS module).");
589
+ }
590
+ auto name = args[0].asString(runtime).utf8(runtime);
591
+ if (!args[1].isObject() ||
592
+ !args[1].getObject(runtime).isFunction(runtime)) {
593
+ throw jsi::JSError(
594
+ runtime,
595
+ "The second argument to registerCallableModule must be a function that returns the JS module.");
596
+ }
597
+ callableModules_.emplace(
598
+ std::move(name),
599
+ args[1].getObject(runtime).getFunction(runtime));
600
+ return jsi::Value::undefined();
601
+ }));
602
+
603
+ timerManager_->attachGlobals(runtime);
604
+
605
+ bindingsInstallFunc(runtime);
606
+ });
607
+ }
608
+
609
+ void ReactInstance::handleMemoryPressureJs(int pressureLevel) {
610
+ // The level is an enum value passed by the Android OS to an onTrimMemory
611
+ // event callback. Defined in ComponentCallbacks2.
612
+ enum AndroidMemoryPressure {
613
+ TRIM_MEMORY_BACKGROUND = 40,
614
+ TRIM_MEMORY_COMPLETE = 80,
615
+ TRIM_MEMORY_MODERATE = 60,
616
+ TRIM_MEMORY_RUNNING_CRITICAL = 15,
617
+ TRIM_MEMORY_RUNNING_LOW = 10,
618
+ TRIM_MEMORY_RUNNING_MODERATE = 5,
619
+ TRIM_MEMORY_UI_HIDDEN = 20,
620
+ };
621
+ const char* levelName = nullptr;
622
+ switch (pressureLevel) {
623
+ case TRIM_MEMORY_BACKGROUND:
624
+ levelName = "TRIM_MEMORY_BACKGROUND";
625
+ break;
626
+ case TRIM_MEMORY_COMPLETE:
627
+ levelName = "TRIM_MEMORY_COMPLETE";
628
+ break;
629
+ case TRIM_MEMORY_MODERATE:
630
+ levelName = "TRIM_MEMORY_MODERATE";
631
+ break;
632
+ case TRIM_MEMORY_RUNNING_CRITICAL:
633
+ levelName = "TRIM_MEMORY_RUNNING_CRITICAL";
634
+ break;
635
+ case TRIM_MEMORY_RUNNING_LOW:
636
+ levelName = "TRIM_MEMORY_RUNNING_LOW";
637
+ break;
638
+ case TRIM_MEMORY_RUNNING_MODERATE:
639
+ levelName = "TRIM_MEMORY_RUNNING_MODERATE";
640
+ break;
641
+ case TRIM_MEMORY_UI_HIDDEN:
642
+ levelName = "TRIM_MEMORY_UI_HIDDEN";
643
+ break;
644
+ default:
645
+ levelName = "UNKNOWN";
646
+ break;
647
+ }
648
+
649
+ switch (pressureLevel) {
650
+ case TRIM_MEMORY_RUNNING_LOW:
651
+ case TRIM_MEMORY_RUNNING_MODERATE:
652
+ case TRIM_MEMORY_UI_HIDDEN:
653
+ // For non-severe memory trims, do nothing.
654
+ LOG(INFO) << "Memory warning (pressure level: " << levelName
655
+ << ") received by JS VM, ignoring because it's non-severe";
656
+ break;
657
+ case TRIM_MEMORY_BACKGROUND:
658
+ case TRIM_MEMORY_COMPLETE:
659
+ case TRIM_MEMORY_MODERATE:
660
+ case TRIM_MEMORY_RUNNING_CRITICAL:
661
+ // For now, pressureLevel is unused by collectGarbage.
662
+ // This may change in the future if the JS GC has different styles of
663
+ // collections.
664
+ LOG(INFO) << "Memory warning (pressure level: " << levelName
665
+ << ") received by JS VM, running a GC";
666
+ runtimeScheduler_->scheduleWork([=](jsi::Runtime& runtime) {
667
+ TraceSection s("ReactInstance::handleMemoryPressure");
668
+ runtime.instrumentation().collectGarbage(levelName);
669
+ });
670
+ break;
671
+ default:
672
+ // Use the raw number instead of the name here since the name is
673
+ // meaningless.
674
+ LOG(WARNING) << "Memory warning (pressure level: " << pressureLevel
675
+ << ") received by JS VM, unrecognized pressure level";
676
+ break;
677
+ }
678
+ }
679
+
680
+ void* ReactInstance::getJavaScriptContext() {
681
+ return &runtime_->getRuntime();
682
+ }
683
+
684
+ } // namespace facebook::react
685
+ #if _MSC_VER
686
+ #pragma warning(pop)
687
+ #endif