react-native-tvos 0.79.2-0 → 0.79.3-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/Libraries/Core/ReactNativeVersion.js +1 -1
  2. package/README.md +3 -1
  3. package/React/Base/RCTRootView.h +7 -1
  4. package/React/Base/RCTRootView.m +38 -0
  5. package/React/Base/RCTRootViewInternal.h +1 -0
  6. package/React/Base/RCTTVRemoteSelectHandler.m +2 -1
  7. package/React/Base/RCTVersion.m +1 -1
  8. package/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h +6 -0
  9. package/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm +37 -0
  10. package/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm +18 -4
  11. package/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm +1 -1
  12. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +3 -5
  13. package/React/Views/RCTTVView.m +4 -4
  14. package/ReactAndroid/gradle.properties +1 -1
  15. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
  16. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BorderRadiusStyle.kt +2 -2
  17. package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +0 -3
  18. package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
  19. package/ReactCommon/jsc/React-jsc.podspec +1 -1
  20. package/ReactCommon/react/runtime/TimerManager.cpp +6 -4
  21. package/ReactCommon/react/runtime/TimerManager.h +3 -1
  22. package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm +0 -1
  23. package/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp +9 -5
  24. package/package.json +8 -8
  25. package/scripts/codegen/generate-artifacts-executor.js +53 -18
  26. package/sdks/.hermesversion +1 -1
  27. package/sdks/hermesc/osx-bin/hermes +0 -0
  28. package/sdks/hermesc/osx-bin/hermesc +0 -0
  29. package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
  30. package/types/index.d.ts +1 -1
  31. package/types/tsconfig.test.json +16 -0
@@ -16,7 +16,7 @@ const version: $ReadOnly<{
16
16
  }> = {
17
17
  major: 0,
18
18
  minor: 79,
19
- patch: 2,
19
+ patch: 3,
20
20
  prerelease: '0',
21
21
  };
22
22
 
