react-native 0.76.1 → 0.76.2

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 (26) hide show
  1. package/Libraries/AppDelegate/React-RCTAppDelegate.podspec +1 -1
  2. package/Libraries/Core/ReactNativeVersion.js +1 -1
  3. package/Libraries/Core/setUpErrorHandling.js +1 -7
  4. package/Libraries/LogBox/Data/LogBoxData.js +2 -2
  5. package/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h +1 -0
  6. package/React/Base/RCTVersion.m +1 -1
  7. package/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +47 -3
  8. package/ReactAndroid/api/ReactAndroid.api +0 -1
  9. package/ReactAndroid/cmake-utils/ReactNative-application.cmake +1 -1
  10. package/ReactAndroid/gradle.properties +1 -1
  11. package/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.kt +2 -0
  12. package/ReactAndroid/src/main/java/com/facebook/react/modules/core/TimingModule.kt +0 -8
  13. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
  14. package/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt +8 -1
  15. package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
  16. package/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputShadowNode.cpp +3 -2
  17. package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h +12 -1
  18. package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm +165 -2
  19. package/cli.js +1 -1
  20. package/package.json +8 -8
  21. package/scripts/codegen/generate-artifacts-executor.js +3 -3
  22. package/sdks/.hermesversion +1 -1
  23. package/sdks/hermesc/osx-bin/hermes +0 -0
  24. package/sdks/hermesc/osx-bin/hermesc +0 -0
  25. package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
  26. package/types/modules/Codegen.d.ts +6 -0
@@ -63,7 +63,7 @@ Pod::Spec.new do |s|
63
63
  "CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
64
64
  "DEFINES_MODULE" => "YES"
65
65
  }
66
- s.user_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/Headers/Private/React-Core\""}
66
+ s.user_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/Headers/Private/React-Core\" \"$(PODS_ROOT)/Headers/Private/Yoga\""}
67
67
 
68
68
  s.dependency "React-Core"
69
69
  s.dependency "RCT-Folly", folly_version
@@ -16,7 +16,7 @@ const version: $ReadOnly<{
16
16
  }> = {
17
17
  major: 0,
18
18
  minor: 76,
19
- patch: 1,
19
+ patch: 2,
20
20
  prerelease: null,
21
21
  };
22
22
 
@@ -21,13 +21,7 @@ ExceptionsManager.installConsoleErrorReporter();
21
21
  if (!global.__fbDisableExceptionsManager) {
22
22
  const handleError = (e: mixed, isFatal: boolean) => {
23
23
  try {
24
- // TODO(T196834299): We should really use a c++ turbomodule for this
25
- if (
26
- !global.RN$handleException ||
27
- !global.RN$handleException(e, isFatal)
28
- ) {
29
- ExceptionsManager.handleException(e, isFatal);
30
- }
24
+ ExceptionsManager.handleException(e, isFatal);
31
25
  } catch (ee) {
32
26
  console.log('Failed to print error: ', ee.message);
33
27
  throw e;
@@ -82,9 +82,9 @@ let warningFilter: WarningFilter = function (format) {
82
82
  return {
83
83
  finalFormat: format,
84
84
  forceDialogImmediately: false,
85
- suppressDialog_LEGACY: true,
85
+ suppressDialog_LEGACY: false,
86
86
  suppressCompletely: false,
87
- monitorEvent: 'unknown',
87
+ monitorEvent: 'warning_unhandled',
88
88
  monitorListVersion: 0,
89
89
  monitorSampleRate: 1,
90
90
  };
@@ -35,6 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
35
35
  @property (nonatomic, assign, readonly) CGFloat zoomScale;
36
36
  @property (nonatomic, assign, readonly) CGPoint contentOffset;
37
37
  @property (nonatomic, assign, readonly) UIEdgeInsets contentInset;
38
+ @property (nullable, nonatomic, copy) NSDictionary<NSAttributedStringKey, id> *typingAttributes;
38
39
 
39
40
  // This protocol disallows direct access to `selectedTextRange` property because
40
41
  // unwise usage of it can break the `delegate` behavior. So, we always have to
@@ -23,7 +23,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
23
23
  __rnVersion = @{
24
24
  RCTVersionMajor: @(0),
25
25
  RCTVersionMinor: @(76),
26
- RCTVersionPatch: @(1),
26
+ RCTVersionPatch: @(2),
27
27
  RCTVersionPrerelease: [NSNull null],
28
28
  };
29
29
  });
@@ -61,6 +61,13 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
61
61
  */
62
62
  BOOL _comingFromJS;
63
63
  BOOL _didMoveToWindow;
64
+
65
+ /*
66
+ * Newly initialized default typing attributes contain a no-op NSParagraphStyle and NSShadow. These cause inequality
67
+ * between the AttributedString backing the input and those generated from state. We store these attributes to make
68
+ * later comparison insensitive to them.
69
+ */
70
+ NSDictionary<NSAttributedStringKey, id> *_originalTypingAttributes;
64
71
  }
65
72
 
66
73
  #pragma mark - UIView overrides
@@ -76,6 +83,7 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
76
83
  _ignoreNextTextInputCall = NO;
77
84
  _comingFromJS = NO;
78
85
  _didMoveToWindow = NO;
86
+ _originalTypingAttributes = [_backedTextInputView.typingAttributes copy];
79
87
 
80
88
  [self addSubview:_backedTextInputView];
81
89
  [self initializeReturnKeyType];
@@ -84,6 +92,20 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
84
92
  return self;
85
93
  }
