Skip to content

Commit

Permalink
synchronise dispatching of view commands through RuntimeScheduler (fa…
Browse files Browse the repository at this point in the history
…cebook#47604)

Summary:
Pull Request resolved: facebook#47604

## Changelog:

[iOS] [Fixed] - Fixed use of view commands from layout effects

Mounting of views is delayed by runtime scheduler to allow React to run layout effects. Execution of view commands must by queued together with mounting of views, otherwise it might be executed before views are mounted. When this happens, view commands are ignored.

So before, if view command was executed from layout effect (or ref function), it would get dispatched to the UI thread as quickly as possible. But mounting of views would be delayed. To fix this, both mounting of views and view commands are put on the same queue inside of RuntimeScheduler.

## What about Android?
Android employs a [retry mechanism](https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java#L211) that was needed for react tag based view commands. In paper, one could send a view command to a react tag which was completely disconnected from whether a view exists or not.

iOS was built with ref commands in mind, so it doesn't have this mechanism.

Fixes: facebook#47576

Reviewed By: javache, cipolleschi

Differential Revision: D65909191

fbshipit-source-id: 9d2a444879bee62a7b8b7d31edde450e18339b89
  • Loading branch information
sammy-SC authored and facebook-github-bot committed Nov 16, 2024
1 parent 38fb83c commit 6f1c2a5
Show file tree
Hide file tree
Showing 20 changed files with 169 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<b2f32b87f4e87ad9588add08dcb9b0c6>>
* @generated SignedSource<<1adfbb1f0b9791d93ea00f39fbce5520>>
*/

/**
Expand Down Expand Up @@ -118,6 +118,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableFabricRendererExclusively(): Boolean = accessor.enableFabricRendererExclusively()

/**
* Synchronise the view command dispatching with mounting of new transaction
*/
@JvmStatic
public fun enableFixForViewCommandRace(): Boolean = accessor.enableFixForViewCommandRace()

/**
* When enabled, the renderer would only fail commits when they propagate state and the last commit that updated state changed before committing.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<2a25e30cbee2548ee5538ecbc4b92fdc>>
* @generated SignedSource<<fb943b9c4c43ac8214a8f368076cbd62>>
*/

/**
Expand Down Expand Up @@ -35,6 +35,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
private var enableFabricLogsCache: Boolean? = null
private var enableFabricRendererCache: Boolean? = null
private var enableFabricRendererExclusivelyCache: Boolean? = null
private var enableFixForViewCommandRaceCache: Boolean? = null
private var enableGranularShadowTreeStateReconciliationCache: Boolean? = null
private var enableIOSViewClipToPaddingBoxCache: Boolean? = null
private var enableLayoutAnimationsOnAndroidCache: Boolean? = null
Expand Down Expand Up @@ -202,6 +203,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
return cached
}

override fun enableFixForViewCommandRace(): Boolean {
var cached = enableFixForViewCommandRaceCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableFixForViewCommandRace()
enableFixForViewCommandRaceCache = cached
}
return cached
}

override fun enableGranularShadowTreeStateReconciliation(): Boolean {
var cached = enableGranularShadowTreeStateReconciliationCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<0656ed5b5317e6caf85605bba62d08d1>>
* @generated SignedSource<<3980c51f97745c20e0fd510f595477dc>>
*/

/**
Expand Down Expand Up @@ -58,6 +58,8 @@ public object ReactNativeFeatureFlagsCxxInterop {

@DoNotStrip @JvmStatic public external fun enableFabricRendererExclusively(): Boolean

@DoNotStrip @JvmStatic public external fun enableFixForViewCommandRace(): Boolean

@DoNotStrip @JvmStatic public external fun enableGranularShadowTreeStateReconciliation(): Boolean

@DoNotStrip @JvmStatic public external fun enableIOSViewClipToPaddingBox(): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<608eece71b01769be0df8731774f9b0a>>
* @generated SignedSource<<f4f263578308798dcf7561918f58e0cc>>
*/

/**
Expand Down Expand Up @@ -53,6 +53,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi

override fun enableFabricRendererExclusively(): Boolean = false

override fun enableFixForViewCommandRace(): Boolean = false

override fun enableGranularShadowTreeStateReconciliation(): Boolean = false

override fun enableIOSViewClipToPaddingBox(): Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<71dcfc3812f442a35ae2c24621c05605>>
* @generated SignedSource<<bd3529c1455508333a45a5852c3213c6>>
*/

/**
Expand Down Expand Up @@ -39,6 +39,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
private var enableFabricLogsCache: Boolean? = null
private var enableFabricRendererCache: Boolean? = null
private var enableFabricRendererExclusivelyCache: Boolean? = null
private var enableFixForViewCommandRaceCache: Boolean? = null
private var enableGranularShadowTreeStateReconciliationCache: Boolean? = null
private var enableIOSViewClipToPaddingBoxCache: Boolean? = null
private var enableLayoutAnimationsOnAndroidCache: Boolean? = null
Expand Down Expand Up @@ -221,6 +222,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
return cached
}

override fun enableFixForViewCommandRace(): Boolean {
var cached = enableFixForViewCommandRaceCache
if (cached == null) {
cached = currentProvider.enableFixForViewCommandRace()
accessedFeatureFlags.add("enableFixForViewCommandRace")
enableFixForViewCommandRaceCache = cached
}
return cached
}

override fun enableGranularShadowTreeStateReconciliation(): Boolean {
var cached = enableGranularShadowTreeStateReconciliationCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<2dd3e32b571ae171bd5621424116188b>>
* @generated SignedSource<<a74e9cdce26b156a74e397fd065618c2>>
*/

/**
Expand Down Expand Up @@ -53,6 +53,8 @@ public interface ReactNativeFeatureFlagsProvider {

@DoNotStrip public fun enableFabricRendererExclusively(): Boolean

@DoNotStrip public fun enableFixForViewCommandRace(): Boolean

@DoNotStrip public fun enableGranularShadowTreeStateReconciliation(): Boolean

@DoNotStrip public fun enableIOSViewClipToPaddingBox(): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<62bd0386265d0fa4bdccab1faf22d25c>>
* @generated SignedSource<<9c1572172189f9f9ded86a9fdb1cb021>>
*/

/**
Expand Down Expand Up @@ -129,6 +129,12 @@ class ReactNativeFeatureFlagsProviderHolder
return method(javaProvider_);
}

bool enableFixForViewCommandRace() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableFixForViewCommandRace");
return method(javaProvider_);
}

bool enableGranularShadowTreeStateReconciliation() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableGranularShadowTreeStateReconciliation");
Expand Down Expand Up @@ -394,6 +400,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableFabricRendererExclusively(
return ReactNativeFeatureFlags::enableFabricRendererExclusively();
}

bool JReactNativeFeatureFlagsCxxInterop::enableFixForViewCommandRace(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableFixForViewCommandRace();
}

bool JReactNativeFeatureFlagsCxxInterop::enableGranularShadowTreeStateReconciliation(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableGranularShadowTreeStateReconciliation();
Expand Down Expand Up @@ -625,6 +636,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"enableFabricRendererExclusively",
JReactNativeFeatureFlagsCxxInterop::enableFabricRendererExclusively),
makeNativeMethod(
"enableFixForViewCommandRace",
JReactNativeFeatureFlagsCxxInterop::enableFixForViewCommandRace),
makeNativeMethod(
"enableGranularShadowTreeStateReconciliation",
JReactNativeFeatureFlagsCxxInterop::enableGranularShadowTreeStateReconciliation),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<00e9f2368ec7745d960e8671b0e58d19>>
* @generated SignedSource<<92fcd7e8c814a6a76ec15c4cd60e00e4>>
*/

/**
Expand Down Expand Up @@ -75,6 +75,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool enableFabricRendererExclusively(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static bool enableFixForViewCommandRace(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static bool enableGranularShadowTreeStateReconciliation(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<e432522acfd785458553aa09806edb83>>
* @generated SignedSource<<93b93588adcd6b45ec748dff7ee18f07>>
*/

/**
Expand Down Expand Up @@ -86,6 +86,10 @@ bool ReactNativeFeatureFlags::enableFabricRendererExclusively() {
return getAccessor().enableFabricRendererExclusively();
}

bool ReactNativeFeatureFlags::enableFixForViewCommandRace() {
return getAccessor().enableFixForViewCommandRace();
}

bool ReactNativeFeatureFlags::enableGranularShadowTreeStateReconciliation() {
return getAccessor().enableGranularShadowTreeStateReconciliation();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<079c1e8cd65a004c1b26f1a2517e9042>>
* @generated SignedSource<<b24144040cb5bd51f9910b81675ba5b2>>
*/

/**
Expand Down Expand Up @@ -114,6 +114,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool enableFabricRendererExclusively();

/**
* Synchronise the view command dispatching with mounting of new transaction
*/
RN_EXPORT static bool enableFixForViewCommandRace();

/**
* When enabled, the renderer would only fail commits when they propagate state and the last commit that updated state changed before committing.
*/
Expand Down
Loading

0 comments on commit 6f1c2a5

Please sign in to comment.