mirror of
https://github.com/facebook/react-native.git
synced 2024-11-21 12:39:27 +00:00
RN: Feature Flag to Disable InteractionManager
in Batchinator
(#47690)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/47690 Creates a feature flag to evalute the impact of disabling `InteractionManager` in `Batchinator` and synchronously invoking callbacks after the timeout. This also deletes the `dispose` arguments in `Batchinator` that were unused. Changelog: [Internal] Reviewed By: bvanderhoof Differential Revision: D66139643 fbshipit-source-id: d17bab0cd25c0c69779686cb435c063f707255e4
This commit is contained in:
parent
fbe4c0ed34
commit
29a0d7c3b2
@ -468,6 +468,15 @@ const definitions: FeatureFlagDefinitions = {
|
||||
purpose: 'experimentation',
|
||||
},
|
||||
},
|
||||
disableInteractionManagerInBatchinator: {
|
||||
defaultValue: false,
|
||||
metadata: {
|
||||
dateAdded: '2024-11-18',
|
||||
description:
|
||||
'Skips InteractionManager in `Batchinator` and invokes callbacks synchronously.',
|
||||
purpose: 'experimentation',
|
||||
},
|
||||
},
|
||||
enableAccessToHostTreeInFabric: {
|
||||
defaultValue: false,
|
||||
metadata: {
|
||||
|
@ -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<<8334fdc6d34d4a090eb8be73f92ccd0f>>
|
||||
* @generated SignedSource<<d7715d63338e96f5842026458a3b69c8>>
|
||||
* @flow strict
|
||||
*/
|
||||
|
||||
@ -31,6 +31,7 @@ export type ReactNativeFeatureFlagsJsOnly = {
|
||||
animatedShouldDebounceQueueFlush: Getter<boolean>,
|
||||
animatedShouldUseSingleOp: Getter<boolean>,
|
||||
disableInteractionManager: Getter<boolean>,
|
||||
disableInteractionManagerInBatchinator: Getter<boolean>,
|
||||
enableAccessToHostTreeInFabric: Getter<boolean>,
|
||||
enableAnimatedAllowlist: Getter<boolean>,
|
||||
enableAnimatedClearImmediateFix: Getter<boolean>,
|
||||
@ -119,6 +120,11 @@ export const animatedShouldUseSingleOp: Getter<boolean> = createJavaScriptFlagGe
|
||||
*/
|
||||
export const disableInteractionManager: Getter<boolean> = createJavaScriptFlagGetter('disableInteractionManager', false);
|
||||
|
||||
/**
|
||||
* Skips InteractionManager in `Batchinator` and invokes callbacks synchronously.
|
||||
*/
|
||||
export const disableInteractionManagerInBatchinator: Getter<boolean> = createJavaScriptFlagGetter('disableInteractionManagerInBatchinator', false);
|
||||
|
||||
/**
|
||||
* Enables access to the host tree in Fabric using DOM-compatible APIs.
|
||||
*/
|
||||
|
@ -4,13 +4,12 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {InteractionManager} = require('react-native');
|
||||
import {InteractionManager} from 'react-native';
|
||||
import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
|
||||
|
||||
/**
|
||||
* A simple class for batching up invocations of a low-pri callback. A timeout is set to run the
|
||||
@ -38,37 +37,47 @@ class Batchinator {
|
||||
_callback: () => void;
|
||||
_delay: number;
|
||||
_taskHandle: ?{cancel: () => void, ...};
|
||||
constructor(callback: () => void, delayMS: number) {
|
||||
this._delay = delayMS;
|
||||
|
||||
constructor(callback: () => void, delay: number) {
|
||||
this._delay = delay;
|
||||
this._callback = callback;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup any pending tasks.
|
||||
*
|
||||
* By default, if there is a pending task the callback is run immediately. Set the option abort to
|
||||
* true to not call the callback if it was pending.
|
||||
*/
|
||||
dispose(options: {abort: boolean, ...} = {abort: false}) {
|
||||
dispose(): void {
|
||||
if (this._taskHandle) {
|
||||
this._taskHandle.cancel();
|
||||
if (!options.abort) {
|
||||
this._callback();
|
||||
}
|
||||
this._taskHandle = null;
|
||||
}
|
||||
}
|
||||
schedule() {
|
||||
|
||||
schedule(): void {
|
||||
if (this._taskHandle) {
|
||||
return;
|
||||
}
|
||||
const timeoutHandle = setTimeout(() => {
|
||||
this._taskHandle = InteractionManager.runAfterInteractions(() => {
|
||||
// Note that we clear the handle before invoking the callback so that if the callback calls
|
||||
// schedule again, it will actually schedule another task.
|
||||
this._taskHandle = null;
|
||||
this._callback();
|
||||
});
|
||||
}, this._delay);
|
||||
const invokeCallback = () => {
|
||||
// Note that we clear the handle before invoking the callback so that if the callback calls
|
||||
// schedule again, it will actually schedule another task.
|
||||
this._taskHandle = null;
|
||||
this._callback();
|
||||
};
|
||||
|
||||
const timeoutHandle = setTimeout(
|
||||
// NOTE: When shipping this, delete `Batchinator` instead of only these
|
||||
// lines of code. Without `InteractionManager`, it's just a `setTimeout`.
|
||||
ReactNativeFeatureFlags.disableInteractionManagerInBatchinator()
|
||||
? invokeCallback
|
||||
: () => {
|
||||
this._taskHandle =
|
||||
InteractionManager.runAfterInteractions(invokeCallback);
|
||||
},
|
||||
this._delay,
|
||||
);
|
||||
this._taskHandle = {cancel: () => clearTimeout(timeoutHandle)};
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
function expectToBeCalledOnce(fn) {
|
||||
expect(fn.mock.calls.length).toBe(1);
|
||||
}
|
||||
|
||||
describe('Batchinator', () => {
|
||||
const Batchinator = require('../Batchinator');
|
||||
|
||||
@ -22,7 +18,7 @@ describe('Batchinator', () => {
|
||||
const batcher = new Batchinator(callback, 10000);
|
||||
batcher.schedule();
|
||||
jest.runAllTimers();
|
||||
expectToBeCalledOnce(callback);
|
||||
expect(callback).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('batches up tasks', () => {
|
||||
@ -32,20 +28,20 @@ describe('Batchinator', () => {
|
||||
batcher.schedule();
|
||||
batcher.schedule();
|
||||
batcher.schedule();
|
||||
expect(callback).not.toBeCalled();
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
jest.runAllTimers();
|
||||
expectToBeCalledOnce(callback);
|
||||
expect(callback).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('flushes on dispose', () => {
|
||||
it('does nothing after dispose', () => {
|
||||
const callback = jest.fn();
|
||||
const batcher = new Batchinator(callback, 10000);
|
||||
batcher.schedule();
|
||||
batcher.schedule();
|
||||
batcher.dispose();
|
||||
expectToBeCalledOnce(callback);
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
jest.runAllTimers();
|
||||
expectToBeCalledOnce(callback);
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call tasks scheduled by the callback', () => {
|
||||
@ -69,10 +65,10 @@ describe('Batchinator', () => {
|
||||
batcher.schedule();
|
||||
batcher.schedule();
|
||||
jest.runAllTimers();
|
||||
expectToBeCalledOnce(callback);
|
||||
expect(callback).toHaveBeenCalledTimes(1);
|
||||
jest.runAllTimers();
|
||||
expectToBeCalledOnce(callback);
|
||||
expect(callback).toHaveBeenCalledTimes(1);
|
||||
batcher.dispose();
|
||||
expectToBeCalledOnce(callback);
|
||||
expect(callback).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
@ -687,7 +687,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
||||
if (this._isNestedWithSameOrientation()) {
|
||||
this.context.unregisterAsNestedChild({ref: this});
|
||||
}
|
||||
this._updateCellsToRenderBatcher.dispose({abort: true});
|
||||
this._updateCellsToRenderBatcher.dispose();
|
||||
this._viewabilityTuples.forEach(tuple => {
|
||||
tuple.viewabilityHelper.dispose();
|
||||
});
|
||||
@ -1762,7 +1762,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
||||
this._hiPriInProgress = true;
|
||||
// Don't worry about interactions when scrolling quickly; focus on filling content as fast
|
||||
// as possible.
|
||||
this._updateCellsToRenderBatcher.dispose({abort: true});
|
||||
this._updateCellsToRenderBatcher.dispose();
|
||||
this._updateCellsToRender();
|
||||
return;
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user