Skip to content

Commit

Permalink
Add feature flag to use microtasks in the React Native Fabric renderer (
Browse files Browse the repository at this point in the history
#27364)

## Summary

This is part of an effort to align the event loop in React Native with
its behavior on the Web. In this case, we're going to test enabling
microtasks in React Native (Fabric) and we need React to schedule work
using microtasks if available there. This just adds a feature flag to
configure that behavior at runtime.

## How did you test this change?

* Reviewed the generated code, which looks ok.
* Did a manual sync of this PR to Meta's internal infra and tested it
with my changes to enable microtasks in RN/Hermes.

DiffTrain build for commit 54baa79.
  • Loading branch information
rubennorte committed Oct 2, 2023
1 parent 6f57bac commit 5bad9b0
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<3cf0c7070b82c229b406663b7dbae937>>
* @generated SignedSource<<d08221cdf198c30256d8574839ecbf7a>>
*/

'use strict';
Expand Down Expand Up @@ -145,7 +145,7 @@ var createRootStrictEffectsByDefault = false;
var enableLazyContextPropagation = false;
var enableLegacyHidden = false;
var enableAsyncActions = false;
var alwaysThrottleRetries = true; // Flow magic to verify the exports of this file match the original version.
var alwaysThrottleRetries = true;

var FunctionComponent = 0;
var ClassComponent = 1;
Expand Down Expand Up @@ -23997,7 +23997,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-canary-a6ed60a8e-20230929";
var ReactVersion = "18.3.0-canary-54baa7997-20231002";

// Might add PROFILE later.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8623,7 +8623,7 @@ var devToolsConfig$jscomp$inline_1030 = {
throw Error("TestRenderer does not support findFiberByHostInstance()");
},
bundleType: 0,
version: "18.3.0-canary-a6ed60a8e-20230929",
version: "18.3.0-canary-54baa7997-20231002",
rendererPackageName: "react-test-renderer"
};
var internals$jscomp$inline_1229 = {
Expand Down Expand Up @@ -8654,7 +8654,7 @@ var internals$jscomp$inline_1229 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-canary-a6ed60a8e-20230929"
reconcilerVersion: "18.3.0-canary-54baa7997-20231002"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1230 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9049,7 +9049,7 @@ var devToolsConfig$jscomp$inline_1072 = {
throw Error("TestRenderer does not support findFiberByHostInstance()");
},
bundleType: 0,
version: "18.3.0-canary-a6ed60a8e-20230929",
version: "18.3.0-canary-54baa7997-20231002",
rendererPackageName: "react-test-renderer"
};
var internals$jscomp$inline_1270 = {
Expand Down Expand Up @@ -9080,7 +9080,7 @@ var internals$jscomp$inline_1270 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-canary-a6ed60a8e-20230929"
reconcilerVersion: "18.3.0-canary-54baa7997-20231002"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1271 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ if (
}
"use strict";

var ReactVersion = "18.3.0-canary-a6ed60a8e-20230929";
var ReactVersion = "18.3.0-canary-54baa7997-20231002";

// ATTENTION
// When adding new symbols to this file,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -616,4 +616,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactCurrentDispatcher.current.useTransition();
};
exports.version = "18.3.0-canary-a6ed60a8e-20230929";
exports.version = "18.3.0-canary-54baa7997-20231002";
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactCurrentDispatcher.current.useTransition();
};
exports.version = "18.3.0-canary-a6ed60a8e-20230929";
exports.version = "18.3.0-canary-54baa7997-20231002";

