react-native 0.76.2 → 0.76.4

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 (29) hide show
  1. package/Libraries/Core/ReactNativeVersion.js +1 -1
  2. package/React/Base/RCTVersion.m +1 -1
  3. package/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.h +1 -1
  4. package/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm +8 -18
  5. package/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +7 -2
  6. package/React/Views/RCTFont.h +2 -0
  7. package/React/Views/RCTFont.mm +4 -5
  8. package/ReactAndroid/api/ReactAndroid.api +2 -0
  9. package/ReactAndroid/cmake-utils/ReactNative-application.cmake +2 -3
  10. package/ReactAndroid/cmake-utils/default-app-setup/OnLoad.cpp +13 -0
  11. package/ReactAndroid/gradle.properties +1 -1
  12. package/ReactAndroid/hermes-engine/build.gradle.kts +4 -0
  13. package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +8 -2
  14. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
  15. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +11 -3
  16. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +11 -3
  17. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt +25 -0
  18. package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
  19. package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm +10 -10
  20. package/ReactCommon/react/renderer/uimanager/UIManager.cpp +29 -8
  21. package/jest/setup.js +5 -1
  22. package/package.json +8 -8
  23. package/scripts/codegen/generate-artifacts-executor.js +53 -7
  24. package/sdks/hermesc/osx-bin/hermes +0 -0
  25. package/sdks/hermesc/osx-bin/hermesc +0 -0
  26. package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
  27. package/sdks/hermesc/win64-bin/msvcp140.dll +0 -0
  28. package/sdks/hermesc/win64-bin/vcruntime140.dll +0 -0
  29. package/sdks/hermesc/win64-bin/vcruntime140_1.dll +0 -0
@@ -16,7 +16,7 @@ const version: $ReadOnly<{
16
16
  }> = {
17
17
  major: 0,
18
18
  minor: 76,
19
- patch: 2,
19
+ patch: 4,
20
20
  prerelease: null,
21
21
  };
22
22
 
@@ -23,7 +23,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
23
23
  __rnVersion = @{
24
24
  RCTVersionMajor: @(0),
25
25
  RCTVersionMinor: @(76),
26
- RCTVersionPatch: @(2),
26
+ RCTVersionPatch: @(4),
27
27
  RCTVersionPrerelease: [NSNull null],
28
28
  };
29
29
  });
@@ -10,7 +10,7 @@
10
10
  /**
11
11
  * UIView class for root <ModalHostView> component.
12
12
  */
13
- @interface RCTModalHostViewComponentView : RCTViewComponentView
13
+ @interface RCTModalHostViewComponentView : RCTViewComponentView <UIAdaptivePresentationControllerDelegate>
14
14
 