package/README.md CHANGED
@@ -262,7 +262,9 @@ class Game2048 extends React.Component {
262
262
 
263
263
  - _LogBox_: The LogBox error/warning display (which replaced YellowBox in 0.63) is working as expected on TV platforms, after a few adjustments to make the controls accessible to the focus engine.
264
264
 
265
- - _Dev Menu support_: On the Apple TV simulator, cmd-D will bring up the developer menu, just like on iOS. To bring it up on a real Apple TV device, make a long press on the play/pause button on the remote. (Please do not shake the Apple TV device, that will not work :) ). Android TV dev menu behavior is the same as on Android phone.
265
+ - _Dev Menu support_:
266
+ - The developer menu provided by React Native itself works on TV. On the Apple TV simulator, cmd-D will bring up the developer menu, just like on iOS. To bring it up on a real Apple TV device, make a long press on the play/pause button on the remote. (Please do not shake the Apple TV device, that will not work :) ). Android TV dev menu behavior is the same as on Android phone.
267
+ - The Expo dev menu (provided by the [Expo dev client package](https://docs.expo.dev/versions/latest/sdk/dev-client/)) is *not* supported on TV.
266
268
 
267
269
  - _TV remote animations on Apple TV_: `RCTTVView` native code implements Apple-recommended parallax animations to help guide the eye as the user navigates through views. The animations can be disabled or adjusted with new optional view properties.
268
270
 
@@ -14,6 +14,9 @@
14
14
  extern NSString * _Nonnull const RCTTVEnableMenuKeyNotification;
15
15
  extern NSString * _Nonnull const RCTTVDisableMenuKeyNotification;
16
16
 
17
+ #if TARGET_OS_TV
18
+ #import "RCTTVRemoteSelectHandler.h"
19
+ #endif
17
20
 
18
21
  @protocol RCTRootViewDelegate;
19
22
 
@@ -51,8 +54,11 @@ extern
51
54
  * like any ordinary UIView. You can have multiple RCTRootViews on screen at
52
55
  * once, all controlled by the same JavaScript application.
53
56
  */
57
+ #if TARGET_OS_TV
58
+ @interface RCTRootView : UIView <RCTTVRemoteSelectHandlerDelegate>
59
+ #else
54
60
  @interface RCTRootView : UIView
55
-
61
+ #endif
56
62
  /**
57
63
  * - Designated initializer -
58
64
  */
@@ -31,6 +31,8 @@
31
31
  #if TARGET_OS_TV
32
32
  #import "RCTTVNavigationEventEmitter.h"
33
33
  #import "RCTTVRemoteHandler.h"
34
+ #import "RCTTVRemoteSelectHandler.h"
35
+ #import <React/RCTTVNavigationEventNotification.h>
34
36
  #endif
35
37
 
36
38
  #if RCT_DEV
@@ -98,6 +100,7 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat
98
100
  #endif
99
101
 
100
102
  self.tvRemoteHandler = [[RCTTVRemoteHandler alloc] initWithView:self];
103
+ self.tvRemoteSelectHandler = [[RCTTVRemoteSelectHandler alloc] initWithView:self];
101
104
  #endif
102
105
 
103
106
  [self showLoadingView];
@@ -424,10 +427,45 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
424
427
  {
425
428
  #if TARGET_OS_TV
426
429
  self.tvRemoteHandler = nil;
430
+ self.tvRemoteSelectHandler = nil;
427
431
  #endif
428
432
  [_contentView invalidate];
429
433
  }
430
434
 
435
+ #if TARGET_OS_TV
436
+
437
+ #pragma mark -
438
+ #pragma mark RCTTVRemoteSelectHandlerDelegate methods
439
+
440
+ - (void)animatePressIn {
441
+ }
442
+
443
+ - (void)animatePressOut {
444
+ }
445
+
446
+ - (void)emitPressInEvent {
447
+ }
448
+
449
+ - (void)emitPressOutEvent {
450
+ }
451
+
452
+ - (void)sendSelectNotification
453
+ {
454
+ [[NSNotificationCenter defaultCenter] postNavigationPressEventWithType:RCTTVRemoteEventSelect keyAction:RCTTVRemoteEventKeyActionUp tag:self.reactTag target:self.reactTag];
455
+ }
456
+
457
+ - (void)sendLongSelectBeganNotification
458
+ {
459
+ [[NSNotificationCenter defaultCenter] postNavigationPressEventWithType:RCTTVRemoteEventLongSelect keyAction:RCTTVRemoteEventKeyActionDown tag:self.reactTag target:self.reactTag];
460
+ }
461
+
462
+ - (void)sendLongSelectEndedNotification
463
+ {
464
+ [[NSNotificationCenter defaultCenter] postNavigationPressEventWithType:RCTTVRemoteEventLongSelect keyAction:RCTTVRemoteEventKeyActionUp tag:self.reactTag target:self.reactTag];
465
+ }
466
+
467
+ #endif
468
+
431
469
  @end
432
470
 
433
471
  @implementation RCTRootView (Deprecated)
@@ -26,6 +26,7 @@
26
26
  */
27
27
  #if TARGET_OS_TV
28
28
  @property (nonatomic, strong, nullable) RCTTVRemoteHandler *tvRemoteHandler;
29
+ @property (nonatomic, strong, nullable) RCTTVRemoteSelectHandler *tvRemoteSelectHandler;
29
30
  @property (nonatomic, weak) UIView *reactPreferredFocusedView;
30
31
  @property (nonatomic, copy, nullable) NSArray<id<UIFocusEnvironment>> *reactPreferredFocusEnvironments;
31
32
  #endif
@@ -36,7 +36,7 @@
36
36
 
37
37
  // Press recognizer should allow long press recognizer to work (but not the reverse)
38
38
  - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
39
- return gestureRecognizer == _pressRecognizer;
39
+ return gestureRecognizer == self.pressRecognizer && otherGestureRecognizer == self.longPressRecognizer;
40
40
  }
41
41
 
42
42
  #pragma mark -
@@ -54,6 +54,7 @@
54
54
  UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
55
55
  longPressRecognizer.allowedPressTypes = @[ @(UIPressTypeSelect) ];
56
56
  longPressRecognizer.minimumPressDuration = 0.5;
57
+ longPressRecognizer.delegate = self;
57
58
 
58
59
  [self.view addGestureRecognizer:longPressRecognizer];
59
60
  self.longPressRecognizer = longPressRecognizer;
@@ -23,7 +23,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
23
23
  __rnVersion = @{
24
24
  RCTVersionMajor: @(0),
25
25
  RCTVersionMinor: @(79),
26
- RCTVersionPatch: @(2),
26
+ RCTVersionPatch: @(3),
27
27
  RCTVersionPrerelease: @"0",
28
28
  };
29
29
  });