/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
if (
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
a6ed60a8eb0626e5f84d0bdbb62c0b61219150d3
54baa7997c7b0bbd456460ead6e051655ea43790
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<86fb5a18e030273bb12b79024c6073c2>>
* @generated SignedSource<<c7798d7e49297e588bffdcccc6aa6cb9>>
*/

'use strict';
Expand Down Expand Up @@ -3178,7 +3178,9 @@ function dispatchEvent(target, topLevelType, nativeEvent) {
var enableUseRefAccessWarning = dynamicFlags.enableUseRefAccessWarning,
enableDeferRootSchedulingToMicrotask =
dynamicFlags.enableDeferRootSchedulingToMicrotask,
alwaysThrottleRetries = dynamicFlags.alwaysThrottleRetries; // The rest of the flags are static for better dead code elimination.
alwaysThrottleRetries = dynamicFlags.alwaysThrottleRetries,
useMicrotasksForSchedulingInFabric =
dynamicFlags.useMicrotasksForSchedulingInFabric; // The rest of the flags are static for better dead code elimination.
var enableSchedulingProfiler = true;
var enableProfilerTimer = true;
var enableProfilerCommitHooks = true;
Expand Down Expand Up @@ -5073,6 +5075,12 @@ function preloadInstance(type, props) {
function waitForCommitToBeReady() {
return null;
}
// Microtasks
// -------------------

var supportsMicrotasks = useMicrotasksForSchedulingInFabric;
var scheduleMicrotask =
typeof queueMicrotask === "function" ? queueMicrotask : scheduleTimeout;

// This is ok in DOM because they types are interchangeable, but in React Native
// they aren't.
Expand Down Expand Up @@ -10097,7 +10105,28 @@ function scheduleImmediateTask(cb) {
} // TODO: Can we land supportsMicrotasks? Which environments don't support it?
// Alternatively, can we move this check to the host config?

{
if (supportsMicrotasks) {
scheduleMicrotask(function () {
// In Safari, appending an iframe forces microtasks to run.
// https://github.com/facebook/react/issues/22459
// We don't support running callbacks in the middle of render
// or commit so we need to check against that.
var executionContext = getExecutionContext();

if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
// Note that this would still prematurely flush the callbacks
// if this happens outside render or commit phase (e.g. in an event).
// Intentionally using a macrotask instead of a microtask here. This is
// wrong semantically but it prevents an infinite loop. The bug is
// Safari's, not ours, so we just do our best to not crash even though
// the behavior isn't completely correct.
scheduleCallback$2(ImmediatePriority, cb);
return;
}

cb();
});
} else {
// If microtasks are not supported, use Scheduler.
scheduleCallback$2(ImmediatePriority, cb);
}
Expand Down Expand Up @@ -27034,7 +27063,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-canary-84876954";
var ReactVersion = "18.3.0-canary-4227b2ef";

function createPortal$1(
children,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<c369fd4070037f1dc7d616d80d10dcfd>>
* @generated SignedSource<<35a02eea4da4b468c9397d48533b560b>>
*/

"use strict";
require("react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore");
var ReactNativePrivateInterface = require("react-native/Libraries/ReactPrivate/ReactNativePrivateInterface"),
React = require("react"),
dynamicFlags = require("ReactNativeInternalFeatureFlags"),
React = require("react"),
Scheduler = require("scheduler");
function invokeGuardedCallbackImpl(name, func, context) {
var funcArgs = Array.prototype.slice.call(arguments, 3);
Expand Down Expand Up @@ -1318,6 +1318,8 @@ var enableUseRefAccessWarning = dynamicFlags.enableUseRefAccessWarning,
enableDeferRootSchedulingToMicrotask =
dynamicFlags.enableDeferRootSchedulingToMicrotask,
alwaysThrottleRetries = dynamicFlags.alwaysThrottleRetries,
useMicrotasksForSchedulingInFabric =
dynamicFlags.useMicrotasksForSchedulingInFabric,
scheduleCallback$2 = Scheduler.unstable_scheduleCallback,
cancelCallback$1 = Scheduler.unstable_cancelCallback,
shouldYield = Scheduler.unstable_shouldYield,
Expand Down Expand Up @@ -1627,6 +1629,8 @@ function cloneHiddenInstance(instance) {
canonical: instance.canonical
};
}
var scheduleMicrotask =
"function" === typeof queueMicrotask ? queueMicrotask : scheduleTimeout;
function getInstanceFromNode(node) {
return null != node.canonical && null != node.canonical.internalInstanceHandle
? node.canonical.internalInstanceHandle
Expand Down Expand Up @@ -3361,7 +3365,7 @@ function ensureRootIsScheduled(root) {
mightHavePendingSyncWork = !0;
didScheduleMicrotask ||
((didScheduleMicrotask = !0),
scheduleCallback$2(ImmediatePriority, processRootScheduleInMicrotask));
scheduleImmediateTask(processRootScheduleInMicrotask));
enableDeferRootSchedulingToMicrotask ||
scheduleTaskForRootDuringMicrotask(root, now());
}
Expand Down Expand Up @@ -3446,8 +3450,7 @@ function flushSyncWorkAcrossRoots_impl(onlyLegacy) {
if ("function" === typeof AggregateError)
throw new AggregateError(errors);
for (onlyLegacy = 1; onlyLegacy < errors.length; onlyLegacy++)
(didPerformSomeWork = throwError.bind(null, errors[onlyLegacy])),
scheduleCallback$2(ImmediatePriority, didPerformSomeWork);
scheduleImmediateTask(throwError.bind(null, errors[onlyLegacy]));
}
throw errors[0];
}
Expand Down Expand Up @@ -3547,6 +3550,15 @@ function scheduleTaskForRootDuringMicrotask(root, currentTime) {
root.callbackNode = suspendedLanes;
return currentTime;
}
function scheduleImmediateTask(cb) {
useMicrotasksForSchedulingInFabric
? scheduleMicrotask(function () {
0 !== (executionContext & 6)
? scheduleCallback$2(ImmediatePriority, cb)
: cb();
})
: scheduleCallback$2(ImmediatePriority, cb);
}
var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher,
ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig,
renderLanes$1 = 0,
Expand Down Expand Up @@ -9425,10 +9437,10 @@ batchedUpdatesImpl = function (fn, a) {
}
};
var roots = new Map(),
devToolsConfig$jscomp$inline_1039 = {
devToolsConfig$jscomp$inline_1035 = {
findFiberByHostInstance: getInstanceFromNode,
bundleType: 0,
version: "18.3.0-canary-0ca674fe",
version: "18.3.0-canary-6367a5b9",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForInstance: getInspectorDataForInstance,
Expand All @@ -9444,11 +9456,11 @@ var roots = new Map(),
}.bind(null, findNodeHandle)
}
};
var internals$jscomp$inline_1281 = {
bundleType: devToolsConfig$jscomp$inline_1039.bundleType,
version: devToolsConfig$jscomp$inline_1039.version,
rendererPackageName: devToolsConfig$jscomp$inline_1039.rendererPackageName,
rendererConfig: devToolsConfig$jscomp$inline_1039.rendererConfig,
var internals$jscomp$inline_1277 = {
bundleType: devToolsConfig$jscomp$inline_1035.bundleType,
version: devToolsConfig$jscomp$inline_1035.version,
rendererPackageName: devToolsConfig$jscomp$inline_1035.rendererPackageName,
rendererConfig: devToolsConfig$jscomp$inline_1035.rendererConfig,
overrideHookState: null,
overrideHookStateDeletePath: null,
overrideHookStateRenamePath: null,
Expand All @@ -9464,26 +9476,26 @@ var internals$jscomp$inline_1281 = {
return null === fiber ? null : fiber.stateNode;
},
findFiberByHostInstance:
devToolsConfig$jscomp$inline_1039.findFiberByHostInstance ||
devToolsConfig$jscomp$inline_1035.findFiberByHostInstance ||
emptyFindFiberByHostInstance,
findHostInstancesForRefresh: null,
scheduleRefresh: null,
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-canary-0ca674fe"
reconcilerVersion: "18.3.0-canary-6367a5b9"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1282 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
var hook$jscomp$inline_1278 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
if (
!hook$jscomp$inline_1282.isDisabled &&
hook$jscomp$inline_1282.supportsFiber
!hook$jscomp$inline_1278.isDisabled &&
hook$jscomp$inline_1278.supportsFiber
)
try {
(rendererID = hook$jscomp$inline_1282.inject(
internals$jscomp$inline_1281
(rendererID = hook$jscomp$inline_1278.inject(
internals$jscomp$inline_1277
)),
(injectedHook = hook$jscomp$inline_1282);
(injectedHook = hook$jscomp$inline_1278);
} catch (err) {}
}
exports.createPortal = function (children, containerTag) {
Expand Down
Loading

0 comments on commit 5bad9b0

Please sign in to comment.