react-native 0.84.0-nightly-20251109-b7012ba92 → 0.84.0-nightly-20251112-7dcedf1de
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/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/Text/Text.js +42 -2
- package/React/Base/RCTVersion.m +1 -1
- package/React/FBReactNativeSpec/FBReactNativeSpecJSI.h +16 -0
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +20 -0
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +13 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +21 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +5 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +5 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +23 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +5 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/BackgroundStyleApplicator.kt +1 -1
- package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +29 -1
- package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +7 -1
- package/ReactApple/RCTAnimatedModuleProvider/RCTAnimatedModuleProvider.mm +4 -1
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/ReactCommon/hermes/React-hermes.podspec +1 -0
- package/ReactCommon/jsiexecutor/React-jsiexecutor.podspec +1 -0
- package/ReactCommon/jsinspector-modern/HostAgent.cpp +33 -0
- package/ReactCommon/jsinspector-modern/HostAgent.h +6 -0
- package/ReactCommon/jsinspector-modern/HostTarget.h +5 -0
- package/ReactCommon/jsinspector-modern/InspectorFlags.cpp +6 -0
- package/ReactCommon/jsinspector-modern/InspectorFlags.h +7 -0
- package/ReactCommon/jsinspector-modern/InspectorInterfaces.cpp +37 -0
- package/ReactCommon/jsinspector-modern/InspectorInterfaces.h +12 -1
- package/ReactCommon/jsinspector-modern/TracingAgent.cpp +11 -0
- package/ReactCommon/jsitooling/React-jsitooling.podspec +4 -0
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +9 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +11 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +92 -56
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +6 -2
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +9 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +19 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +3 -1
- package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +11 -1
- package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +5 -1
- package/ReactCommon/react/renderer/components/text/BaseTextProps.cpp +2 -1
- package/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +4 -0
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm +3 -2
- package/package.json +8 -8
- package/scripts/cocoapods/rncore.rb +3 -2
- package/scripts/cocoapods/spm.rb +28 -10
- package/sdks/hermes-engine/hermes-utils.rb +14 -10
- package/sdks/hermes-engine/version.properties +1 -1
- package/src/private/featureflags/ReactNativeFeatureFlags.js +17 -1
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +3 -1
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
|
12
12
|
#include "InspectorFlags.h"
|
|
13
|
+
#include "InspectorInterfaces.h"
|
|
13
14
|
#include "NetworkIOAgent.h"
|
|
14
15
|
#include "SessionState.h"
|
|
15
16
|
#include "TracingAgent.h"
|
|
@@ -145,6 +146,19 @@ class HostAgent::Impl final {
|
|
|
145
146
|
}
|
|
146
147
|
if (InspectorFlags::getInstance().getNetworkInspectionEnabled()) {
|
|
147
148
|
if (req.method == "Network.enable") {
|
|
149
|
+
auto& inspector = getInspectorInstance();
|
|
150
|
+
if (inspector.getSystemState().registeredPagesCount > 1) {
|
|
151
|
+
frontendChannel_(
|
|
152
|
+
cdp::jsonError(
|
|
153
|
+
req.id,
|
|
154
|
+
cdp::ErrorCode::InternalError,
|
|
155
|
+
"The Network domain is unavailable when multiple React Native hosts are registered."));
|
|
156
|
+
return {
|
|
157
|
+
.isFinishedHandlingRequest = true,
|
|
158
|
+
.shouldSendOKResponse = false,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
148
162
|
sessionState_.isNetworkDomainEnabled = true;
|
|
149
163
|
|
|
150
164
|
return {
|
|
@@ -216,6 +230,11 @@ class HostAgent::Impl final {
|
|
|
216
230
|
cdp::jsonNotification(
|
|
217
231
|
"ReactNativeApplication.metadataUpdated",
|
|
218
232
|
createHostMetadataPayload(hostMetadata_)));
|
|
233
|
+
auto& inspector = getInspectorInstance();
|
|
234
|
+
bool isSingleHost = inspector.getSystemState().registeredPagesCount <= 1;
|
|
235
|
+
if (!isSingleHost) {
|
|
236
|
+
emitSystemStateChanged(isSingleHost);
|
|
237
|
+
}
|
|
219
238
|
|
|
220
239
|
auto stashedTraceRecording =
|
|
221
240
|
targetController_.getDelegate()
|
|
@@ -374,6 +393,15 @@ class HostAgent::Impl final {
|
|
|
374
393
|
tracingAgent_.emitExternalTraceRecording(std::move(traceRecording));
|
|
375
394
|
}
|
|
376
395
|
|
|
396
|
+
void emitSystemStateChanged(bool isSingleHost) {
|
|
397
|
+
frontendChannel_(
|
|
398
|
+
cdp::jsonNotification(
|
|
399
|
+
"ReactNativeApplication.systemStateChanged",
|
|
400
|
+
folly::dynamic::object("isSingleHost", isSingleHost)));
|
|
401
|
+
|
|
402
|
+
frontendChannel_(cdp::jsonNotification("Network.disable"));
|
|
403
|
+
}
|
|
404
|
+
|
|
377
405
|
private:
|
|
378
406
|
enum class FuseboxClientType { Unknown, Fusebox, NonFusebox };
|
|
379
407
|
|
|
@@ -480,6 +508,7 @@ class HostAgent::Impl final {
|
|
|
480
508
|
}
|
|
481
509
|
void emitExternalTraceRecording(tracing::TraceRecordingState traceRecording) {
|
|
482
510
|
}
|
|
511
|
+
void emitSystemStateChanged(bool isSingleHost) {}
|
|
483
512
|
};
|
|
484
513
|
|
|
485
514
|
#endif // REACT_NATIVE_DEBUGGER_ENABLED
|
|
@@ -519,6 +548,10 @@ void HostAgent::emitExternalTraceRecording(
|
|
|
519
548
|
impl_->emitExternalTraceRecording(std::move(traceRecording));
|
|
520
549
|
}
|
|
521
550
|
|
|
551
|
+
void HostAgent::emitSystemStateChanged(bool isSingleHost) const {
|
|
552
|
+
impl_->emitSystemStateChanged(isSingleHost);
|
|
553
|
+
}
|
|
554
|
+
|
|
522
555
|
#pragma mark - Tracing
|
|
523
556
|
|
|
524
557
|
HostTracingAgent::HostTracingAgent(tracing::TraceRecordingState& state)
|
|
@@ -79,6 +79,12 @@ class HostAgent final {
|
|
|
79
79
|
*/
|
|
80
80
|
void emitExternalTraceRecording(tracing::TraceRecordingState traceRecording) const;
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Emits a system state changed event when the number of ReactHost instances
|
|
84
|
+
* changes.
|
|
85
|
+
*/
|
|
86
|
+
void emitSystemStateChanged(bool isSingleHost) const;
|
|
87
|
+
|
|
82
88
|
private:
|
|
83
89
|
// We use the private implementation idiom to ensure this class has the same
|
|
84
90
|
// layout regardless of whether REACT_NATIVE_DEBUGGER_ENABLED is defined. The
|
|
@@ -326,6 +326,11 @@ class JSINSPECTOR_EXPORT HostTarget : public EnableExecutorFromThis<HostTarget>
|
|
|
326
326
|
*/
|
|
327
327
|
void emitTraceRecordingForFirstFuseboxClient(tracing::TraceRecordingState traceRecording) const;
|
|
328
328
|
|
|
329
|
+
/**
|
|
330
|
+
* Emits a system state changed event to all active sessions.
|
|
331
|
+
*/
|
|
332
|
+
void emitSystemStateChanged(bool isSingleHost) const;
|
|
333
|
+
|
|
329
334
|
private:
|
|
330
335
|
/**
|
|
331
336
|
* Constructs a new HostTarget.
|
|
@@ -17,6 +17,10 @@ InspectorFlags& InspectorFlags::getInstance() {
|
|
|
17
17
|
return instance;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
bool InspectorFlags::getAssertSingleHostState() const {
|
|
21
|
+
return loadFlagsAndAssertUnchanged().assertSingleHostState;
|
|
22
|
+
}
|
|
23
|
+
|
|
20
24
|
bool InspectorFlags::getFuseboxEnabled() const {
|
|
21
25
|
if (fuseboxDisabledForTest_) {
|
|
22
26
|
return false;
|
|
@@ -48,6 +52,8 @@ void InspectorFlags::dangerouslyDisableFuseboxForTest() {
|
|
|
48
52
|
const InspectorFlags::Values& InspectorFlags::loadFlagsAndAssertUnchanged()
|
|
49
53
|
const {
|
|
50
54
|
InspectorFlags::Values newValues = {
|
|
55
|
+
.assertSingleHostState =
|
|
56
|
+
ReactNativeFeatureFlags::fuseboxAssertSingleHostState(),
|
|
51
57
|
.fuseboxEnabled =
|
|
52
58
|
#if defined(REACT_NATIVE_DEBUGGER_ENABLED)
|
|
53
59
|
true,
|
|
@@ -19,6 +19,12 @@ class InspectorFlags {
|
|
|
19
19
|
public:
|
|
20
20
|
static InspectorFlags &getInstance();
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Flag determining if the inspector backend should strictly assert that only
|
|
24
|
+
* a single host is registered.
|
|
25
|
+
*/
|
|
26
|
+
bool getAssertSingleHostState() const;
|
|
27
|
+
|
|
22
28
|
/**
|
|
23
29
|
* Flag determining if the modern CDP backend should be enabled.
|
|
24
30
|
*/
|
|
@@ -54,6 +60,7 @@ class InspectorFlags {
|
|
|
54
60
|
|
|
55
61
|
private:
|
|
56
62
|
struct Values {
|
|
63
|
+
bool assertSingleHostState;
|
|
57
64
|
bool fuseboxEnabled;
|
|
58
65
|
bool isProfilingBuild;
|
|
59
66
|
bool networkInspectionEnabled;
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
#include "InspectorInterfaces.h"
|
|
9
9
|
|
|
10
|
+
#include "InspectorFlags.h"
|
|
11
|
+
|
|
10
12
|
#include <cassert>
|
|
11
13
|
#include <list>
|
|
12
14
|
#include <mutex>
|
|
@@ -35,6 +37,14 @@ namespace {
|
|
|
35
37
|
|
|
36
38
|
class InspectorImpl : public IInspector {
|
|
37
39
|
public:
|
|
40
|
+
InspectorImpl() {
|
|
41
|
+
systemStateListener_ = std::make_shared<SystemStateListener>(systemState_);
|
|
42
|
+
auto& inspectorFlags = InspectorFlags::getInstance();
|
|
43
|
+
if (inspectorFlags.getAssertSingleHostState()) {
|
|
44
|
+
registerPageStatusListener(systemStateListener_);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
38
48
|
int addPage(
|
|
39
49
|
const std::string& description,
|
|
40
50
|
const std::string& vm,
|
|
@@ -50,7 +60,21 @@ class InspectorImpl : public IInspector {
|
|
|
50
60
|
void registerPageStatusListener(
|
|
51
61
|
std::weak_ptr<IPageStatusListener> listener) override;
|
|
52
62
|
|
|
63
|
+
InspectorSystemState getSystemState() const override;
|
|
64
|
+
|
|
53
65
|
private:
|
|
66
|
+
class SystemStateListener : public IPageStatusListener {
|
|
67
|
+
public:
|
|
68
|
+
explicit SystemStateListener(InspectorSystemState& state) : state_(state) {}
|
|
69
|
+
|
|
70
|
+
void onPageAdded(int /*pageId*/) override {
|
|
71
|
+
state_.registeredPagesCount++;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private:
|
|
75
|
+
InspectorSystemState& state_;
|
|
76
|
+
};
|
|
77
|
+
|
|
54
78
|
class Page {
|
|
55
79
|
public:
|
|
56
80
|
Page(
|
|
@@ -74,6 +98,8 @@ class InspectorImpl : public IInspector {
|
|
|
74
98
|
int nextPageId_{1};
|
|
75
99
|
std::map<int, Page> pages_;
|
|
76
100
|
std::list<std::weak_ptr<IPageStatusListener>> listeners_;
|
|
101
|
+
InspectorSystemState systemState_{0};
|
|
102
|
+
std::shared_ptr<SystemStateListener> systemStateListener_;
|
|
77
103
|
};
|
|
78
104
|
|
|
79
105
|
InspectorImpl::Page::Page(
|
|
@@ -116,6 +142,12 @@ int InspectorImpl::addPage(
|
|
|
116
142
|
pageId,
|
|
117
143
|
Page{pageId, description, vm, std::move(connectFunc), capabilities});
|
|
118
144
|
|
|
145
|
+
for (const auto& listenerWeak : listeners_) {
|
|
146
|
+
if (auto listener = listenerWeak.lock()) {
|
|
147
|
+
listener->onPageAdded(pageId);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
119
151
|
return pageId;
|
|
120
152
|
}
|
|
121
153
|
|
|
@@ -175,6 +207,11 @@ void InspectorImpl::registerPageStatusListener(
|
|
|
175
207
|
}
|
|
176
208
|
listeners_.push_back(listener);
|
|
177
209
|
}
|
|
210
|
+
|
|
211
|
+
InspectorSystemState InspectorImpl::getSystemState() const {
|
|
212
|
+
std::scoped_lock lock(mutex_);
|
|
213
|
+
return systemState_;
|
|
214
|
+
}
|
|
178
215
|
} // namespace
|
|
179
216
|
|
|
180
217
|
IInspector& getInspectorInstance() {
|
|
@@ -51,6 +51,11 @@ struct InspectorPageDescription {
|
|
|
51
51
|
// Alias for backwards compatibility.
|
|
52
52
|
using InspectorPage = InspectorPageDescription;
|
|
53
53
|
|
|
54
|
+
struct InspectorSystemState {
|
|
55
|
+
/** The total count of pages registered during the app lifetime. */
|
|
56
|
+
int registeredPagesCount;
|
|
57
|
+
};
|
|
58
|
+
|
|
54
59
|
/// IRemoteConnection allows the VM to send debugger messages to the client.
|
|
55
60
|
/// IRemoteConnection's methods are safe to call from any thread *if*
|
|
56
61
|
/// InspectorPackagerConnection.cpp is in use.
|
|
@@ -78,7 +83,8 @@ class JSINSPECTOR_EXPORT ILocalConnection : public IDestructible {
|
|
|
78
83
|
class JSINSPECTOR_EXPORT IPageStatusListener : public IDestructible {
|
|
79
84
|
public:
|
|
80
85
|
virtual ~IPageStatusListener() = 0;
|
|
81
|
-
virtual void
|
|
86
|
+
virtual void onPageAdded(int /*pageId*/) {}
|
|
87
|
+
virtual void onPageRemoved(int /*pageId*/) {}
|
|
82
88
|
};
|
|
83
89
|
|
|
84
90
|
/// IInspector tracks debuggable JavaScript targets (pages).
|
|
@@ -127,6 +133,11 @@ class JSINSPECTOR_EXPORT IInspector : public IDestructible {
|
|
|
127
133
|
* when pages are removed.
|
|
128
134
|
*/
|
|
129
135
|
virtual void registerPageStatusListener(std::weak_ptr<IPageStatusListener> listener) = 0;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Get the current \c InspectorSystemState object.
|
|
139
|
+
*/
|
|
140
|
+
virtual InspectorSystemState getSystemState() const = 0;
|
|
130
141
|
};
|
|
131
142
|
|
|
132
143
|
class NotImplementedException : public std::exception {
|
|
@@ -49,6 +49,17 @@ TracingAgent::~TracingAgent() {
|
|
|
49
49
|
|
|
50
50
|
bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
|
|
51
51
|
if (req.method == "Tracing.start") {
|
|
52
|
+
auto& inspector = getInspectorInstance();
|
|
53
|
+
if (inspector.getSystemState().registeredPagesCount > 1) {
|
|
54
|
+
frontendChannel_(
|
|
55
|
+
cdp::jsonError(
|
|
56
|
+
req.id,
|
|
57
|
+
cdp::ErrorCode::InternalError,
|
|
58
|
+
"The Tracing domain is unavailable when multiple React Native hosts are registered."));
|
|
59
|
+
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
52
63
|
if (sessionState_.isDebuggerDomainEnabled) {
|
|
53
64
|
frontendChannel_(
|
|
54
65
|
cdp::jsonError(
|
|
@@ -44,6 +44,10 @@ Pod::Spec.new do |s|
|
|
|
44
44
|
add_dependency(s, "React-jsinspectortracing", :framework_name => 'jsinspector_moderntracing')
|
|
45
45
|
add_dependency(s, "React-utils", :additional_framework_paths => ["react/utils/platform/ios"])
|
|
46
46
|
|
|
47
|
+
if (use_hermes())
|
|
48
|
+
s.dependency "hermes-engine"
|
|
49
|
+
end
|
|
50
|
+
|
|
47
51
|
add_rn_third_party_dependencies(s)
|
|
48
52
|
add_rncore_dependency(s)
|
|
49
53
|
end
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @generated SignedSource<<
|
|
7
|
+
* @generated SignedSource<<c4020a265f61714560e6742482cc05ab>>
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -142,6 +142,10 @@ bool ReactNativeFeatureFlags::enableImagePrefetchingAndroid() {
|
|
|
142
142
|
return getAccessor().enableImagePrefetchingAndroid();
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
bool ReactNativeFeatureFlags::enableImagePrefetchingJNIBatchingAndroid() {
|
|
146
|
+
return getAccessor().enableImagePrefetchingJNIBatchingAndroid();
|
|
147
|
+
}
|
|
148
|
+
|
|
145
149
|
bool ReactNativeFeatureFlags::enableImagePrefetchingOnUiThreadAndroid() {
|
|
146
150
|
return getAccessor().enableImagePrefetchingOnUiThreadAndroid();
|
|
147
151
|
}
|
|
@@ -254,6 +258,10 @@ bool ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact()
|
|
|
254
258
|
return getAccessor().fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
|
255
259
|
}
|
|
256
260
|
|
|
261
|
+
bool ReactNativeFeatureFlags::fuseboxAssertSingleHostState() {
|
|
262
|
+
return getAccessor().fuseboxAssertSingleHostState();
|
|
263
|
+
}
|
|
264
|
+
|
|
257
265
|
bool ReactNativeFeatureFlags::fuseboxEnabledRelease() {
|
|
258
266
|
return getAccessor().fuseboxEnabledRelease();
|
|
259
267
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @generated SignedSource<<
|
|
7
|
+
* @generated SignedSource<<972740252a5ef5f89f739599da789b79>>
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -184,6 +184,11 @@ class ReactNativeFeatureFlags {
|
|
|
184
184
|
*/
|
|
185
185
|
RN_EXPORT static bool enableImagePrefetchingAndroid();
|
|
186
186
|
|
|
187
|
+
/**
|
|
188
|
+
* When enabled, Android will build and initiate image prefetch requests on ImageShadowNode::layout and batch them together in a single JNI call
|
|
189
|
+
*/
|
|
190
|
+
RN_EXPORT static bool enableImagePrefetchingJNIBatchingAndroid();
|
|
191
|
+
|
|
187
192
|
/**
|
|
188
193
|
* When enabled, Android will initiate image prefetch requested on ImageShadowNode::layout on the UI thread
|
|
189
194
|
*/
|
|
@@ -324,6 +329,11 @@ class ReactNativeFeatureFlags {
|
|
|
324
329
|
*/
|
|
325
330
|
RN_EXPORT static bool fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
|
326
331
|
|
|
332
|
+
/**
|
|
333
|
+
* Enable system assertion validating that Fusebox is configured with a single host. When set, the CDP backend will dynamically disable features (Perf and Network) in the event that multiple hosts are registered (undefined behaviour), and broadcast this over `ReactNativeApplication.systemStateChanged`.
|
|
334
|
+
*/
|
|
335
|
+
RN_EXPORT static bool fuseboxAssertSingleHostState();
|
|
336
|
+
|
|
327
337
|
/**
|
|
328
338
|
* Flag determining if the React Native DevTools (Fusebox) CDP backend should be enabled in release builds. This flag is global and should not be changed across React Host lifetimes.
|
|
329
339
|
*/
|