From f2d264192fe2636a0a0f464b0a540dfc189025b3 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Thu, 9 Jul 2026 05:50:40 -0700 Subject: [PATCH] Move shadow-node ref update thread tag to Fabric install Summary: The runtime shadow-node reference update thread tag was being set on every `RuntimeExecutor` tick in `ReactInstance`. Because the underlying flag is `thread_local` and only meaningful on the JS runtime thread, it's enough to set it once during Fabric installation. Move the `ShadowNode::setUseRuntimeShadowNodeReferenceUpdateOnThread` call into `UIManagerBinding::createAndInstallIfNeeded`, which runs on the JS thread and is guarded to execute once per runtime. This lets the `runtime` module drop its direct dependency on `renderer/core`, reducing coupling between the Bridgeless runtime host and the Fabric renderer. Behavior is unchanged: the write was already unconditional; the read at `updateMountedFlag` is still gated by the existing feature flag. Changelog: [Internal] Reviewed By: lenaic, zeyap Differential Revision: D111059967 --- .../react/renderer/uimanager/UIManagerBinding.cpp | 7 +++++++ .../ReactCommon/react/runtime/ReactInstance.cpp | 2 -- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp index c79fc75df5b4..ed1c62d97394 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,12 @@ void UIManagerBinding::createAndInstallIfNeeded( auto object = jsi::Object::createFromHostObject(runtime, uiManagerBinding); runtime.global().setProperty( runtime, uiManagerModuleName, std::move(object)); + + // Tag this thread (the JS runtime thread) as the one allowed to propagate + // runtime shadow-node reference updates during Fabric commit. The flag is + // thread_local, so it must be set on the JS thread; installing the binding + // is guaranteed to run there and to happen before any JS-driven commit. + ShadowNode::setUseRuntimeShadowNodeReferenceUpdateOnThread(true); } } diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index 4d12c90edfb3..e6b8f129d5f4 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -98,7 +97,6 @@ ReactInstance::ReactInstance( jsi::Runtime& jsiRuntime = runtime->getRuntime(); TraceSection s("ReactInstance::_runtimeExecutor[Callback]"); try { - ShadowNode::setUseRuntimeShadowNodeReferenceUpdateOnThread(true); callback(jsiRuntime); } catch (jsi::JSError& originalError) { jsErrorHandler->handleError(jsiRuntime, originalError, true);