86
94
 
95
+ - (void)updateEventEmitter:(const EventEmitter::Shared &)eventEmitter
96
+ {
97
+ [super updateEventEmitter:eventEmitter];
98
+
99
+ NSMutableDictionary<NSAttributedStringKey, id> *defaultAttributes =
100
+ [_backedTextInputView.defaultTextAttributes mutableCopy];
101
+
102
+ RCTWeakEventEmitterWrapper *eventEmitterWrapper = [RCTWeakEventEmitterWrapper new];
103
+ eventEmitterWrapper.eventEmitter = _eventEmitter;
104
+ defaultAttributes[RCTAttributedStringEventEmitterKey] = eventEmitterWrapper;
105
+
106
+ _backedTextInputView.defaultTextAttributes = defaultAttributes;
107
+ }
108
+
87
109
  - (void)didMoveToWindow
88
110
  {
89
111
  [super didMoveToWindow];
@@ -236,8 +258,11 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
236
258
  }
237
259
 
238
260
  if (newTextInputProps.textAttributes != oldTextInputProps.textAttributes) {
239
- _backedTextInputView.defaultTextAttributes =
261
+ NSMutableDictionary<NSAttributedStringKey, id> *defaultAttributes =
240
262
  RCTNSTextAttributesFromTextAttributes(newTextInputProps.getEffectiveTextAttributes(RCTFontSizeMultiplier()));
263
+ defaultAttributes[RCTAttributedStringEventEmitterKey] =
264
+ _backedTextInputView.defaultTextAttributes[RCTAttributedStringEventEmitterKey];
265
+ _backedTextInputView.defaultTextAttributes = defaultAttributes;
241
266
  }
242
267
 
243
268
  if (newTextInputProps.selectionColor != oldTextInputProps.selectionColor) {
@@ -418,6 +443,7 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
418
443
 
419
444
  - (void)textInputDidChangeSelection
420
445
  {
446
+ [self _updateTypingAttributes];
421
447
  if (_comingFromJS) {
422
448
  return;
423
449
  }
@@ -674,9 +700,26 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
674
700
  [_backedTextInputView scrollRangeToVisible:NSMakeRange(offsetStart, 0)];
675
701
  }
676
702
  [self _restoreTextSelection];
703
+ [self _updateTypingAttributes];
677
704
  _lastStringStateWasUpdatedWith = attributedString;
678
705
  }
679
706
 
707
+ // Ensure that newly typed text will inherit any custom attributes. We follow the logic of RN Android, where attributes
708
+ // to the left of the cursor are copied into new text, unless we are at the start of the field, in which case we will
709
+ // copy the attributes from text to the right. This allows consistency between backed input and new AttributedText
710
+ // 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
+ - (void)_updateTypingAttributes
712
+ {
713
+ if (_backedTextInputView.attributedText.length > 0) {
714
+ NSUInteger offsetStart = [_backedTextInputView offsetFromPosition:_backedTextInputView.beginningOfDocument
715
+ toPosition:_backedTextInputView.selectedTextRange.start];
716
+
717
+ NSUInteger samplePoint = offsetStart == 0 ? 0 : offsetStart - 1;
718
+ _backedTextInputView.typingAttributes = [_backedTextInputView.attributedText attributesAtIndex:samplePoint
719
+ effectiveRange:NULL];
720
+ }
721
+ }
722
+
680
723
  - (void)_setMultiline:(BOOL)multiline
