Skip to content

Commit

Permalink
Partially restore feature flag to disable event loop on bridgeless (#…
Browse files Browse the repository at this point in the history
…48892)

Summary:
Pull Request resolved: #48892

Changelog: [internal]

Reviewed By: javache, Abbondanzo

Differential Revision: D68557746

fbshipit-source-id: d94877d03dc6ea2bf6bca45da77a0a769fa0efeb
  • Loading branch information
rubennorte authored and facebook-github-bot committed Jan 23, 2025
1 parent 317f130 commit 8a2b445
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 39 deletions.
91 changes: 56 additions & 35 deletions packages/react-native/Libraries/Core/setUpTimers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

'use strict';

const ReactNativeFeatureFlags = require('../../src/private/featureflags/ReactNativeFeatureFlags');
const NativeReactNativeFeatureFlags =
require('../../src/private/featureflags/specs/NativeReactNativeFeatureFlags').default;
const {polyfillGlobal} = require('../Utilities/PolyfillFunctions');

if (__DEV__) {
Expand All @@ -18,8 +21,45 @@ if (__DEV__) {
}
}

const isEventLoopEnabled = (() => {
if (NativeReactNativeFeatureFlags == null) {
return false;
}

return (
ReactNativeFeatureFlags.enableBridgelessArchitecture() &&
!ReactNativeFeatureFlags.disableEventLoopOnBridgeless()
);
})();