15
15
  /**
16
16
  * Subclasses may override this method and present the modal on different view controller.
@@ -134,9 +134,7 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
134
134
  completion:(void (^)(void))completion
135
135
  {
136
136
  UIViewController *controller = [self reactViewController];
137
- [[self _topMostViewControllerFrom:controller] presentViewController:modalViewController
138
- animated:animated
139
- completion:completion];
137
+ [controller presentViewController:modalViewController animated:animated completion:completion];
140
138
  }
141
139
 
142
140
  - (void)dismissViewController:(UIViewController *)modalViewController
@@ -151,6 +149,8 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
151
149
  {
152
150
  BOOL shouldBePresented = !_isPresented && _shouldPresent && self.window;
153
151
  if (shouldBePresented) {
152
+ self.viewController.presentationController.delegate = self;
153
+
154
154
  _isPresented = YES;
155
155
  [self presentViewController:self.viewController
156
156
  animated:_shouldAnimatePresentation
@@ -276,24 +276,14 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
276
276
  [childComponentView removeFromSuperview];
277
277
  }
278
278
 
279
- #pragma mark - Private
279
+ #pragma mark - UIAdaptivePresentationControllerDelegate
280
280
 
281
- - (UIViewController *)_topMostViewControllerFrom:(UIViewController *)rootViewController
281
+ - (void)presentationControllerDidAttemptToDismiss:(UIPresentationController *)controller
282
282
  {
283
- UIViewController *topController = rootViewController;
284
- while (topController.presentedViewController) {
285
- topController = topController.presentedViewController;
286
- }
287
- if ([topController isKindOfClass:[UINavigationController class]]) {
288
- UINavigationController *navigationController = (UINavigationController *)topController;
289
- topController = navigationController.visibleViewController;
290
- return [self _topMostViewControllerFrom:topController];
291
- } else if ([topController isKindOfClass:[UITabBarController class]]) {
292
- UITabBarController *tabBarController = (UITabBarController *)topController;
293
- topController = tabBarController.selectedViewController;
294
- return [self _topMostViewControllerFrom:topController];
283
+ auto eventEmitter = [self modalEventEmitter];
284
+ if (eventEmitter) {
285
+ eventEmitter->onRequestClose({});
295
286
  }
296
- return topController;
297
287
  }
298
288
 
299
289
  @end
@@ -443,10 +443,15 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
443
443
 
444
444
  - (void)textInputDidChangeSelection
445
445
  {
446
- [self _updateTypingAttributes];
447
446
  if (_comingFromJS) {
448
447
  return;
449
448
  }
449
+
450
+ // T207198334: Setting a new AttributedString (_comingFromJS) will trigger a selection change before the backing
451
+ // string is updated, so indicies won't point to what we want yet. Only respond to user selection change, and let
452
+ // `_setAttributedString` handle updating typing attributes if content changes.
453
+ [self _updateTypingAttributes];
454
+
450
455
  const auto &props = static_cast<const TextInputProps &>(*_props);
451
456
  if (props.traits.multiline && ![_lastStringStateWasUpdatedWith isEqual:_backedTextInputView.attributedText]) {
452
457
  [self textInputDidChange];
@@ -710,7 +715,7 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
710
715
  // https://github.com/facebook/react-native/blob/3102a58df38d96f3dacef0530e4dbb399037fcd2/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/SetSpanOperation.kt#L30
711
716
  - (void)_updateTypingAttributes
712
717
  {
713
- if (_backedTextInputView.attributedText.length > 0) {
718
+ if (_backedTextInputView.attributedText.length > 0 && _backedTextInputView.selectedTextRange != nil) {
714
719
  NSUInteger offsetStart = [_backedTextInputView offsetFromPosition:_backedTextInputView.beginningOfDocument
715
720
  toPosition:_backedTextInputView.selectedTextRange.start];
716
721
 
@@ -10,6 +10,7 @@
10
10
  #import <React/RCTConvert.h>
11
11
 
12
12
  typedef UIFont * (^RCTFontHandler)(CGFloat fontSize, NSString *fontWeightDescription);
13
+ typedef CGFloat RCTFontWeight;
13
14
 
14
15
  /**
15
16
  * React Native will use the System font for rendering by default. If you want to
@@ -19,6 +20,7 @@ typedef UIFont * (^RCTFontHandler)(CGFloat fontSize, NSString *fontWeightDescrip
19
20
  */
20
21
  RCT_EXTERN void RCTSetDefaultFontHandler(RCTFontHandler handler);
21
22
  RCT_EXTERN BOOL RCTHasFontHandlerSet(void);
23
+ RCT_EXTERN RCTFontWeight RCTGetFontWeight(UIFont *font);
22
24
 
23
25
  @interface RCTFont : NSObject
24
26
 
@@ -11,8 +11,7 @@
11
11
 
12
12
  #import <CoreText/CoreText.h>
13
13
 
