Enable RSNRS only on JS thread (#47637)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47637

Changelog: [Internal]

RSNRS does not support off JS thread layout due to current fiber tree corruption when syncing happens on more than one shadow tree at the same time. This diff guarantees that RSNRS will only be enabled on the JS thread, avoiding any state corruption.

Reviewed By: sammy-SC

Differential Revision: D64500893

fbshipit-source-id: aa20f54a0fcfa47534ae099e95307a692bd9fd0f
This commit is contained in:
Nick Lefever 2024-11-20 00:37:21 -08:00 committed by Facebook GitHub Bot
parent 0eff2c5a22
commit 2944752a5d
5 changed files with 23 additions and 1 deletions

View File

@ -20,6 +20,19 @@
namespace facebook::react {
/*
* Runtime shadow node reference updates should only run from one thread at all
* times to avoid having more than one shadow tree updating the current fiber
* tree simultaneously. This thread_local flag allows enabling the updates for
* choses threads.
*/
thread_local bool useRuntimeShadowNodeReferenceUpdateOnThread{false}; // NOLINT
/* static */ void ShadowNode::setUseRuntimeShadowNodeReferenceUpdateOnThread(
bool isEnabled) {
useRuntimeShadowNodeReferenceUpdateOnThread = isEnabled;
}
ShadowNode::SharedListOfShared ShadowNode::emptySharedShadowNodeSharedList() {
static const auto emptySharedShadowNodeSharedList =
std::make_shared<ShadowNode::ListOfShared>();
@ -308,7 +321,8 @@ void ShadowNode::transferRuntimeShadowNodeReference(
void ShadowNode::transferRuntimeShadowNodeReference(
const Shared& destinationShadowNode,
const ShadowNodeFragment& fragment) const {
if (fragment.runtimeShadowNodeReference &&
if (useRuntimeShadowNodeReferenceUpdateOnThread &&
fragment.runtimeShadowNodeReference &&
ReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate()) {
transferRuntimeShadowNodeReference(destinationShadowNode);
}

View File

@ -61,6 +61,8 @@ class ShadowNode : public Sealable,
return ShadowNodeTraits{};
}
static void setUseRuntimeShadowNodeReferenceUpdateOnThread(bool isEnabled);
#pragma mark - Constructors
/*

View File

@ -154,6 +154,8 @@ class ShadowNodeTest : public testing::TestWithParam<bool> {
}
void SetUp() override {
ShadowNode::setUseRuntimeShadowNodeReferenceUpdateOnThread(true);
ReactNativeFeatureFlags::override(
std::make_unique<ShadowNodeTestFeatureFlags>(GetParam()));
}

View File

@ -59,6 +59,8 @@ Pod::Spec.new do |s|
s.dependency "React-utils"
s.dependency "React-featureflags"
add_dependency(s, "React-Fabric")
if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1"
s.dependency "hermes-engine"
else

View File

@ -19,6 +19,7 @@
#include <jsinspector-modern/HostTarget.h>
#include <jsireact/JSIExecutor.h>
#include <react/featureflags/ReactNativeFeatureFlags.h>
#include <react/renderer/core/ShadowNode.h>
#include <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h>
#include <react/utils/jsi-utils.h>
#include <iostream>
@ -92,6 +93,7 @@ ReactInstance::ReactInstance(
jsi::Runtime& jsiRuntime = runtime->getRuntime();
SystraceSection s("ReactInstance::_runtimeExecutor[Callback]");
try {
ShadowNode::setUseRuntimeShadowNodeReferenceUpdateOnThread(true);
callback(jsiRuntime);
// If we have first-class support for microtasks,