Skip to content

Commit 03476cc

Browse files
Remove legacy RCTTimingModule (#57037)
Summary: ## Changelog: [IOS][Fixed] Remove legacy RCTTimingModule Differential Revision: D107201906
1 parent b0a6386 commit 03476cc

11 files changed

Lines changed: 30 additions & 201 deletions

File tree

packages/react-native/React/Base/RCTBridge+Private.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,6 @@ RCT_EXTERN void RCTRegisterModule(Class);
8484
*/
8585
- (void)start;
8686

87-
/**
88-
* Used by RCTModuleData to register the module for frame updates after it is
89-
* lazily initialized.
90-
*/
91-
- (void)registerModuleForFrameUpdates:(id<RCTBridgeModule>)module withModuleData:(RCTModuleData *)moduleData;
92-
9387
/**
9488
* Dispatch work to a module's queue - this is also supports the fake RCTJSThread
9589
* queue. Exposed for the RCTProfiler

packages/react-native/React/Base/RCTDisplayLink.h

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,13 @@
77

88
#import <Foundation/Foundation.h>
99

10-
@protocol RCTBridgeModule;
11-
@class RCTModuleData;
12-
13-
@protocol RCTDisplayLinkModuleHolder
14-
- (id<RCTBridgeModule>)instance;
15-
- (Class)moduleClass;
16-
- (dispatch_queue_t)methodQueue;
17-
@end
10+
@protocol RCTFrameUpdateObserver;
1811

1912
@interface RCTDisplayLink : NSObject
2013

2114
- (instancetype)init;
2215
- (void)invalidate;
23-
- (void)registerModuleForFrameUpdates:(id<RCTBridgeModule>)module
24-
withModuleHolder:(id<RCTDisplayLinkModuleHolder>)moduleHolder
25-
__attribute__((deprecated(
26-
"registerModuleForFrameUpdates is part of the legacy architecture and will be removed in a future React Native release.")));
16+
- (void)registerTimingForFrameUpdates:(id<RCTFrameUpdateObserver>)module;
2717
- (void)addToRunLoop:(NSRunLoop *)runLoop;
2818

2919
@end

packages/react-native/React/Base/RCTDisplayLink.m

Lines changed: 10 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,15 @@
1111
#import <QuartzCore/CADisplayLink.h>
1212

1313
#import "RCTAssert.h"
14-
#import "RCTBridgeModule.h"
1514
#import "RCTFrameUpdate.h"
16-
#import "RCTModuleData.h"
1715
#import "RCTProfile.h"
1816

1917
#define RCTAssertRunLoop() \
2018
RCTAssert(_runLoop == [NSRunLoop currentRunLoop], @"This method must be called on the CADisplayLink run loop")
2119

2220
@implementation RCTDisplayLink {
2321
CADisplayLink *_jsDisplayLink;
24-
NSMutableSet<id<RCTDisplayLinkModuleHolder>> *_frameUpdateObservers;
22+
NSMutableSet<id<RCTFrameUpdateObserver>> *_frameUpdateObservers;
2523
NSRunLoop *_runLoop;
2624
}
2725

@@ -35,18 +33,11 @@ - (instancetype)init
3533
return self;
3634
}
3735

38-
- (void)registerModuleForFrameUpdates:(id<RCTBridgeModule>)module
39-
withModuleHolder:(id<RCTDisplayLinkModuleHolder>)moduleHolder
36+
- (void)registerTimingForFrameUpdates:(id<RCTFrameUpdateObserver>)timing
4037
{
41-
if (![moduleHolder.moduleClass conformsToProtocol:@protocol(RCTFrameUpdateObserver)] ||
42-
[_frameUpdateObservers containsObject:moduleHolder]) {
43-
return;
44-
}
45-
46-
[_frameUpdateObservers addObject:moduleHolder];
38+
[_frameUpdateObservers addObject:timing];
4739

48-
// Don't access the module instance via moduleHolder, as this will cause deadlock
49-
id<RCTFrameUpdateObserver> observer = (id<RCTFrameUpdateObserver>)module;
40+
id<RCTFrameUpdateObserver> observer = timing;
5041
__weak typeof(self) weakSelf = self;
5142
observer.pauseCallback = ^{
5243
typeof(self) strongSelf = weakSelf;
@@ -97,45 +88,26 @@ - (void)dealloc
9788
- (void)invalidate
9889
{
9990
// ensure observer callbacks do not hold a reference to weak self via pauseCallback
100-
for (id<RCTDisplayLinkModuleHolder> moduleHolder in _frameUpdateObservers) {
101-
id<RCTFrameUpdateObserver> observer = (id<RCTFrameUpdateObserver>)moduleHolder.instance;
91+
for (id<RCTFrameUpdateObserver> observer in _frameUpdateObservers) {
10292
[observer setPauseCallback:nil];
10393
}
10494
[_frameUpdateObservers removeAllObjects]; // just to be explicit
10595

10696
[_jsDisplayLink invalidate];
10797
}
10898

109-
- (void)dispatchBlock:(dispatch_block_t)block queue:(dispatch_queue_t)queue
110-
{
111-
if (queue == RCTJSThread) {
112-
block();
113-
} else if (queue) {
114-
dispatch_async(queue, block);
115-
}
116-
}
117-
11899
- (void)_jsThreadUpdate:(CADisplayLink *)displayLink
119100
{
120101
RCTAssertRunLoop();
121102

122103
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"-[RCTDisplayLink _jsThreadUpdate:]", nil);
123104

105+
// This always runs on the JS thread run loop, which is the queue the frame
106+
// update observers expect their callbacks on, so dispatch inline.
124107
RCTFrameUpdate *frameUpdate = [[RCTFrameUpdate alloc] initWithDisplayLink:displayLink];
125-
for (id<RCTDisplayLinkModuleHolder> moduleHolder in _frameUpdateObservers) {
126-
id<RCTFrameUpdateObserver> observer = (id<RCTFrameUpdateObserver>)moduleHolder.instance;
108+
for (id<RCTFrameUpdateObserver> observer in _frameUpdateObservers) {
127109
if (!observer.paused) {
128-
if (moduleHolder.methodQueue) {
129-
RCTProfileBeginFlowEvent();
130-
[self
131-
dispatchBlock:^{
132-
RCTProfileEndFlowEvent();
133-
[observer didUpdateFrame:frameUpdate];
134-
}
135-
queue:moduleHolder.methodQueue];
136-
} else {
137-
[observer didUpdateFrame:frameUpdate];
138-
}
110+
[observer didUpdateFrame:frameUpdate];
139111
}
140112
}
141113

@@ -151,8 +123,7 @@ - (void)updateJSDisplayLinkState
151123
RCTAssertRunLoop();
152124

153125
BOOL pauseDisplayLink = YES;
154-
for (id<RCTDisplayLinkModuleHolder> moduleHolder in _frameUpdateObservers) {
155-
id<RCTFrameUpdateObserver> observer = (id<RCTFrameUpdateObserver>)moduleHolder.instance;
126+
for (id<RCTFrameUpdateObserver> observer in _frameUpdateObservers) {
156127
if (!observer.paused) {
157128
pauseDisplayLink = NO;
158129
break;

packages/react-native/React/CoreModules/CoreModulesPlugins.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ Class RCTPlatformCls(void) __attribute__((used));
4949
Class RCTRedBoxCls(void) __attribute__((used));
5050
Class RCTSourceCodeCls(void) __attribute__((used));
5151
Class RCTStatusBarManagerCls(void) __attribute__((used));
52-
Class RCTTimingCls(void) __attribute__((used));
5352
Class RCTWebSocketModuleCls(void) __attribute__((used));
5453
Class RCTBlobManagerCls(void) __attribute__((used));
5554

packages/react-native/React/CoreModules/CoreModulesPlugins.mm

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,6 @@ Class RCTCoreModulesClassProvider(const char *name)
100100
return RCTStatusBarManagerCls();
101101
}
102102

103-
if (name == "Timing"sv) {
104-
return RCTTimingCls();
105-
}
106-
107103
if (name == "WebSocketModule"sv) {
108104
return RCTWebSocketModuleCls();
109105
}

packages/react-native/React/CoreModules/RCTTiming.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
#import <Foundation/Foundation.h>
99

10-
#import <React/RCTBridgeModule.h>
1110
#import <React/RCTFrameUpdate.h>
1211
#import <React/RCTInitializing.h>
1312
#import <React/RCTInvalidating.h>
@@ -22,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN
2221

2322
@end
2423

25-
@interface RCTTiming : NSObject <RCTBridgeModule, RCTInvalidating, RCTFrameUpdateObserver, RCTInitializing>
24+
@interface RCTTiming : NSObject <RCTInvalidating, RCTFrameUpdateObserver, RCTInitializing>
2625

2726
- (instancetype)initWithDelegate:(id<RCTTimingDelegate>)delegate;
2827
- (void)createTimerForNextFrame:(NSNumber *)callbackID

packages/react-native/React/CoreModules/RCTTiming.mm

Lines changed: 9 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,11 @@
77

88
#import "RCTTiming.h"
99

10-
#import <FBReactNativeSpec/FBReactNativeSpec.h>
11-
1210
#import <React/RCTAssert.h>
13-
#import <React/RCTBridge+Private.h>
14-
#import <React/RCTBridge.h>
1511
#import <React/RCTConvert.h>
1612
#import <React/RCTLog.h>
1713
#import <React/RCTUtils.h>
1814

19-
#import "CoreModulesPlugins.h"
20-
2115
static const NSTimeInterval kMinimumSleepInterval = 1;
2216

2317
// These timing contants should be kept in sync with the ones in `JSTimers.js`.
@@ -82,7 +76,7 @@ @implementation _RCTTimingProxy {
8276
+ (instancetype)proxyWithTarget:(id)target
8377
{
8478
_RCTTimingProxy *proxy = [self new];
85-
if (proxy) {
79+
if (proxy != nullptr) {
8680
proxy->_target = target;
8781
}
8882
return proxy;
@@ -103,12 +97,9 @@ @implementation RCTTiming {
10397
id<RCTTimingDelegate> _timingDelegate;
10498
}
10599

106-
@synthesize bridge = _bridge;
107100
@synthesize paused = _paused;
108101
@synthesize pauseCallback = _pauseCallback;
109102

110-
RCT_EXPORT_MODULE()
111-
112103
- (instancetype)initWithDelegate:(id<RCTTimingDelegate>)delegate
113104
{
114105
if (self = [super init]) {
@@ -165,15 +156,9 @@ - (void)dealloc
165156
[_sleepTimer invalidate];
166157
}
167158

168-
- (dispatch_queue_t)methodQueue
169-
{
170-
return RCTJSThread;
171-
}
172-
173159
- (void)invalidate
174160
{
175161
[self stopTimers];
176-
_bridge = nil;
177162
_timingDelegate = nil;
178163
}
179164

@@ -220,7 +205,7 @@ - (void)stopTimers
220205

221206
- (void)startTimers
222207
{
223-
if ((!_bridge && !_timingDelegate) || _inBackground || ![self hasPendingTimers]) {
208+
if ((!_timingDelegate) || _inBackground || ![self hasPendingTimers]) {
224209
return;
225210
}
226211

@@ -259,11 +244,7 @@ - (void)didUpdateFrame:(RCTFrameUpdate *)update
259244
NSArray<NSNumber *> *sortedTimers = [[timersToCall sortedArrayUsingComparator:^(_RCTTimer *a, _RCTTimer *b) {
260245
return [a.target compare:b.target];
261246
}] valueForKey:@"callbackID"];
262-
if (_bridge) {
263-
[_bridge enqueueJSCall:@"JSTimers" method:@"callTimers" args:@[ sortedTimers ] completion:NULL];
264-
} else {
265-
[_timingDelegate callTimers:sortedTimers];
266-
}
247+
[_timingDelegate callTimers:sortedTimers];
267248
}
268249

269250
for (_RCTTimer *timer in timersToCall) {
@@ -282,23 +263,19 @@ - (void)didUpdateFrame:(RCTFrameUpdate *)update
282263
if (kFrameDuration - frameElapsed >= kIdleCallbackFrameDeadline) {
283264
NSTimeInterval currentTimestamp = [[NSDate date] timeIntervalSince1970];
284265
NSNumber *absoluteFrameStartMS = @((currentTimestamp - frameElapsed) * 1000);
285-
if (_bridge) {
286-
[_bridge enqueueJSCall:@"JSTimers" method:@"callIdleCallbacks" args:@[ absoluteFrameStartMS ] completion:NULL];
287-
} else {
288-
[_timingDelegate callIdleCallbacks:absoluteFrameStartMS];
289-
}
266+
[_timingDelegate callIdleCallbacks:absoluteFrameStartMS];
290267
}
291268
}
292269

293270
// Switch to a paused state only if we didn't call any timer this frame, so if
294271
// in response to this timer another timer is scheduled, we don't pause and unpause
295272
// the displaylink frivolously.
296-
NSUInteger timerCount;
273+
NSUInteger timerCount = 0;
297274
@synchronized(_timers) {
298275
timerCount = _timers.count;
299276
}
300277
if (_inBackground) {
301-
if (timerCount) {
278+
if (timerCount != 0u) {
302279
[self scheduleSleepTimer:nextScheduledTarget];
303280
}
304281
} else if (!_sendIdleEvents && timersToCall.count == 0) {
@@ -318,7 +295,7 @@ - (void)didUpdateFrame:(RCTFrameUpdate *)update
318295
- (void)scheduleSleepTimer:(NSDate *)sleepTarget
319296
{
320297
@synchronized(self) {
321-
if (!_sleepTimer || !_sleepTimer.valid) {
298+
if ((_sleepTimer == nullptr) || !_sleepTimer.valid) {
322299
_sleepTimer = [[NSTimer alloc] initWithFireDate:sleepTarget
323300
interval:0
324301
target:[_RCTTimingProxy proxyWithTarget:self]
@@ -343,35 +320,6 @@ - (void)timerDidFire
343320
}
344321
}
345322

346-
/**
347-
* A method used for asynchronously creating a timer. If the timer has already expired,
348-
* (based on the provided jsSchedulingTime) then it will be immediately invoked.
349-
*
350-
* There's a small difference between the time when we call
351-
* setTimeout/setInterval/requestAnimation frame and the time it actually makes
352-
* it here. This is important and needs to be taken into account when
353-
* calculating the timer's target time. We calculate this by passing in
354-
* Date.now() from JS and then subtracting that from the current time here.
355-
*/
356-
RCT_EXPORT_METHOD(
357-
createTimer : (double)callbackID duration : (NSTimeInterval)jsDuration jsSchedulingTime : (double)
358-
jsSchedulingTime repeats : (BOOL)repeats)
359-
{
360-
NSNumber *callbackIdObjc = [NSNumber numberWithDouble:callbackID];
361-
NSDate *schedulingTime = [RCTConvert NSDate:[NSNumber numberWithDouble:jsSchedulingTime]];
362-
if (jsDuration == 0 && repeats == NO) {
363-
// For super fast, one-off timers, just enqueue them immediately rather than waiting a frame.
364-
if (_bridge) {
365-
[_bridge _immediatelyCallTimer:callbackIdObjc];
366-
} else {
367-
[_timingDelegate immediatelyCallTimer:callbackIdObjc];
368-
}
369-
return;
370-
}
371-
372-
[self createTimerForNextFrame:callbackIdObjc duration:jsDuration jsSchedulingTime:schedulingTime repeats:repeats];
373-
}
374-
375323
/**
376324
* A method used for synchronously creating a timer. The timer will not be invoked until the
377325
* next frame, regardless of whether it has already expired (i.e. jsSchedulingTime is 0).
@@ -407,29 +355,14 @@ - (void)createTimerForNextFrame:(nonnull NSNumber *)callbackID
407355
}
408356
}
409357

410-
RCT_EXPORT_METHOD(deleteTimer : (double)timerID)
358+
- (void)deleteTimer:(double)timerID
411359
{
412360
@synchronized(_timers) {
413-
[_timers removeObjectForKey:[NSNumber numberWithDouble:timerID]];
361+
[_timers removeObjectForKey:@(timerID)];
414362
}
415363
if (![self hasPendingTimers]) {
416364
[self stopTimers];
417365
}
418366
}
419367

420-
RCT_EXPORT_METHOD(setSendIdleEvents : (BOOL)sendIdleEvents)
421-
{
422-
_sendIdleEvents = sendIdleEvents;
423-
if (sendIdleEvents) {
424-
[self startTimers];
425-
} else if (![self hasPendingTimers]) {
426-
[self stopTimers];
427-
}
428-
}
429-
430368
@end
431-
432-
Class RCTTimingCls(void)
433-
{
434-
return RCTTiming.class;
435-
}

0 commit comments

Comments
 (0)