681
724
  {
682
725
  [_backedTextInputView removeFromSuperview];
@@ -732,9 +775,10 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
732
775
  _backedTextInputView.markedTextRange || _backedTextInputView.isSecureTextEntry || fontHasBeenUpdatedBySystem;
733
776
 
734
777
  if (shouldFallbackToBareTextComparison) {
735
- return ([newText.string isEqualToString:oldText.string]);
778
+ return [newText.string isEqualToString:oldText.string];
736
779
  } else {
737
- return ([newText isEqualToAttributedString:oldText]);
780
+ return RCTIsAttributedStringEffectivelySame(
781
+ newText, oldText, _originalTypingAttributes, static_cast<const TextInputProps &>(*_props).textAttributes);
738
782
  }
739
783
  }
740
784
 
@@ -3306,7 +3306,6 @@ public final class com/facebook/react/modules/core/TimingModule : com/facebook/f
3306
3306
  public fun createTimer (DDDZ)V
3307
3307
  public fun deleteTimer (D)V
3308
3308
  public fun emitTimeDriftWarning (Ljava/lang/String;)V
3309
- public fun initialize ()V
3310
3309
  public fun invalidate ()V
3311
3310
  public fun setSendIdleEvents (Z)V
3312
3311
  }
@@ -36,7 +36,7 @@ if(CMAKE_HOST_WIN32)
36
36
  endif()
37
37
 