@@ -14,6 +14,7 @@
14
14
 
15
15
  #if TARGET_OS_TV
16
16
  #import <React/RCTTVRemoteHandler.h>
17
+ #import <React/RCTTVRemoteSelectHandler.h>
17
18
  #endif
18
19
 
19
20
  NS_ASSUME_NONNULL_BEGIN
@@ -25,7 +26,11 @@ NS_ASSUME_NONNULL_BEGIN
25
26
  *
26
27
  * WARNING: In the future, RCTRootView will be deprecated in favor of RCTSurfaceHostingView.
27
28
  */
29
+ #if TARGET_OS_TV
30
+ @interface RCTSurfaceHostingProxyRootView : RCTSurfaceHostingView <RCTTVRemoteSelectHandlerDelegate>
31
+ #else
28
32
  @interface RCTSurfaceHostingProxyRootView : RCTSurfaceHostingView
33
+ #endif
29
34
 
30
35
  #pragma mark RCTRootView compatibility - keep these sync'ed with RCTRootView.h
31
36
 
@@ -44,6 +49,7 @@ NS_ASSUME_NONNULL_BEGIN
44
49
  @property (nonatomic, assign) CGSize minimumSize;
45
50
  #if TARGET_OS_TV
46
51
  @property (nonatomic, strong, nullable) RCTTVRemoteHandler *tvRemoteHandler;
52
+ @property (nonatomic, strong, nullable) RCTTVRemoteSelectHandler *tvRemoteSelectHandler;
47
53
  @property (nonatomic, weak, nullable) UIView *reactPreferredFocusedView;
48
54
  @property (nonatomic, copy, nullable) NSArray<id<UIFocusEnvironment>> *reactPreferredFocusEnvironments;
49
55
  #endif
@@ -20,6 +20,10 @@
20
20
  #import "RCTSurface.h"
21
21
  #import "UIView+React.h"
22
22
 
23
+ #if TARGET_OS_TV
24
+ #import <React/RCTTVNavigationEventNotification.h>
25
+ #endif
26
+
23
27
  static RCTSurfaceSizeMeasureMode convertToSurfaceSizeMeasureMode(RCTRootViewSizeFlexibility sizeFlexibility)
24
28
  {
25
29
  switch (sizeFlexibility) {
@@ -61,9 +65,11 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
61
65
  RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
62
66
 
63
67
  #if TARGET_OS_TV
68
+
64
69
  - (void)dealloc
65
70
  {
66
71
  self.tvRemoteHandler = nil;
72
+ self.tvRemoteSelectHandler = nil;
67
73
  }
68
74
 
69
75
  - (NSArray<id<UIFocusEnvironment>> *)preferredFocusEnvironments {
@@ -78,6 +84,36 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
78
84
  }
79
85
  return [super preferredFocusEnvironments];
80
86
  }
87
+
88
+ #pragma mark -
89
+ #pragma mark RCTTVRemoteSelectHandlerDelegate methods
90
+
91
+ - (void)animatePressIn {
92
+ }
93
+
94
+ - (void)animatePressOut {
95
+ }
96
+
97
+ - (void)emitPressInEvent {
98
+ }
99
+
100
+ - (void)emitPressOutEvent {
101
+ }
102
+
103
+ - (void)sendSelectNotification
104
+ {
105
+ [[NSNotificationCenter defaultCenter] postNavigationPressEventWithType:RCTTVRemoteEventSelect keyAction:RCTTVRemoteEventKeyActionUp tag:self.reactTag target:self.reactTag];
106
+ }
107
+
108
+ - (void)sendLongSelectBeganNotification
109
+ {
110
+ [[NSNotificationCenter defaultCenter] postNavigationPressEventWithType:RCTTVRemoteEventLongSelect keyAction:RCTTVRemoteEventKeyActionDown tag:self.reactTag target:self.reactTag];
111
+ }
112
+
113
+ - (void)sendLongSelectEndedNotification
114
+ {
115
+ [[NSNotificationCenter defaultCenter] postNavigationPressEventWithType:RCTTVRemoteEventLongSelect keyAction:RCTTVRemoteEventKeyActionUp tag:self.reactTag target:self.reactTag];
116
+ }
81
117
  #endif
82
118
 
83
119
 
@@ -145,6 +181,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
145
181
  dispatch_async(dispatch_get_main_queue(), ^{
146
182
  #if TARGET_OS_TV
147
183
  self.tvRemoteHandler = [[RCTTVRemoteHandler alloc] initWithView:[self contentView]];
184
+ self.tvRemoteSelectHandler = [[RCTTVRemoteSelectHandler alloc] initWithView:self];
148
185
  #endif
149
186
  });
150
187
  }
