react-native 0.76.0 → 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.
- package/Libraries/AppDelegate/RCTAppDelegate.mm +1 -0
- package/Libraries/AppDelegate/React-RCTAppDelegate.podspec +1 -1
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/Core/setUpErrorHandling.js +1 -7
- package/Libraries/LogBox/Data/LogBoxData.js +2 -2
- package/Libraries/ReactNative/AppRegistry.js +3 -3
- package/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h +1 -0
- package/React/Base/RCTVersion.m +1 -1
- package/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +47 -3
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +2 -0
- package/ReactAndroid/api/ReactAndroid.api +0 -1
- package/ReactAndroid/cmake-utils/ReactNative-application.cmake +1 -1
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/HeadlessJsTaskService.java +4 -8
- package/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.kt +2 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/core/TimingModule.kt +0 -8
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt +8 -1
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputShadowNode.cpp +3 -2
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h +12 -1
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm +165 -2
- package/cli.js +1 -1
- package/package.json +8 -8
- package/scripts/cocoapods/utils.rb +4 -2
- package/scripts/codegen/generate-artifacts-executor.js +19 -4
- package/sdks/.hermesversion +1 -1
- package/sdks/hermesc/osx-bin/hermes +0 -0
- package/sdks/hermesc/osx-bin/hermesc +0 -0
- package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
- package/types/modules/Codegen.d.ts +6 -0
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
|
77
77
|
UIViewController *rootViewController = [self createRootViewController];
|
|
78
78
|
[self setRootView:rootView toRootViewController:rootViewController];
|
|
79
|
+
_window.windowScene.delegate = self;
|
|
79
80
|
_window.rootViewController = rootViewController;
|
|
80
81
|
[_window makeKeyAndVisible];
|
|
81
82
|
}
|
|
@@ -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
|
|
@@ -21,13 +21,7 @@ ExceptionsManager.installConsoleErrorReporter();
|
|
|
21
21
|
if (!global.__fbDisableExceptionsManager) {
|
|
22
22
|
const handleError = (e: mixed, isFatal: boolean) => {
|
|
23
23
|
try {
|
|
24
|
-
|
|
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:
|
|
85
|
+
suppressDialog_LEGACY: false,
|
|
86
86
|
suppressCompletely: false,
|
|
87
|
-
monitorEvent: '
|
|
87
|
+
monitorEvent: 'warning_unhandled',
|
|
88
88
|
monitorListVersion: 0,
|
|
89
89
|
monitorSampleRate: 1,
|
|
90
90
|
};
|
|
@@ -13,7 +13,7 @@ import type {RootTag} from '../Types/RootTagTypes';
|
|
|
13
13
|
import type {IPerformanceLogger} from '../Utilities/createPerformanceLogger';
|
|
14
14
|
import type {DisplayModeType} from './DisplayMode';
|
|
15
15
|
|
|
16
|
-
import
|
|
16
|
+
import registerCallableModule from '../Core/registerCallableModule';
|
|
17
17
|
import BugReporting from '../BugReporting/BugReporting';
|
|
18
18
|
import createPerformanceLogger from '../Utilities/createPerformanceLogger';
|
|
19
19
|
import infoLog from '../Utilities/infoLog';
|
|
@@ -363,8 +363,8 @@ global.RN$SurfaceRegistry = {
|
|
|
363
363
|
|
|
364
364
|
if (global.RN$Bridgeless === true) {
|
|
365
365
|
console.log('Bridgeless mode is enabled');
|
|
366
|
-
} else {
|
|
367
|
-
BatchedBridge.registerCallableModule('AppRegistry', AppRegistry);
|
|
368
366
|
}
|
|
369
367
|
|
|
368
|
+
registerCallableModule('AppRegistry', AppRegistry);
|
|
369
|
+
|
|
370
370
|
module.exports = AppRegistry;
|
|
@@ -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
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -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
|
-
|
|
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
|
|
778
|
+
return [newText.string isEqualToString:oldText.string];
|
|
736
779
|
} else {
|
|
737
|
-
return (
|
|
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
|
-
|
|
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})
|
|
@@ -124,15 +124,11 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
|
|
|
124
124
|
@Override
|
|
125
125
|
public void onDestroy() {
|
|
126
126
|
super.onDestroy();
|
|
127
|
+
ReactContext reactContext = getReactContext();
|
|
127
128
|
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (reactContext != null) {
|
|
132
|
-
HeadlessJsTaskContext headlessJsTaskContext =
|
|
133
|
-
HeadlessJsTaskContext.getInstance(reactContext);
|
|
134
|
-
headlessJsTaskContext.removeTaskEventListener(this);
|
|
135
|
-
}
|
|
129
|
+
if (reactContext != null) {
|
|
130
|
+
HeadlessJsTaskContext headlessJsTaskContext = HeadlessJsTaskContext.getInstance(reactContext);
|
|
131
|
+
headlessJsTaskContext.removeTaskEventListener(this);
|
|
136
132
|
}
|
|
137
133
|
if (sWakeLock != null) {
|
|
138
134
|
sWakeLock.release();
|
|
@@ -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
|
|
|
@@ -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() =
|
|
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
|
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native",
|
|
3
|
-
"version": "0.76.
|
|
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.
|
|
113
|
-
"@react-native/codegen": "0.76.
|
|
114
|
-
"@react-native/community-cli-plugin": "0.76.
|
|
115
|
-
"@react-native/gradle-plugin": "0.76.
|
|
116
|
-
"@react-native/js-polyfills": "0.76.
|
|
117
|
-
"@react-native/normalize-colors": "0.76.
|
|
118
|
-
"@react-native/virtualized-lists": "0.76.
|
|
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",
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
# This source code is licensed under the MIT license found in the
|
|
4
4
|
# LICENSE file in the root directory of this source tree.
|
|
5
5
|
|
|
6
|
+
require 'shellwords'
|
|
7
|
+
|
|
6
8
|
require_relative "./helpers.rb"
|
|
7
9
|
|
|
8
10
|
# Utilities class for React Native Cocoapods
|
|
@@ -237,8 +239,8 @@ class ReactNativePodsUtils
|
|
|
237
239
|
# When installing pods with a yarn alias, yarn creates a fake yarn and node executables
|
|
238
240
|
# in a temporary folder.
|
|
239
241
|
# Using `node --print "process.argv[0]";` we are able to retrieve the actual path from which node is running.
|
|
240
|
-
# see https://github.com/facebook/react-native/issues/43285 for more info
|
|
241
|
-
node_binary = `node --print "process.argv[0]"
|
|
242
|
+
# see https://github.com/facebook/react-native/issues/43285 for more info. We've tweaked this slightly.
|
|
243
|
+
node_binary = Shellwords.escape(`node --print "process.argv[0]"`.strip)
|
|
242
244
|
system("echo 'export NODE_BINARY=#{node_binary}' > #{file_path}.local")
|
|
243
245
|
end
|
|
244
246
|
end
|
|
@@ -489,11 +489,22 @@ function rootCodegenTargetNeedsThirdPartyComponentProvider(pkgJson, platform) {
|
|
|
489
489
|
return !pkgJsonIncludesGeneratedCode(pkgJson) && platform === 'ios';
|
|
490
490
|
}
|
|
491
491
|
|
|
492
|
-
function dependencyNeedsThirdPartyComponentProvider(
|
|
492
|
+
function dependencyNeedsThirdPartyComponentProvider(
|
|
493
|
+
schemaInfo,
|
|
494
|
+
platform,
|
|
495
|
+
appCodegenConfigSpec,
|
|
496
|
+
) {
|
|
493
497
|
// Filter the react native core library out.
|
|
494
498
|
// In the future, core library and third party library should
|
|
495
499
|
// use the same way to generate/register the fabric components.
|
|
496
|
-
|
|
500
|
+
// We also have to filter out the the components defined in the app
|
|
501
|
+
// because the RCTThirdPartyComponentProvider is generated inside Fabric,
|
|
502
|
+
// which lives in a different target from the app and it has no visibility over
|
|
503
|
+
// the symbols defined in the app.
|
|
504
|
+
return (
|
|
505
|
+
!isReactNativeCoreLibrary(schemaInfo.library.config.name, platform) &&
|
|
506
|
+
schemaInfo.library.config.name !== appCodegenConfigSpec
|
|
507
|
+
);
|
|
497
508
|
}
|
|
498
509
|
|
|
499
510
|
function mustGenerateNativeCode(includeLibraryPath, schemaInfo) {
|
|
@@ -704,8 +715,12 @@ function execute(projectRoot, targetPlatform, baseOutputPath) {
|
|
|
704
715
|
if (
|
|
705
716
|
rootCodegenTargetNeedsThirdPartyComponentProvider(pkgJson, platform)
|
|
706
717
|
) {
|
|
707
|
-
const filteredSchemas = schemaInfos.filter(
|
|
708
|
-
dependencyNeedsThirdPartyComponentProvider
|
|
718
|
+
const filteredSchemas = schemaInfos.filter(schemaInfo =>
|
|
719
|
+
dependencyNeedsThirdPartyComponentProvider(
|
|
720
|
+
schemaInfo,
|
|
721
|
+
platform,
|
|
722
|
+
pkgJson.codegenConfig?.name,
|
|
723
|
+
),
|
|
709
724
|
);
|
|
710
725
|
const schemas = filteredSchemas.map(schemaInfo => schemaInfo.schema);
|
|
711
726
|
const supportedApplePlatforms = filteredSchemas.map(
|
package/sdks/.hermesversion
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
hermes-2024-
|
|
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
|
}
|