38
38
  file(GLOB input_SRC CONFIGURE_DEPENDS
39
- *.cpp
39
+ ${REACT_ANDROID_DIR}/cmake-utils/default-app-setup/*.cpp
40
40
  ${BUILD_DIR}/generated/autolinking/src/main/jni/*.cpp)
41
41
 
42
42
  add_library(${CMAKE_PROJECT_NAME} SHARED ${input_SRC})
@@ -1,4 +1,4 @@
1
- VERSION_NAME=0.76.1
1
+ VERSION_NAME=0.76.2
2
2
  react.internal.publishingGroup=com.facebook.react
3
3
 
4
4
  android.useAndroidX=true
@@ -65,6 +65,7 @@ public open class JavaTimerManager(
65
65
 
66
66
  init {
67
67
  reactApplicationContext.addLifecycleEventListener(this)
68
+ HeadlessJsTaskContext.getInstance(reactApplicationContext).addTaskEventListener(this)
68
69
  }
69
70
 
70
71
  override fun onHostPause() {
@@ -103,6 +104,7 @@ public open class JavaTimerManager(
103
104
  }
104
105
 
105
106
  public open fun onInstanceDestroy() {
107
+ HeadlessJsTaskContext.getInstance(reactApplicationContext).removeTaskEventListener(this)
106
108
  reactApplicationContext.removeLifecycleEventListener(this)
107
109
  clearFrameCallback()
108
110
  clearChoreographerIdleCallback()
@@ -12,7 +12,6 @@ import com.facebook.react.bridge.ReactApplicationContext
12
12
  import com.facebook.react.bridge.WritableArray
13
13
  import com.facebook.react.common.annotations.VisibleForTesting
14
14
  import com.facebook.react.devsupport.interfaces.DevSupportManager
15
- import com.facebook.react.jstasks.HeadlessJsTaskContext
16
15
  import com.facebook.react.module.annotations.ReactModule
17
16
 
18
17
  /** Native module for JS timer execution. Timers fire on frame boundaries. */
@@ -24,11 +23,6 @@ public class TimingModule(
24
23
  private val javaTimerManager: JavaTimerManager =
25
24
  JavaTimerManager(reactContext, this, ReactChoreographer.getInstance(), devSupportManager)
26
25
 
27
- override fun initialize() {
28
- HeadlessJsTaskContext.getInstance(getReactApplicationContext())
29
- .addTaskEventListener(javaTimerManager)
30
- }
31
-
32
26
  override fun createTimer(
33
27
  callbackIDDouble: Double,
34
28
  durationDouble: Double,
@@ -68,8 +62,6 @@ public class TimingModule(
68
62
  }
69
63
 
70
64
  override fun invalidate() {
71
- val headlessJsTaskContext = HeadlessJsTaskContext.getInstance(getReactApplicationContext())
72
- headlessJsTaskContext.removeTaskEventListener(javaTimerManager)
73
65
  javaTimerManager.onInstanceDestroy()
74
66
  }
75
67
 
@@ -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", 1,
20
+ "patch", 2,
21
21
  "prerelease", null);
22
22
  }
@@ -296,7 +296,14 @@ public class ReactModalHostView(context: ThemedReactContext) :
296
296
  * changed. This has the pleasant side-effect of us not having to preface all Modals with "top:
297
297
  * statusBarHeight", since that margin will be included in the FrameLayout.
298
298
  */
299
- get() = FrameLayout(context).apply { addView(dialogRootViewGroup) }
299
+ get() =
300
+ FrameLayout(context).apply {
301
+ addView(dialogRootViewGroup)
302
+ if (!statusBarTranslucent) {
303
+ // this is needed to prevent content hiding behind systems bars < API 30
304
+ this.fitsSystemWindows = true
305
+ }
306
+ }
300
307
 
301
308
  /**
302
309
  * updateProperties will update the properties that do not require us to recreate the dialog
@@ -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 = 1;
20
+ int32_t Patch = 2;
21
21
  std::string_view Prerelease = "";
22
22
  } ReactNativeVersion;
23
23
 
@@ -83,7 +83,7 @@ AttributedString TextInputShadowNode::getAttributedString(
83
83
  .string = getConcreteProps().text,
84
84
  .textAttributes = textAttributes,
85
85
  // TODO: Is this really meant to be by value?
86
- .parentShadowView = ShadowView{}});
86
+ .parentShadowView = ShadowView(*this)});
87
87
 
88
88
  auto attachments = Attachments{};
89
89
  BaseTextShadowNode::buildAttributedString(
@@ -110,7 +110,8 @@ void TextInputShadowNode::updateStateIfNeeded(
110
110
  (!state.layoutManager || state.layoutManager == textLayoutManager_) &&
111
111
  "`StateData` refers to a different `TextLayoutManager`");
112
112
 
113
- if (state.reactTreeAttributedString == reactTreeAttributedString &&
113
+ if (state.reactTreeAttributedString.isContentEqual(
114
+ reactTreeAttributedString) &&
114
115
  state.layoutManager == textLayoutManager_) {
115
116
  return;
116
117
  }
@@ -22,7 +22,7 @@ NSString *const RCTTextAttributesAccessibilityRoleAttributeName = @"Accessibilit
22
22
  /*
23
23
  * Creates `NSTextAttributes` from given `facebook::react::TextAttributes`
24
24
  */
25
- NSDictionary<NSAttributedStringKey, id> *RCTNSTextAttributesFromTextAttributes(
25
+ NSMutableDictionary<NSAttributedStringKey, id> *RCTNSTextAttributesFromTextAttributes(
26
26
  const facebook::react::TextAttributes &textAttributes);
27
27
 
28
28
  /*
@@ -41,6 +41,17 @@ NSString *RCTNSStringFromStringApplyingTextTransform(NSString *string, facebook:
41
41
 
42
42
  void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText);
43
43
 
44
+ /*
45
+ * Whether two `NSAttributedString` lead to the same underlying displayed text, even if they are not strictly equal.
46
+ * I.e. is one string substitutable for the other when backing a control (which may have some ignorable attributes
47
+ * provided).
48
+ */
49
+ BOOL RCTIsAttributedStringEffectivelySame(
50
+ NSAttributedString *text1,
51
+ NSAttributedString *text2,
52
+ NSDictionary<NSAttributedStringKey, id> *insensitiveAttributes,
53
+ const facebook::react::TextAttributes &baseTextAttributes);
54
+
44
55
  @interface RCTWeakEventEmitterWrapper : NSObject
45
56
  @property (nonatomic, assign) facebook::react::SharedEventEmitter eventEmitter;
46
57
  @end
@@ -35,6 +35,24 @@ using namespace facebook::react;
35
35
  _weakEventEmitter.reset();
36
36
  }
37
37
 
38
+ - (BOOL)isEqual:(id)object
39
+ {
40
+ // We consider the underlying EventEmitter as the identity
41
+ if (![object isKindOfClass:[self class]]) {
42
+ return NO;
43
+ }
44
+
45
+ auto thisEventEmitter = [self eventEmitter];
46
+ auto otherEventEmitter = [((RCTWeakEventEmitterWrapper *)object) eventEmitter];
47
+ return thisEventEmitter == otherEventEmitter;
48
+ }
49
+
50
+ - (NSUInteger)hash
51
+ {
52
+ // We consider the underlying EventEmitter as the identity
53
+ return (NSUInteger)_weakEventEmitter.lock().get();
54
+ }
55
+
38
56
  @end
39
57
 
40
58
  inline static UIFontWeight RCTUIFontWeightFromInteger(NSInteger fontWeight)
@@ -178,7 +196,8 @@ inline static UIColor *RCTEffectiveBackgroundColorFromTextAttributes(const TextA
178
196
  return effectiveBackgroundColor ?: [UIColor clearColor];
179
197
  }
180
198
 
181
- NSDictionary<NSAttributedStringKey, id> *RCTNSTextAttributesFromTextAttributes(const TextAttributes &textAttributes)
199
+ NSMutableDictionary<NSAttributedStringKey, id> *RCTNSTextAttributesFromTextAttributes(
200
+ const TextAttributes &textAttributes)
182
201
  {
183
202
  NSMutableDictionary<NSAttributedStringKey, id> *attributes = [NSMutableDictionary dictionaryWithCapacity:10];
184
203
 
@@ -302,7 +321,7 @@ NSDictionary<NSAttributedStringKey, id> *RCTNSTextAttributesFromTextAttributes(c
302
321
  attributes[RCTTextAttributesAccessibilityRoleAttributeName] = [NSString stringWithUTF8String:roleStr.c_str()];
303
322
  }
304
323
 
305
- return [attributes copy];
324
+ return attributes;
306
325
  }
307
326
 
308
327
  void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText)