// In bridgeless mode, timers are host functions installed from cpp.
if (global.RN$Bridgeless === true) {
if (global.RN$Bridgeless !== true) {
/**
* Set up timers.
* You can use this module directly, or just require InitializeCore.
*/
const defineLazyTimer = (
name:
| 'cancelAnimationFrame'
| 'cancelIdleCallback'
| 'clearInterval'
| 'clearTimeout'
| 'requestAnimationFrame'
| 'requestIdleCallback'
| 'setInterval'
| 'setTimeout',
) => {
polyfillGlobal(name, () => require('./Timers/JSTimers')[name]);
};
defineLazyTimer('setTimeout');
defineLazyTimer('clearTimeout');
defineLazyTimer('setInterval');
defineLazyTimer('clearInterval');
defineLazyTimer('requestAnimationFrame');
defineLazyTimer('cancelAnimationFrame');
defineLazyTimer('requestIdleCallback');
defineLazyTimer('cancelIdleCallback');
} else if (isEventLoopEnabled) {
polyfillGlobal(
'requestIdleCallback',
() =>
Expand All @@ -33,7 +73,12 @@ if (global.RN$Bridgeless === true) {
require('../../src/private/webapis/idlecallbacks/specs/NativeIdleCallbacks')
.default.cancelIdleCallback,
);
}

// We need to check if the native module is available before accessing the
// feature flag, because otherwise the API would throw an error in the legacy
// architecture in OSS, where the native module isn't available.
if (isEventLoopEnabled) {
// This is the flag that tells React to use `queueMicrotask` to batch state
// updates, instead of using the scheduler to schedule a regular task.
// We use a global variable because we don't currently have any other
Expand All @@ -58,32 +103,6 @@ if (global.RN$Bridgeless === true) {
() => require('./Timers/immediateShim').clearImmediate,
);
} else {
/**
* Set up timers.
* You can use this module directly, or just require InitializeCore.
*/
const defineLazyTimer = (
name:
| 'cancelAnimationFrame'
| 'cancelIdleCallback'
| 'clearInterval'
| 'clearTimeout'
| 'requestAnimationFrame'
| 'requestIdleCallback'
| 'setInterval'
| 'setTimeout',
) => {
polyfillGlobal(name, () => require('./Timers/JSTimers')[name]);
};
defineLazyTimer('setTimeout');
defineLazyTimer('clearTimeout');
defineLazyTimer('setInterval');
defineLazyTimer('clearInterval');
defineLazyTimer('requestAnimationFrame');
defineLazyTimer('cancelAnimationFrame');
defineLazyTimer('requestIdleCallback');
defineLazyTimer('cancelIdleCallback');

// Polyfill it with promise (regardless it's polyfilled or native) otherwise.
polyfillGlobal(
'queueMicrotask',
Expand All @@ -93,12 +112,14 @@ if (global.RN$Bridgeless === true) {
// When promise was polyfilled hence is queued to the RN microtask queue,
// we polyfill the immediate APIs as aliases to the ReactNativeMicrotask APIs.
// Note that in bridgeless mode, immediate APIs are installed from cpp.
polyfillGlobal(
'setImmediate',
() => require('./Timers/JSTimers').queueReactNativeMicrotask,
);
polyfillGlobal(
'clearImmediate',
() => require('./Timers/JSTimers').clearReactNativeMicrotask,
);
if (global.RN$Bridgeless !== true) {
polyfillGlobal(
'setImmediate',
() => require('./Timers/JSTimers').queueReactNativeMicrotask,
);
polyfillGlobal(
'clearImmediate',
() => require('./Timers/JSTimers').clearReactNativeMicrotask,
);
}
}
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<<9e4ac7a270dd74f6978374d8e2c05013>>
* @generated SignedSource<<70ce0689b8452f99877fa46b9f6b6215>>
*/

/**
Expand Down Expand Up @@ -54,6 +54,13 @@ bool NativeReactNativeFeatureFlags::completeReactInstanceCreationOnBgThreadOnAnd
return ReactNativeFeatureFlags::completeReactInstanceCreationOnBgThreadOnAndroid();
}

bool NativeReactNativeFeatureFlags::disableEventLoopOnBridgeless(
jsi::Runtime& /*runtime*/) {
// This flag is configured with `skipNativeAPI: true`.
// TODO(T204838867): Implement support for optional methods in C++ TM codegen and remove the method definition altogether.
return false;
}

bool NativeReactNativeFeatureFlags::disableMountItemReorderingAndroid(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::disableMountItemReorderingAndroid();
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<<c11c50b272b571325ee3947ec53f0050>>
* @generated SignedSource<<3aadd0d890f3dac9fee5bc465d759203>>
*/

/**
Expand Down Expand Up @@ -41,6 +41,8 @@ class NativeReactNativeFeatureFlags

bool completeReactInstanceCreationOnBgThreadOnAndroid(jsi::Runtime& runtime);

bool disableEventLoopOnBridgeless(jsi::Runtime& runtime);

bool disableMountItemReorderingAndroid(jsi::Runtime& runtime);

bool enableAccumulatedUpdatesInRawPropsAndroid(jsi::Runtime& runtime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ const definitions: FeatureFlagDefinitions = {
purpose: 'release',
},
},
disableEventLoopOnBridgeless: {
defaultValue: false,
metadata: {
description:
'The bridgeless architecture enables the event loop by default. This feature flag allows us to force disabling it in specific instances.',
expectedReleaseValue: true,
purpose: 'release',
},
skipNativeAPI: true,
},
disableMountItemReorderingAndroid: {
defaultValue: false,
metadata: {
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<<811a054f0ada56d8cc1ed21c6930fc52>>
* @generated SignedSource<<43c428552b2f180bccddcfe62fc36697>>
* @flow strict
*/

Expand Down Expand Up @@ -49,6 +49,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{
commonTestFlag: Getter<boolean>,
commonTestFlagWithoutNativeImplementation: Getter<boolean>,
completeReactInstanceCreationOnBgThreadOnAndroid: Getter<boolean>,
disableEventLoopOnBridgeless: Getter<boolean>,
disableMountItemReorderingAndroid: Getter<boolean>,
enableAccumulatedUpdatesInRawPropsAndroid: Getter<boolean>,
enableBridgelessArchitecture: Getter<boolean>,
Expand Down Expand Up @@ -172,6 +173,10 @@ export const commonTestFlagWithoutNativeImplementation: Getter<boolean> = create
* Do not wait for a main-thread dispatch to complete init to start executing work on the JS thread on Android
*/
export const completeReactInstanceCreationOnBgThreadOnAndroid: Getter<boolean> = createNativeFlagGetter('completeReactInstanceCreationOnBgThreadOnAndroid', true);
/**
* The bridgeless architecture enables the event loop by default. This feature flag allows us to force disabling it in specific instances.
*/
export const disableEventLoopOnBridgeless: Getter<boolean> = createNativeFlagGetter('disableEventLoopOnBridgeless', false);
/**
* Prevent FabricMountingManager from reordering mountitems, which may lead to invalid state on the UI thread
*/
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<<bcb501bc8f71f02c82a58b898e73d9a0>>
* @generated SignedSource<<2dbeae49bc79bdbbf06c54273b2e2b9b>>
* @flow strict
*/

Expand All @@ -26,6 +26,7 @@ export interface Spec extends TurboModule {
+commonTestFlag?: () => boolean;
+commonTestFlagWithoutNativeImplementation?: () => boolean;
+completeReactInstanceCreationOnBgThreadOnAndroid?: () => boolean;
+disableEventLoopOnBridgeless?: () => boolean;
+disableMountItemReorderingAndroid?: () => boolean;
+enableAccumulatedUpdatesInRawPropsAndroid?: () => boolean;
+enableBridgelessArchitecture?: () => boolean;
Expand Down

0 comments on commit 8a2b445

Please sign in to comment.