14
- typedef CGFloat RCTFontWeight;
15
- static RCTFontWeight weightOfFont(UIFont *font)
14
+ RCTFontWeight RCTGetFontWeight(UIFont *font)
16
15
  {
17
16
  static NSArray<NSString *> *weightSuffixes;
18
17
  static NSArray<NSNumber *> *fontWeights;
@@ -405,7 +404,7 @@ RCT_ARRAY_CONVERTER(RCTFontVariantDescriptor)
405
404
  if (font) {
406
405
  familyName = font.familyName ?: defaultFontFamily;
407
406
  fontSize = font.pointSize ?: defaultFontSize;
408
- fontWeight = weightOfFont(font);
407
+ fontWeight = RCTGetFontWeight(font);
409
408
  isItalic = isItalicFont(font);
410
409
  isCondensed = isCondensedFont(font);
411
410
  }
@@ -453,7 +452,7 @@ RCT_ARRAY_CONVERTER(RCTFontVariantDescriptor)
453
452
  // It's actually a font name, not a font family name,
454
453
  // but we'll do what was meant, not what was said.
455
454
  familyName = font.familyName;
456
- fontWeight = weight ? fontWeight : weightOfFont(font);
455
+ fontWeight = weight ? fontWeight : RCTGetFontWeight(font);
457
456
  isItalic = style ? isItalic : isItalicFont(font);
458
457
  isCondensed = isCondensedFont(font);
459
458
  } else {
@@ -476,7 +475,7 @@ RCT_ARRAY_CONVERTER(RCTFontVariantDescriptor)
476
475
  for (NSString *name in names) {
477
476
  UIFont *match = [UIFont fontWithName:name size:fontSize];
478
477
  if (isItalic == isItalicFont(match) && isCondensed == isCondensedFont(match)) {
479
- CGFloat testWeight = weightOfFont(match);
478
+ CGFloat testWeight = RCTGetFontWeight(match);
480
479
  if (ABS(testWeight - fontWeight) < ABS(closestWeight - fontWeight)) {
481
480
  font = match;
482
481
  closestWeight = testWeight;
@@ -7280,6 +7280,8 @@ public final class com/facebook/react/views/scroll/ReactScrollViewHelper {
7280
7280
  public static final field SNAP_ALIGNMENT_END I
7281
7281
  public static final field SNAP_ALIGNMENT_START I
7282
7282
  public static final fun addScrollListener (Lcom/facebook/react/views/scroll/ReactScrollViewHelper$ScrollListener;)V
7283
+ public static final fun dispatchMomentumEndOnAnimationEnd (Landroid/view/ViewGroup;)V
7284
+ public static final fun emitLayoutChangeEvent (Landroid/view/ViewGroup;)V
7283
7285
  public static final fun emitLayoutEvent (Landroid/view/ViewGroup;)V
7284
7286
  public static final fun emitScrollBeginDragEvent (Landroid/view/ViewGroup;)V
7285
7287
  public static final fun emitScrollEndDragEvent (Landroid/view/ViewGroup;FF)V
@@ -31,9 +31,8 @@ if(CCACHE_FOUND)
31
31
  endif(CCACHE_FOUND)
32
32
 
33
33
  set(BUILD_DIR ${PROJECT_BUILD_DIR})
34
- if(CMAKE_HOST_WIN32)
35
- string(REPLACE "\\" "/" BUILD_DIR ${BUILD_DIR})
36
- endif()
34
+ file(TO_CMAKE_PATH "${BUILD_DIR}" BUILD_DIR)
35
+ file(TO_CMAKE_PATH "${REACT_ANDROID_DIR}" REACT_ANDROID_DIR)
37
36
 
38
37
  file(GLOB input_SRC CONFIGURE_DEPENDS
39
38
  ${REACT_ANDROID_DIR}/cmake-utils/default-app-setup/*.cpp
@@ -29,7 +29,12 @@
29
29
 
30
30
  #include <DefaultComponentsRegistry.h>
31
31
  #include <DefaultTurboModuleManagerDelegate.h>
32
+ #if __has_include("<autolinking.h>")
33
+ #define AUTOLINKING_AVAILABLE 1
32
34
  #include <autolinking.h>
35
+ #else
36
+ #define AUTOLINKING_AVAILABLE 0
37
+ #endif
33
38
  #include <fbjni/fbjni.h>
34
39
  #include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
35
40
  #include <rncore.h>
@@ -56,8 +61,10 @@ void registerComponents(
56
61
  REACT_NATIVE_APP_COMPONENT_REGISTRATION(registry);
57
62
  #endif
58
63
 
64
+ #if AUTOLINKING_AVAILABLE
59
65
  // And we fallback to the components autolinked
60
66
  autolinking_registerProviders(registry);
67
+ #endif
61
68
  }
62
69
 
63
70
  std::shared_ptr<TurboModule> cxxModuleProvider(
@@ -71,8 +78,12 @@ std::shared_ptr<TurboModule> cxxModuleProvider(
71
78
  // return std::make_shared<NativeCxxModuleExample>(jsInvoker);
72
79
  // }
73
80
 
81
+ #if AUTOLINKING_AVAILABLE
74
82
  // And we fallback to the CXX module providers autolinked
75
83
  return autolinking_cxxModuleProvider(name, jsInvoker);
84
+ #endif
85
+
86
+ return nullptr;
76
87
  }
77
88
 
78
89
  std::shared_ptr<TurboModule> javaModuleProvider(
@@ -101,10 +112,12 @@ std::shared_ptr<TurboModule> javaModuleProvider(
101
112
  return module;
102
113
  }
103
114
 
115
+ #if AUTOLINKING_AVAILABLE
104
116
  // And we fallback to the module providers autolinked
105
117
  if (auto module = autolinking_ModuleProvider(name, params)) {
106
118
  return module;
107
119
  }
120
+ #endif
108
121
 
109
122
  return nullptr;
110
123
  }
@@ -1,4 +1,4 @@
1
- VERSION_NAME=0.76.2
1
+ VERSION_NAME=0.76.4
2
2
  react.internal.publishingGroup=com.facebook.react
3
3
 
4
4
  android.useAndroidX=true
@@ -36,9 +36,13 @@ fun getSDKPath(): String {
36
36
  fun getSDKManagerPath(): String {
37
37
  val metaSdkManagerPath = File("${getSDKPath()}/cmdline-tools/latest/bin/sdkmanager")
38
38
  val ossSdkManagerPath = File("${getSDKPath()}/tools/bin/sdkmanager")
39
+ val windowsMetaSdkManagerPath = File("${getSDKPath()}/cmdline-tools/latest/bin/sdkmanager.bat")
40
+ val windowsOssSdkManagerPath = File("${getSDKPath()}/tools/bin/sdkmanager.bat")
39
41
  return when {
40
42
  metaSdkManagerPath.exists() -> metaSdkManagerPath.absolutePath
43
+ windowsMetaSdkManagerPath.exists() -> windowsMetaSdkManagerPath.absolutePath
41
44
  ossSdkManagerPath.exists() -> ossSdkManagerPath.absolutePath
45
+ windowsOssSdkManagerPath.exists() -> windowsOssSdkManagerPath.absolutePath
42
46
  else -> throw GradleException("Could not find sdkmanager executable.")
43
47
  }
44
48
  }
@@ -449,12 +449,18 @@ public class FabricUIManager
449
449
 
450
450
  @Override
451
451
  public void markActiveTouchForTag(int surfaceId, int reactTag) {
452
- mMountingManager.getSurfaceManager(surfaceId).markActiveTouchForTag(reactTag);
452
+ SurfaceMountingManager surfaceMountingManager = mMountingManager.getSurfaceManager(surfaceId);
453
+ if (surfaceMountingManager != null) {
454
+ surfaceMountingManager.markActiveTouchForTag(reactTag);
455
+ }
453
456
  }
454
457
 
455
458
  @Override
456
459
  public void sweepActiveTouchForTag(int surfaceId, int reactTag) {
457
- mMountingManager.getSurfaceManager(surfaceId).sweepActiveTouchForTag(reactTag);
460
+ SurfaceMountingManager surfaceMountingManager = mMountingManager.getSurfaceManager(surfaceId);
461
+ if (surfaceMountingManager != null) {
462
+ surfaceMountingManager.sweepActiveTouchForTag(reactTag);
463
+ }
458
464
  }
459
465
 
460
466
  /**
@@ -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", 76,
20
- "patch", 2,
20
+ "patch", 4,
21
21
  "prerelease", null);
22
22
  }
@@ -1544,12 +1544,20 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
1544
1544
  DEFAULT_FLING_ANIMATOR.cancel();
1545
1545
 
1546
1546
  // Update the fling animator with new values
1547
- DEFAULT_FLING_ANIMATOR
1548
- .setDuration(ReactScrollViewHelper.getDefaultScrollAnimationDuration(getContext()))
1549
- .setIntValues(start, end);
1547
+ int duration = ReactScrollViewHelper.getDefaultScrollAnimationDuration(getContext());
1548
+ DEFAULT_FLING_ANIMATOR.setDuration(duration).setIntValues(start, end);
1550
1549
 
1551
1550
  // Start the animator
1552
1551
  DEFAULT_FLING_ANIMATOR.start();
1552
+
1553
+ if (mSendMomentumEvents) {
1554
+ int xVelocity = 0;
1555
+ if (duration > 0) {
1556
+ xVelocity = (end - start) / duration;
1557
+ }
1558
+ ReactScrollViewHelper.emitScrollMomentumBeginEvent(this, xVelocity, 0);
1559
+ ReactScrollViewHelper.dispatchMomentumEndOnAnimationEnd(this);
1560
+ }
1553
1561
  }
1554
1562
 
1555
1563
  @Override
@@ -1358,12 +1358,20 @@ public class ReactScrollView extends ScrollView
1358
1358
  DEFAULT_FLING_ANIMATOR.cancel();
1359
1359
 
1360
1360
  // Update the fling animator with new values
1361
- DEFAULT_FLING_ANIMATOR
1362
- .setDuration(ReactScrollViewHelper.getDefaultScrollAnimationDuration(getContext()))
1363
- .setIntValues(start, end);
1361
+ int duration = ReactScrollViewHelper.getDefaultScrollAnimationDuration(getContext());
1362
+ DEFAULT_FLING_ANIMATOR.setDuration(duration).setIntValues(start, end);
1364
1363
 
1365
1364
  // Start the animator
1366
1365
  DEFAULT_FLING_ANIMATOR.start();
1366
+
1367
+ if (mSendMomentumEvents) {
1368
+ int yVelocity = 0;
1369
+ if (duration > 0) {
1370
+ yVelocity = (end - start) / duration;
1371
+ }
1372
+ ReactScrollViewHelper.emitScrollMomentumBeginEvent(this, 0, yVelocity);
1373
+ ReactScrollViewHelper.dispatchMomentumEndOnAnimationEnd(this);
1374
+ }
1367
1375
  }
1368
1376
 
1369
1377
  @NonNull
@@ -412,6 +412,31 @@ public object ReactScrollViewHelper {
412
412
  })
413
413
  }
414
414
 
415
+ @JvmStatic
416
+ public fun <T> dispatchMomentumEndOnAnimationEnd(scrollView: T) where
417
+ T : HasFlingAnimator?,
418
+ T : HasScrollEventThrottle?,
419
+ T : ViewGroup {
420
+ scrollView
421
+ .getFlingAnimator()
422
+ .addListener(
423
+ object : Animator.AnimatorListener {
424
+ override fun onAnimationStart(animator: Animator) = Unit
425
+
426
+ override fun onAnimationEnd(animator: Animator) {
427
+ emitScrollMomentumEndEvent(scrollView)
428
+ animator.removeListener(this)
429
+ }
430
+
431
+ override fun onAnimationCancel(animator: Animator) {
432
+ emitScrollMomentumEndEvent(scrollView)
433
+ animator.removeListener(this)
434
+ }
435
+
436
+ override fun onAnimationRepeat(animator: Animator) = Unit
437
+ })
438
+ }
439
+
415
440
  @JvmStatic
416
441
  public fun <T> predictFinalScrollPosition(
417
442
  scrollView: T,
@@ -17,7 +17,7 @@ namespace facebook::react {
17
17
  constexpr struct {
18
18
  int32_t Major = 0;
19
19
  int32_t Minor = 76;
20
- int32_t Patch = 2;
20
+ int32_t Patch = 4;
21
21
  std::string_view Prerelease = "";
22
22
  } ReactNativeVersion;
23
23
 
@@ -7,6 +7,7 @@
7
7
 
8
8
  #import "RCTFontUtils.h"
9
9
  #import <CoreText/CoreText.h>
10
+ #import <React/RCTFont.h>
10
11
 
11
12
  #import <algorithm>
12
13
  #import <cmath>
@@ -45,12 +46,6 @@ static RCTFontProperties RCTResolveFontProperties(
45
46
  return fontProperties;
46
47
  }
47
48
 
48
- static UIFontWeight RCTGetFontWeight(UIFont *font)
49
- {
50
- NSDictionary *traits = [font.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute];
51
- return [traits[UIFontWeightTrait] doubleValue];
52
- }
53
-
54
49
  static RCTFontStyle RCTGetFontStyle(UIFont *font)
55
50
  {
56
51
  NSDictionary *traits = [font.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute];
@@ -165,17 +160,22 @@ UIFont *RCTFontWithFontProperties(RCTFontProperties fontProperties)
165
160
  font = RCTDefaultFontWithFontProperties(fontProperties);
166
161
  } else {
167
162
  NSArray<NSString *> *fontNames = [UIFont fontNamesForFamilyName:fontProperties.family];
163
+ UIFontWeight fontWeight = fontProperties.weight;
168
164
 
169
165
  if (fontNames.count == 0) {
170
166
  // Gracefully handle being given a font name rather than font family, for
171
167
  // example: "Helvetica Light Oblique" rather than just "Helvetica".
172
168
  font = [UIFont fontWithName:fontProperties.family size:effectiveFontSize];
173
-
174
- if (!font) {
169
+ if (font) {
170
+ fontNames = [UIFont fontNamesForFamilyName:font.familyName];
171
+ fontWeight = fontWeight ?: RCTGetFontWeight(font);
172
+ } else {
175
173
  // Failback to system font.
176
174
  font = [UIFont systemFontOfSize:effectiveFontSize weight:fontProperties.weight];
177
175
  }
178
- } else {
176
+ }
177
+
178
+ if (fontNames.count > 0) {
179
179
  // Get the closest font that matches the given weight for the fontFamily
180
180
  CGFloat closestWeight = INFINITY;
181
181
  for (NSString *name in fontNames) {
@@ -186,7 +186,7 @@ UIFont *RCTFontWithFontProperties(RCTFontProperties fontProperties)
186
186
  }
187
187
 
188
188
  CGFloat testWeight = RCTGetFontWeight(fontMatch);
189
- if (ABS(testWeight - fontProperties.weight) < ABS(closestWeight - fontProperties.weight)) {
189
+ if (ABS(testWeight - fontWeight) < ABS(closestWeight - fontWeight)) {
190
190
  font = fontMatch;
191
191
  closestWeight = testWeight;
192
192
  }
@@ -126,20 +126,41 @@ std::shared_ptr<ShadowNode> UIManager::cloneNode(
126
126
 
127
127
  if (!rawProps.isEmpty()) {
128
128
  if (family.nativeProps_DEPRECATED != nullptr) {
129
+ // 1. update the nativeProps_DEPRECATED props.
130
+ //
131
+ // In this step, we want the most recent value for the props
132
+ // managed by setNativeProps.
129
133
  // Values in `rawProps` patch (take precedence over)
130
- // `nativeProps_DEPRECATED`. For example, if both `nativeProps_DEPRECATED`
131
- // and `rawProps` contain key 'A'. Value from `rawProps` overrides what
132
- // was previously in `nativeProps_DEPRECATED`.
134
+ // `nativeProps_DEPRECATED`. For example, if both
135
+ // `nativeProps_DEPRECATED` and `rawProps` contain key 'A'.
136
+ // Value from `rawProps` overrides what was previously in
137
+ // `nativeProps_DEPRECATED`. Notice that the `nativeProps_DEPRECATED`
138
+ // patch will not get more props from `rawProps`: if the key is not
139
+ // present in `nativeProps_DEPRECATED`, it will not be added.
140
+ //
141
+ // The result of this operation is the new `nativeProps_DEPRECATED`.
133
142
  family.nativeProps_DEPRECATED =
134
143
  std::make_unique<folly::dynamic>(mergeDynamicProps(
135
- *family.nativeProps_DEPRECATED,
136
- (folly::dynamic)rawProps,
144
+ *family.nativeProps_DEPRECATED, // source
145
+ (folly::dynamic)rawProps, // patch
137
146
  NullValueStrategy::Ignore));
138
147
 
148
+ // 2. Compute the final set of props.
149
+ //
150
+ // This step takes the new props handled by `setNativeProps` and
151
+ // merges them in the `rawProps` managed by React.
152
+ // The new props handled by `nativeProps` now takes precedence
153
+ // on the props handled by React, as we want to make sure that
154
+ // all the props are applied to the component.
155
+ // We use these finalProps as source of truth for the component.
156
+ auto finalProps = mergeDynamicProps(
157
+ (folly::dynamic)rawProps, // source
158
+ *family.nativeProps_DEPRECATED, // patch
159
+ NullValueStrategy::Override);
160
+
161
+ // 3. Clone the props by using finalProps.
139
162
  props = componentDescriptor.cloneProps(
140
- propsParserContext,
141
- shadowNode.getProps(),
142
- RawProps(*family.nativeProps_DEPRECATED));
163
+ propsParserContext, shadowNode.getProps(), RawProps(finalProps));
143
164
  } else {
144
165
  props = componentDescriptor.cloneProps(
145
166
  propsParserContext, shadowNode.getProps(), std::move(rawProps));
package/jest/setup.js CHANGED
@@ -417,4 +417,8 @@ jest
417
417
  return jest.requireActual(
418
418
  '../Libraries/ReactNative/RendererImplementation',
419
419
  );
420
- });
420
+ })
421
+ .mock('../Libraries/Utilities/useColorScheme', () => ({
422
+ __esModule: true,
423
+ default: jest.fn().mockReturnValue('light'),
424
+ }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native",
3
- "version": "0.76.2",
3
+ "version": "0.76.4",
4
4
  "description": "A framework for building native apps using React",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -109,13 +109,13 @@
109
109
  },
110
110
  "dependencies": {
111
111
  "@jest/create-cache-key-function": "^29.6.3",
112
- "@react-native/assets-registry": "0.76.2",
113
- "@react-native/codegen": "0.76.2",
114
- "@react-native/community-cli-plugin": "0.76.2",
115
- "@react-native/gradle-plugin": "0.76.2",
116
- "@react-native/js-polyfills": "0.76.2",
117
- "@react-native/normalize-colors": "0.76.2",
118
- "@react-native/virtualized-lists": "0.76.2",
112
+ "@react-native/assets-registry": "0.76.4",
113
+ "@react-native/codegen": "0.76.4",
114
+ "@react-native/community-cli-plugin": "0.76.4",
115
+ "@react-native/gradle-plugin": "0.76.4",
116
+ "@react-native/js-polyfills": "0.76.4",
117
+ "@react-native/normalize-colors": "0.76.4",
118
+ "@react-native/virtualized-lists": "0.76.4",
119
119
  "abort-controller": "^3.0.0",
120
120
  "anser": "^1.4.9",
121
121
  "ansi-regex": "^5.0.0",
@@ -152,6 +152,7 @@ function extractLibrariesFromJSON(configFile, dependencyPath) {
152
152
  const config = configFile.codegenConfig;
153
153
  return [
154
154
  {
155
+ libraryName: configFile.name,
155
156
  config,
156
157
  libraryPath: dependencyPath,
157
158
  },
@@ -251,19 +252,23 @@ function findExternalLibraries(pkgJson, projectRoot) {
251
252
  });
252
253
  }
253
254
 
254
- function findLibrariesFromReactNativeConfig(projectRoot) {
255
+ function readRNConfigJSFile(projectRoot) {
255
256
  const rnConfigFileName = 'react-native.config.js';
256
257
 
257
- console.log(
258
- `\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in ${rnConfigFileName}`,
259
- );
260
-
261
258
  const rnConfigFilePath = path.resolve(projectRoot, rnConfigFileName);
262
259
 
263
260
  if (!fs.existsSync(rnConfigFilePath)) {
264
261
  return [];
265
262
  }
266
- const rnConfig = require(rnConfigFilePath);
263
+ return require(rnConfigFilePath);
264
+ }
265
+
266
+ function findLibrariesFromReactNativeConfig(projectRoot) {
267
+ console.log(
268
+ `\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in react-native.config.js`,
269
+ );
270
+
271
+ const rnConfig = readRNConfigJSFile(projectRoot);
267
272
 
268
273
  if (rnConfig.dependencies == null) {
269
274
  return [];
@@ -289,6 +294,33 @@ function findLibrariesFromReactNativeConfig(projectRoot) {
289
294
  });
290
295
  }
291
296
 
297
+ // Function to look for libraries explicitly unlinked from the app
298
+ // through the react-native.config.js file.
299
+ // If this happens, it might be that the app does not need
300
+ // to generate code for that library as it won't be used by that platform
301
+ // @return { [libraryName: string]: [platform: string] }
302
+ function findNotLinkedLibraries(projectRoot) {
303
+ const rnConfig = readRNConfigJSFile(projectRoot);
304
+
305
+ if (rnConfig.dependencies == null) {
306
+ return {};
307
+ }
308
+
309
+ let notLinkedLibraries = {};
310
+
311
+ Object.keys(rnConfig.dependencies).forEach(name => {
312
+ const dependency = rnConfig.dependencies[name];
313
+ let notLinkedPlatforms = [];
314
+ Object.keys(dependency.platforms).forEach(platform => {
315
+ if (dependency.platforms[platform] == null) {
316
+ notLinkedPlatforms.push(platform);
317
+ }
318
+ });
319
+ notLinkedLibraries[name] = notLinkedPlatforms;
320
+ });
321
+ return notLinkedLibraries;
322
+ }
323
+
292
324
  function findProjectRootLibraries(pkgJson, projectRoot) {
293
325
  console.log('[Codegen] Searching for codegen-enabled libraries in the app.');
294
326
 
@@ -694,6 +726,8 @@ function execute(projectRoot, targetPlatform, baseOutputPath) {
694
726
  let platforms =
695
727
  targetPlatform === 'all' ? supportedPlatforms : [targetPlatform];
696
728
 
729
+ const notLinkedLibraries = findNotLinkedLibraries(projectRoot);
730
+
697
731
  for (const platform of platforms) {
698
732
  const outputPath = computeOutputPath(
699
733
  projectRoot,
@@ -702,7 +736,19 @@ function execute(projectRoot, targetPlatform, baseOutputPath) {
702
736
  platform,
703
737
  );
704
738
 
705
- const schemaInfos = generateSchemaInfos(libraries);
739
+ const schemaInfos = generateSchemaInfos(
740
+ libraries.filter(library => {
741
+ const unlinkedPlatforms = notLinkedLibraries[library.libraryName];
742
+ if (unlinkedPlatforms && unlinkedPlatforms.includes(platform)) {
743
+ console.log(
744
+ `[Codegen - ${library.libraryName}] Skipping Codegen on ${platform}`,
745
+ );
746
+ return false;
747
+ }
748
+ return true;
749
+ }),
750
+ );
751
+
706
752
  generateNativeCode(
707
753
  outputPath,
708
754
  schemaInfos.filter(schemaInfo =>
Binary file
Binary file
Binary file
Binary file