@@ -466,3 +485,147 @@ NSString *RCTNSStringFromStringApplyingTextTransform(NSString *string, TextTrans
466
485
  return string;
467
486
  }
468
487
  }
488
+
489
+ static BOOL RCTIsParagraphStyleEffectivelySame(
490
+ NSParagraphStyle *style1,
491
+ NSParagraphStyle *style2,
492
+ const TextAttributes &baseTextAttributes)
493
+ {
494
+ if (style1 == nil || style2 == nil) {
495
+ return style1 == nil && style2 == nil;
496
+ }
497
+
498
+ // The NSParagraphStyle included as part of typingAttributes may eventually resolve "natural" directions to
499
+ // physical direction, so we should compare resolved directions
500
+ auto naturalAlignment =
501
+ baseTextAttributes.layoutDirection.value_or(LayoutDirection::LeftToRight) == LayoutDirection::LeftToRight
502
+ ? NSTextAlignmentLeft
503
+ : NSTextAlignmentRight;
504
+
505
+ NSWritingDirection naturalBaseWritingDirection = baseTextAttributes.baseWritingDirection.has_value()
506
+ ? RCTNSWritingDirectionFromWritingDirection(baseTextAttributes.baseWritingDirection.value())
507
+ : [NSParagraphStyle defaultWritingDirectionForLanguage:nil];
508
+
509
+ if (style1.alignment == NSTextAlignmentNatural || style1.baseWritingDirection == NSWritingDirectionNatural) {
510
+ NSMutableParagraphStyle *mutableStyle1 = [style1 mutableCopy];
511
+ style1 = mutableStyle1;
512
+
513
+ if (mutableStyle1.alignment == NSTextAlignmentNatural) {
514
+ mutableStyle1.alignment = naturalAlignment;
515
+ }
516
+
517
+ if (mutableStyle1.baseWritingDirection == NSWritingDirectionNatural) {
518
+ mutableStyle1.baseWritingDirection = naturalBaseWritingDirection;
519
+ }
520
+ }
521
+
522
+ if (style2.alignment == NSTextAlignmentNatural || style2.baseWritingDirection == NSWritingDirectionNatural) {
523
+ NSMutableParagraphStyle *mutableStyle2 = [style2 mutableCopy];
524
+ style2 = mutableStyle2;
525
+
526
+ if (mutableStyle2.alignment == NSTextAlignmentNatural) {
527
+ mutableStyle2.alignment = naturalAlignment;
528
+ }
529
+
530
+ if (mutableStyle2.baseWritingDirection == NSWritingDirectionNatural) {
531
+ mutableStyle2.baseWritingDirection = naturalBaseWritingDirection;
532
+ }
533
+ }
534
+
535
+ return [style1 isEqual:style2];
536
+ }
537
+
538
+ static BOOL RCTIsAttributeEffectivelySame(
539
+ NSAttributedStringKey attributeKey,
540
+ NSDictionary<NSAttributedStringKey, id> *attributes1,
541
+ NSDictionary<NSAttributedStringKey, id> *attributes2,
542
+ NSDictionary<NSAttributedStringKey, id> *insensitiveAttributes,
543
+ const TextAttributes &baseTextAttributes)
544
+ {
545
+ id attribute1 = attributes1[attributeKey] ?: insensitiveAttributes[attributeKey];
546
+ id attribute2 = attributes2[attributeKey] ?: insensitiveAttributes[attributeKey];
547
+
548
+ // Normalize attributes which can inexact but still effectively the same
549
+ if ([attributeKey isEqualToString:NSParagraphStyleAttributeName]) {
550
+ return RCTIsParagraphStyleEffectivelySame(attribute1, attribute2, baseTextAttributes);
551
+ }
552
+
553
+ // Otherwise rely on built-in comparison
554
+ return [attribute1 isEqual:attribute2];
555
+ }
556
+
557
+ BOOL RCTIsAttributedStringEffectivelySame(
558
+ NSAttributedString *text1,
559
+ NSAttributedString *text2,
560
+ NSDictionary<NSAttributedStringKey, id> *insensitiveAttributes,
561
+ const TextAttributes &baseTextAttributes)
562
+ {
563
+ if (![text1.string isEqualToString:text2.string]) {
564
+ return NO;
565
+ }
566
+
567
+ // We check that for every fragment in the old string
568
+ // 1. The new string's fragment overlapping the first spans the same characters
569
+ // 2. The attributes of each matching fragment are the same, ignoring those which match insensitive attibutes
570
+ __block BOOL areAttributesSame = YES;
571
+ [text1 enumerateAttributesInRange:NSMakeRange(0, text1.length)
572
+ options:0
573
+ usingBlock:^(
574
+ NSDictionary<NSAttributedStringKey, id> *text1Attributes,
575
+ NSRange text1Range,
576
+ BOOL *text1Stop) {
577
+ [text2 enumerateAttributesInRange:text1Range
578
+ options:0
579
+ usingBlock:^(
580
+ NSDictionary<NSAttributedStringKey, id> *text2Attributes,
581
+ NSRange text2Range,
582
+ BOOL *text2Stop) {
583
+ if (!NSEqualRanges(text1Range, text2Range)) {
584
+ areAttributesSame = NO;
585
+ *text1Stop = YES;
586
+ *text2Stop = YES;
587
+ return;
588
+ }
589
+
590
+ // Compare every attribute in text1 to the corresponding attribute
591
+ // in text2, or the set of insensitive attributes if not present
592
+ for (NSAttributedStringKey key in text1Attributes) {
593
+ if (!RCTIsAttributeEffectivelySame(
594
+ key,
595
+ text1Attributes,
596
+ text2Attributes,
597
+ insensitiveAttributes,
598
+ baseTextAttributes)) {
599
+ areAttributesSame = NO;
600
+ *text1Stop = YES;
601
+ *text2Stop = YES;
602
+ return;
603
+ }
604
+ }
605
+
606
+ for (NSAttributedStringKey key in text2Attributes) {
607
+ // We have already compared this attribute if it is present in
608
+ // both
609
+ if (text1Attributes[key] != nil) {
610
+ continue;
611
+ }
612
+
613
+ // But we still need to compare attributes if it is only present
614
+ // in text 2, to compare against insensitive attributes
615
+ if (!RCTIsAttributeEffectivelySame(
616
+ key,
617
+ text1Attributes,
618
+ text2Attributes,
619
+ insensitiveAttributes,
620
+ baseTextAttributes)) {
621
+ areAttributesSame = NO;
622
+ *text1Stop = YES;
623
+ *text2Stop = YES;
624
+ return;
625
+ }
626
+ }
627
+ }];
628
+ }];
629
+
630
+ return areAttributesSame;
631
+ }
package/cli.js CHANGED
@@ -204,7 +204,7 @@ async function main() {
204
204
 
205
205
  const proc = spawn(
206
206
  'npx',
207
- ['@react-native-community/cli', ...process.argv.slice(2)],
207
+ ['@react-native-community/cli@latest', ...process.argv.slice(2)],
208
208
  {
209
209
  stdio: 'inherit',
210
210
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native",
3
- "version": "0.76.1",
3
+ "version": "0.76.2",
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.1",
113
- "@react-native/codegen": "0.76.1",
114
- "@react-native/community-cli-plugin": "0.76.1",
115
- "@react-native/gradle-plugin": "0.76.1",
116
- "@react-native/js-polyfills": "0.76.1",
117
- "@react-native/normalize-colors": "0.76.1",
118
- "@react-native/virtualized-lists": "0.76.1",
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",
119
119
  "abort-controller": "^3.0.0",
120
120
  "anser": "^1.4.9",
121
121
  "ansi-regex": "^5.0.0",
@@ -492,7 +492,7 @@ function rootCodegenTargetNeedsThirdPartyComponentProvider(pkgJson, platform) {
492
492
  function dependencyNeedsThirdPartyComponentProvider(
493
493
  schemaInfo,
494
494
  platform,
495
- appCondegenConfigSpec,
495
+ appCodegenConfigSpec,
496
496
  ) {
497
497
  // Filter the react native core library out.
498
498
  // In the future, core library and third party library should
@@ -503,7 +503,7 @@ function dependencyNeedsThirdPartyComponentProvider(
503
503
  // the symbols defined in the app.
504
504
  return (
505
505
  !isReactNativeCoreLibrary(schemaInfo.library.config.name, platform) &&
506
- schemaInfo.library.config.name !== appCondegenConfigSpec
506
+ schemaInfo.library.config.name !== appCodegenConfigSpec
507
507
  );
508
508
  }
509
509
 
@@ -719,7 +719,7 @@ function execute(projectRoot, targetPlatform, baseOutputPath) {
719
719
  dependencyNeedsThirdPartyComponentProvider(
720
720
  schemaInfo,
721
721
  platform,
722
- pkgJson.codegenConfig?.appCondegenConfigSpec,
722
+ pkgJson.codegenConfig?.name,
723
723
  ),
724
724
  );
725
725
  const schemas = filteredSchemas.map(schemaInfo => schemaInfo.schema);
@@ -1 +1 @@
1
- hermes-2024-09-09-RNv0.76.0-db6d12e202e15f7a446d8848d6ca8f7abb3cfb32
1
+ hermes-2024-11-12-RNv0.76.2-5b4aa20c719830dcf5684832b89a6edb95ac3d64
Binary file
Binary file
Binary file
@@ -41,6 +41,7 @@ declare module 'react-native/Libraries/Utilities/codegenNativeComponent' {
41
41
 
42
42
  declare module 'react-native/Libraries/Types/CodegenTypes' {
43
43
  import type {NativeSyntheticEvent} from 'react-native';
44
+ import type {EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter';
44
45
 
45
46
  // Event types
46
47
  // We're not using the PaperName, it is only used to codegen view config settings
@@ -59,6 +60,7 @@ declare module 'react-native/Libraries/Types/CodegenTypes' {
59
60
  export type Float = number;
60
61
  export type Int32 = number;
61
62
  export type UnsafeObject = object;
63
+ export type UnsafeMixed = unknown;
62
64
 
63
65
  type DefaultTypes = number | boolean | string | ReadonlyArray<string>;
64
66
  // Default handling, ignore the unused value
@@ -71,4 +73,8 @@ declare module 'react-native/Libraries/Types/CodegenTypes' {
71
73
  Type extends DefaultTypes,
72
74
  Value extends Type | string | undefined | null,
73
75
  > = Type | undefined | null;
76
+
77
+ export type EventEmitter<T> = (
78
+ handler: (arg: T) => void | Promise<void>,
79
+ ) => EventSubscription;
74
80
  }