diff --git a/packages/react-reconciler/src/ReactFiberScheduler.new.js b/packages/react-reconciler/src/ReactFiberScheduler.new.js index c86bd58ce6a57..26a2e12ed1d90 100644 --- a/packages/react-reconciler/src/ReactFiberScheduler.new.js +++ b/packages/react-reconciler/src/ReactFiberScheduler.new.js @@ -228,12 +228,13 @@ let interruptedBy: Fiber | null = null; // In other words, because expiration times determine how updates are batched, // we want all updates of like priority that occur within the same event to // receive the same expiration time. Otherwise we get tearing. +let initialTimeMs: number = now(); let currentEventTime: ExpirationTime = NoWork; export function requestCurrentTime() { if (workPhase === RenderPhase || workPhase === CommitPhase) { // We're inside React, so it's fine to read the actual time. - return msToExpirationTime(now()); + return msToExpirationTime(now() - initialTimeMs); } // We're not inside React, so we may be in the middle of a browser event. if (currentEventTime !== NoWork) { @@ -241,7 +242,7 @@ export function requestCurrentTime() { return currentEventTime; } // This is the first update since React yielded. Compute a new start time. - currentEventTime = msToExpirationTime(now()); + currentEventTime = msToExpirationTime(now() - initialTimeMs); return currentEventTime; } diff --git a/packages/react-reconciler/src/__tests__/ReactExpiration-test.internal.js b/packages/react-reconciler/src/__tests__/ReactExpiration-test.internal.js index 8001a8d2c96c6..9a9402ecb90d2 100644 --- a/packages/react-reconciler/src/__tests__/ReactExpiration-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactExpiration-test.internal.js @@ -245,4 +245,31 @@ describe('ReactExpiration', () => { '1 [D] [render]', ]); }); + + it('should measure expiration times relative to module initialization', () => { + // Tests an implementation detail where expiration times are computed using + // bitwise operations. + + jest.resetModules(); + Scheduler = require('scheduler'); + // Before importing the renderer, advance the current time by a number + // larger than the maximum allowed for bitwise operations. + const maxSigned31BitInt = 1073741823; + Scheduler.advanceTime(maxSigned31BitInt * 100); + + // Now import the renderer. On module initialization, it will read the + // current time. + ReactNoop = require('react-noop-renderer'); + + ReactNoop.render('Hi'); + + // The update should not have expired yet. + expect(Scheduler).toFlushExpired([]); + expect(ReactNoop).toMatchRenderedOutput(null); + + // Advance the time some more to expire the update. + Scheduler.advanceTime(10000); + expect(Scheduler).toFlushExpired([]); + expect(ReactNoop).toMatchRenderedOutput('Hi'); + }); });