@@ -170,10 +170,24 @@ static NSString *const kRCTLegacyInteropChildIndexKey = @"index";
170
170
 
171
171
  - (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
172
172
  {
173
- [_viewsToBeMounted addObject:@{
174
- kRCTLegacyInteropChildIndexKey : [NSNumber numberWithInteger:index],
175
- kRCTLegacyInteropChildComponentKey : childComponentView
176
- }];
173
+ if (_adapter && index == _adapter.paperView.reactSubviews.count) {
174
+ // This is a new child view that is being added to the end of the children array.
175
+ // After the children is added, we need to call didUpdateReactSubviews to make sure that it is rendered.
176
+ // Without this change, the new child will not be rendered right away because the didUpdateReactSubviews is not
177
+ // called and the `finalizeUpdate` is not invoked.
178
+ if ([childComponentView isKindOfClass:[RCTLegacyViewManagerInteropComponentView class]]) {
179
+ UIView *target = ((RCTLegacyViewManagerInteropComponentView *)childComponentView).contentView;
180
+ [_adapter.paperView insertReactSubview:target atIndex:index];
181
+ } else {
182
+ [_adapter.paperView insertReactSubview:childComponentView atIndex:index];
183
+ }
184
+ [_adapter.paperView didUpdateReactSubviews];
185
+ } else {
186
+ [_viewsToBeMounted addObject:@{
187
+ kRCTLegacyInteropChildIndexKey : [NSNumber numberWithInteger:index],
188
+ kRCTLegacyInteropChildComponentKey : childComponentView
189
+ }];
190
+ }
177
191
  }
178
192
 
179
193
  - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
@@ -68,7 +68,7 @@ using namespace facebook::react;
68
68
  const auto &newSwitchProps = static_cast<const SwitchProps &>(*props);
69
69
 
70
70
  // `value`
71
- if (oldSwitchProps.value != newSwitchProps.value) {
71
+ if (!_isInitialValueSet || oldSwitchProps.value != newSwitchProps.value) {
72
72
  BOOL shouldAnimate = _isInitialValueSet == YES;
73
73
  [_switchView setOn:newSwitchProps.value animated:shouldAnimate];
74
74
  }
@@ -587,23 +587,21 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
587
587
  }
588
588
 
589
589
  if (context.nextFocusedView == self) {
590
- if(_eventEmitter) _eventEmitter->onFocus();
591
-
592
590
  [self becomeFirstResponder];
593
591
  [self enableDirectionalFocusGuides];
594
592
  [coordinator addCoordinatedAnimations:^(void){
595
- [self addParallaxMotionEffects];
593
+ if (self->_eventEmitter) self->_eventEmitter->onFocus();
596
594
  [self sendFocusNotification:context];
595
+ [self addParallaxMotionEffects];
597
596
  } completion:^(void){}];
598
597
  // Without this check, onBlur would also trigger when `TVFocusGuideView` transfers focus to its children.
599
598
  // [self isTVFocusGuide] is false when autofocus and destinations are not used, so we cannot use that.
600
599
  // Generally speaking, it would happen for any non-collapsable `View`.
601
600
  } else if (context.previouslyFocusedView == self) {
602
- if (_eventEmitter) _eventEmitter->onBlur();
603
-
604
601
  [self disableDirectionalFocusGuides];
605
602
  [coordinator addCoordinatedAnimations:^(void){
606
603
  [self removeParallaxMotionEffects];
604
+ if (self->_eventEmitter) self->_eventEmitter->onBlur();
607
605
  [self sendBlurNotification:context];
608
606
  } completion:^(void){}];
609
607
  [self resignFirstResponder];
@@ -304,22 +304,22 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
304
304
  }
305
305
 
306
306
  if (context.nextFocusedView == self) {
307
- if (self.onFocus) self.onFocus(nil);
308
307
  [self becomeFirstResponder];
309
308
  [self enableDirectionalFocusGuides];
310
309
  [coordinator addCoordinatedAnimations:^(void){
311
- [self addParallaxMotionEffects];
310
+ if (self.onFocus) self.onFocus(nil);
312
311
  [self sendFocusNotification:context];
312
+ [self addParallaxMotionEffects];
313
313
  } completion:^(void){}];
314
314
  // Without this check, onBlur would also trigger when `TVFocusGuideView` transfers focus to its children.
315
315
  // [self isTVFocusGuide] is false when autofocus and destinations are not used, so we cannot use that.
316
316
  // Generally speaking, it would happen for any non-collapsable `View`.
317
317
  } else if (context.previouslyFocusedView == self ) {
318
- if (self.onBlur) self.onBlur(nil);
319
318
  [self disableDirectionalFocusGuides];
320
319
  [coordinator addCoordinatedAnimations:^(void){
321
- [self sendBlurNotification:context];
322
320
  [self removeParallaxMotionEffects];
321
+ if (self.onBlur) self.onBlur(nil);
322
+ [self sendBlurNotification:context];
323
323
  } completion:^(void){}];
324
324
  [self resignFirstResponder];
325
325
  }
@@ -1,4 +1,4 @@
1
- VERSION_NAME=0.79.2-0
1
+ VERSION_NAME=0.79.3-0
2
2
  react.internal.publishingGroup=io.github.react-native-tvos
3
3
 
4
4
  android.useAndroidX=true
@@ -17,6 +17,6 @@ public class ReactNativeVersion {
17
17
  public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
18
18
  "major", 0,
19
19
  "minor", 79,
20
- "patch", 2,
20
+ "patch", 3,
21
21
  "prerelease", "0");
22
22
  }
@@ -136,10 +136,10 @@ internal data class BorderRadiusStyle(
136
136
  (startStart ?: topStart ?: topLeft ?: uniform)?.resolve(width, height)
137
137
  ?: zeroRadii,
138
138
  bottomLeft =
139
- (endEnd ?: bottomStart ?: bottomRight ?: uniform)?.resolve(width, height)
139
+ (endEnd ?: bottomEnd ?: bottomRight ?: uniform)?.resolve(width, height)
140
140
  ?: zeroRadii,
141
141
  bottomRight =
142
- (startEnd ?: bottomEnd ?: bottomLeft ?: uniform)?.resolve(width, height)
142
+ (startEnd ?: bottomStart ?: bottomLeft ?: uniform)?.resolve(width, height)
143
143
  ?: zeroRadii,
144
144
  width = width,
145
145
  height = height,
@@ -710,9 +710,6 @@ public class ReactViewGroup extends ViewGroup
710
710
  UiThreadUtil.assertOnUiThread();
711
711
  checkViewClippingTag(child, Boolean.TRUE);
712
712
  if (!customDrawOrderDisabled()) {
713
- if (indexOfChild(child) == -1) {
714
- return;
715
- }
716
713
  getDrawingOrderHelper().handleRemoveView(child);
717
714
  setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder());
718
715
  } else {
@@ -17,7 +17,7 @@ namespace facebook::react {
17
17
  constexpr struct {
18
18
  int32_t Major = 0;
19
19
  int32_t Minor = 79;
20
- int32_t Patch = 2;
20
+ int32_t Patch = 3;
21
21
  std::string_view Prerelease = "0";
22
22
  } ReactNativeVersion;
23
23
 
@@ -32,6 +32,6 @@ Pod::Spec.new do |s|
32
32
  s.dependency "React-jsi", version
33
33
 
34
34
  s.subspec "Fabric" do |ss|
35
- ss.pod_target_xcconfig = { "OTHER_CFLAGS" => "$(inherited)" }
35
+ ss.pod_target_xcconfig = { "OTHER_CFLAGS" => "$(inherited)", "DEFINES_MODULE" => "YES" }
36
36
  end
37
37
  end
@@ -242,8 +242,9 @@ void TimerManager::attachGlobals(jsi::Runtime& runtime) {
242
242
  }
243
243
 
244
244
  if (!args[0].isObject() || !args[0].asObject(rt).isFunction(rt)) {
245
- // Do not throw any error to match web spec
246
- return timerIndex_++;
245
+ // Do not throw any error to match web spec; instead return 0, an
246
+ // invalid timer id
247
+ return 0;
247
248
  }
248
249
 
249
250
  auto callback = args[0].getObject(rt).getFunction(rt);
@@ -300,8 +301,9 @@ void TimerManager::attachGlobals(jsi::Runtime& runtime) {
300
301
  }
301
302
 
302
303
  if (!args[0].isObject() || !args[0].asObject(rt).isFunction(rt)) {
303
- throw jsi::JSError(
304
- rt, "The first argument to setInterval must be a function.");
304
+ // Do not throw any error to match web spec; instead return 0, an
305
+ // invalid timer id
306
+ return 0;
305
307
  }
306
308
  auto callback = args[0].getObject(rt).getFunction(rt);
307
309
  auto delay = count > 1
@@ -93,7 +93,9 @@ class TimerManager {
93
93
 
94
94
  // Each timeout that is registered on this queue gets a sequential id. This
95
95
  // is the global count from which those are assigned.
96
- TimerHandle timerIndex_{0};
96
+ // As per WHATWG HTML 8.6.1 (Timers) ids must be greater than zero, i.e. start
97
+ // at 1
98
+ TimerHandle timerIndex_{1};
97
99
 
98
100
  // The React Native microtask queue is used to back public APIs including
99
101
  // `queueMicrotask`, `clearImmediate`, and `setImmediate` (which is used by
@@ -474,7 +474,6 @@ void RCTInstanceSetRuntimeDiagnosticFlags(NSString *flags)
474
474
 
475
475
  if (error) {
476
476
  [strongSelf handleBundleLoadingError:error];
477
- [strongSelf invalidate];
478
477
  return;
479
478
  }
480
479
  // DevSettings module is needed by _loadScriptFromSource's callback so prior initialization is required
@@ -267,7 +267,9 @@ TEST_F(ReactInstanceTest, testSetTimeoutWithoutDelay) {
267
267
  EXPECT_CALL(
268
268
  *mockRegistry_,
269
269
  createTimer(_, 0)); // If delay is not provided, it should use 0
270
- eval("setTimeout(() => {});");
270
+ auto val = eval("setTimeout(() => {});");
271
+ expectNoError();
272
+ EXPECT_EQ(val.asNumber(), 1); // First timer id should start at 1
271
273
  }
272
274
 
273
275
  TEST_F(ReactInstanceTest, testSetTimeoutWithPassThroughArgs) {
@@ -299,8 +301,9 @@ TEST_F(ReactInstanceTest, testSetTimeoutWithInvalidArgs) {
299
301
  getErrorMessage("setTimeout();"),
300
302
  "setTimeout must be called with at least one argument (the function to call).");
301
303
 
302
- eval("setTimeout('invalid');");
304
+ auto val = eval("setTimeout('invalid')");
303
305
  expectNoError();
306
+ EXPECT_EQ(val.asNumber(), 0);
304
307
 
305
308
  eval("setTimeout(() => {}, 'invalid');");
306
309
  expectNoError();
@@ -417,9 +420,10 @@ TEST_F(ReactInstanceTest, testSetIntervalWithInvalidArgs) {
417
420
  EXPECT_EQ(
418
421
  getErrorMessage("setInterval();"),
419
422
  "setInterval must be called with at least one argument (the function to call).");
420
- EXPECT_EQ(
421
- getErrorMessage("setInterval('invalid', 100);"),
422
- "The first argument to setInterval must be a function.");
423
+
424
+ auto val = eval("setInterval('invalid', 100)");
425
+ expectNoError();
426
+ EXPECT_EQ(val.asNumber(), 0);
423
427
  }
424
428
 
425
429
  TEST_F(ReactInstanceTest, testClearInterval) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-tvos",
3
- "version": "0.79.2-0",
3
+ "version": "0.79.3-0",
4
4
  "description": "A framework for building native apps using React",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -112,12 +112,12 @@
112
112
  },
113
113
  "dependencies": {
114
114
  "@jest/create-cache-key-function": "^29.7.0",
115
- "@react-native/assets-registry": "0.79.2",
116
- "@react-native/codegen": "0.79.2",
117
- "@react-native/community-cli-plugin": "0.79.2",
118
- "@react-native/gradle-plugin": "0.79.2",
119
- "@react-native/js-polyfills": "0.79.2",
120
- "@react-native/normalize-colors": "0.79.2",
115
+ "@react-native/assets-registry": "0.79.3",
116
+ "@react-native/codegen": "0.79.3",
117
+ "@react-native/community-cli-plugin": "0.79.3",
118
+ "@react-native/gradle-plugin": "0.79.3",
119
+ "@react-native/js-polyfills": "0.79.3",
120
+ "@react-native/normalize-colors": "0.79.3",
121
121
  "abort-controller": "^3.0.0",
122
122
  "anser": "^1.4.9",
123
123
  "ansi-regex": "^5.0.0",
@@ -146,7 +146,7 @@
146
146
  "whatwg-fetch": "^3.0.0",
147
147
  "ws": "^6.2.3",
148
148
  "yargs": "^17.6.2",
149
- "@react-native-tvos/virtualized-lists": "0.79.2-0"
149
+ "@react-native-tvos/virtualized-lists": "0.79.3-0"
150
150
  },
151
151
  "codegenConfig": {
152
152
  "libraries": [
@@ -326,22 +326,13 @@ function findExternalLibraries(pkgJson, projectRoot) {
326
326
  });
327
327
  }
328
328
 
329
- function findLibrariesFromReactNativeConfig(projectRoot) {
330
- const rnConfigFileName = 'react-native.config.js';
331
-
329
+ function findLibrariesFromReactNativeConfig(projectRoot, rnConfig) {
332
330
  codegenLog(
333
- `Searching for codegen-enabled libraries in ${rnConfigFileName}`,
331
+ `Searching for codegen-enabled libraries in react-native.config.js`,
334
332
  true,
335
333
  );
336
334
 
337
- const rnConfigFilePath = path.resolve(projectRoot, rnConfigFileName);
338
-
339
- if (!fs.existsSync(rnConfigFilePath)) {
340
- return [];
341
- }
342
- const rnConfig = require(rnConfigFilePath);
343
-
344
- if (rnConfig.dependencies == null) {
335
+ if (!rnConfig.dependencies) {
345
336
  return [];
346
337
  }
347
338
  return Object.keys(rnConfig.dependencies).flatMap(name => {
@@ -365,6 +356,19 @@ function findLibrariesFromReactNativeConfig(projectRoot) {
365
356
  });
366
357
  }
367
358
 
359
+ /**
360
+ * Finds all disabled libraries by platform based the react native config.
361
+ *
362
+ * This is needed when selectively disabling libraries in react-native.config.js since codegen should exclude those libraries as well.
363
+ */
364
+ function findDisabledLibrariesByPlatform(reactNativeConfig, platform) {
365
+ const dependencies = reactNativeConfig.dependencies ?? {};
366
+
367
+ return Object.keys(dependencies).filter(
368
+ dependency => dependencies[dependency].platforms?.[platform] === null,
369
+ );
370
+ }
371
+
368
372
  function findProjectRootLibraries(pkgJson, projectRoot) {
369
373
  codegenLog('Searching for codegen-enabled libraries in the app.', true);
370
374
 
@@ -593,7 +597,7 @@ function mustGenerateNativeCode(includeLibraryPath, schemaInfo) {
593
597
  );
594
598
  }
595
599
 
596
- function findCodegenEnabledLibraries(pkgJson, projectRoot) {
600
+ function findCodegenEnabledLibraries(pkgJson, projectRoot, reactNativeConfig) {
597
601
  const projectLibraries = findProjectRootLibraries(pkgJson, projectRoot);
598
602
  if (pkgJsonIncludesGeneratedCode(pkgJson)) {
599
603
  return projectLibraries;
@@ -601,11 +605,21 @@ function findCodegenEnabledLibraries(pkgJson, projectRoot) {
601
605
  return [
602
606
  ...projectLibraries,
603
607
  ...findExternalLibraries(pkgJson, projectRoot),
604
- ...findLibrariesFromReactNativeConfig(projectRoot),
608
+ ...findLibrariesFromReactNativeConfig(projectRoot, reactNativeConfig),
605
609
  ];
606
610
  }
607
611
  }
608
612
 
613
+ function readReactNativeConfig(projectRoot) {
614
+ const rnConfigFilePath = path.resolve(projectRoot, 'react-native.config.js');
615
+
616
+ if (!fs.existsSync(rnConfigFilePath)) {
617
+ return {};
618
+ }
619
+
620
+ return require(rnConfigFilePath);
621
+ }
622
+
609
623
  function generateCustomURLHandlers(libraries, outputDir) {
610
624
  const customImageURLLoaderClasses = libraries
611
625
  .flatMap(
@@ -834,8 +848,11 @@ function findFilesWithExtension(filePath, extension) {
834
848
  return null;
835
849
  }
836
850
 
837
- // Skip hidden folders, that starts with `.`
838
- if (absolutePath.includes(`${path.sep}.`)) {
851
+ // Skip hidden folders, that starts with `.` but allow `.pnpm`
852
+ if (
853
+ absolutePath.includes(`${path.sep}.`) &&
854
+ !absolutePath.includes(`${path.sep}.pnpm`)
855
+ ) {
839
856
  return null;
840
857
  }
841
858
 
@@ -1054,9 +1071,14 @@ function execute(projectRoot, targetPlatform, baseOutputPath, source) {
1054
1071
 
1055
1072
  buildCodegenIfNeeded();
1056
1073
 
1057
- const libraries = findCodegenEnabledLibraries(pkgJson, projectRoot);
1074
+ const reactNativeConfig = readReactNativeConfig(projectRoot);
1075
+ const codegenEnabledLibraries = findCodegenEnabledLibraries(
1076
+ pkgJson,
1077
+ projectRoot,
1078
+ reactNativeConfig,
1079
+ );
1058
1080
 
1059
- if (libraries.length === 0) {
1081
+ if (codegenEnabledLibraries.length === 0) {
1060
1082
  codegenLog('No codegen-enabled libraries found.', true);
1061
1083
  return;
1062
1084
  }
@@ -1065,6 +1087,19 @@ function execute(projectRoot, targetPlatform, baseOutputPath, source) {
1065
1087
  targetPlatform === 'all' ? supportedPlatforms : [targetPlatform];
1066
1088
 
1067
1089
  for (const platform of platforms) {
1090
+ const disabledLibraries = findDisabledLibrariesByPlatform(
1091
+ reactNativeConfig,
1092
+ platform,
1093
+ );
1094
+
1095
+ const libraries = codegenEnabledLibraries.filter(
1096
+ ({name}) => !disabledLibraries.includes(name),
1097
+ );
1098
+
1099
+ if (!libraries.length) {
1100
+ continue;
1101
+ }
1102
+
1068
1103
  const outputPath = computeOutputPath(
1069
1104
  projectRoot,
1070
1105
  baseOutputPath,
@@ -1 +1 @@
1
- hermes-2025-03-03-RNv0.79.0-bc17d964d03743424823d7dd1a9f37633459c5c5
1
+ hermes-2025-06-04-RNv0.79.3-7f9a871eefeb2c3852365ee80f0b6733ec12ac3b
Binary file
Binary file
Binary file
package/types/index.d.ts CHANGED
@@ -68,7 +68,7 @@
68
68
  /// <reference path="modules/BatchedBridge.d.ts" />
69
69
  /// <reference path="modules/Codegen.d.ts" />
70
70
  /// <reference path="modules/Devtools.d.ts" />
71
- /// <reference types="../src/types/globals.d.ts" />
71
+ /// <reference path="../src/types/globals.d.ts" />
72
72
  /// <reference path="modules/LaunchScreen.d.ts" />
73
73
 
74
74
  export * from '../Libraries/ActionSheetIOS/ActionSheetIOS';
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "commonjs",
4
+ "lib": ["es6"],
5
+ "noImplicitAny": true,
6
+ "noImplicitThis": true,
7
+ "strictFunctionTypes": true,
8
+ "strictNullChecks": true,
9
+ "types": [],
10
+ "jsx": "react",
11
+ "noEmit": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "paths": {"react-native": ["."]}
14
+ },
15
+ "include": ["../**/*.d.ts", "__typetests__/**/*"]
16
+ }