react-native 0.77.2 → 0.77.3
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/Core/ReactNativeVersion.js +1 -1
- package/Libraries/Network/RCTDataRequestHandler.mm +17 -3
- package/Libraries/Network/RCTFileRequestHandler.mm +17 -3
- package/React/Base/RCTVersion.m +1 -1
- package/React/DevSupport/RCTPausedInDebuggerOverlayController.mm +3 -5
- package/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm +18 -4
- package/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm +1 -4
- package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +22 -3
- package/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm +1 -1
- package/React/Fabric/Surface/RCTFabricSurface.mm +1 -0
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +13 -8
- package/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.kt +3 -16
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.kt +13 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java +0 -3
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BorderRadiusStyle.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt +39 -0
- package/ReactCommon/React-FabricComponents.podspec +1 -1
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/ReactCommon/react/renderer/components/modal/CMakeLists.txt +4 -1
- package/ReactCommon/react/renderer/components/modal/ModalHostViewComponentDescriptor.h +3 -2
- package/ReactCommon/react/renderer/components/modal/ModalHostViewState.h +4 -12
- package/ReactCommon/react/renderer/components/modal/ModalHostViewUtils.h +2 -2
- package/ReactCommon/react/renderer/components/modal/ModalHostViewUtils.mm +1 -1
- package/ReactCommon/react/renderer/components/modal/platform/android/JReactModalHostView.h +38 -0
- package/ReactCommon/react/renderer/components/modal/platform/android/ModalHostViewUtils.cpp +18 -0
- package/ReactCommon/react/renderer/components/modal/platform/cxx/ModalHostViewUtils.cpp +17 -0
- package/ReactCommon/react/renderer/components/scrollview/ScrollEvent.cpp +33 -0
- package/ReactCommon/react/renderer/components/scrollview/ScrollEvent.h +17 -0
- package/ReactCommon/react/renderer/components/scrollview/ScrollViewEventEmitter.cpp +3 -2
- package/ReactCommon/react/renderer/components/scrollview/ScrollViewEventEmitter.h +2 -1
- package/ReactCommon/react/runtime/TimerManager.cpp +6 -4
- package/ReactCommon/react/runtime/TimerManager.h +3 -1
- package/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp +9 -5
- package/package.json +10 -10
- 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/sdks/hermesc/win64-bin/msvcp140.dll +0 -0
- package/sdks/hermesc/win64-bin/vcruntime140.dll +0 -0
- package/sdks/hermesc/win64-bin/vcruntime140_1.dll +0 -0
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
#import <React/RCTDataRequestHandler.h>
|
|
9
9
|
#import <ReactCommon/RCTTurboModule.h>
|
|
10
10
|
|
|
11
|
+
#import <mutex>
|
|
12
|
+
|
|
11
13
|
#import "RCTNetworkPlugins.h"
|
|
12
14
|
|
|
13
15
|
@interface RCTDataRequestHandler () <RCTTurboModule>
|
|
@@ -15,14 +17,22 @@
|
|
|
15
17
|
|
|
16
18
|
@implementation RCTDataRequestHandler {
|
|
17
19
|
NSOperationQueue *_queue;
|
|
20
|
+
std::mutex _operationHandlerMutexLock;
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
RCT_EXPORT_MODULE()
|
|
21
24
|
|
|
22
25
|
- (void)invalidate
|
|
23
26
|
{
|
|
24
|
-
|
|
25
|
-
_queue
|
|
27
|
+
std::lock_guard<std::mutex> lock(_operationHandlerMutexLock);
|
|
28
|
+
if (_queue) {
|
|
29
|
+
for (NSOperation *operation in _queue.operations) {
|
|
30
|
+
if (!operation.isCancelled && !operation.isFinished) {
|
|
31
|
+
[operation cancel];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
_queue = nil;
|
|
35
|
+
}
|
|
26
36
|
}
|
|
27
37
|
|
|
28
38
|
- (BOOL)canHandleRequest:(NSURLRequest *)request
|
|
@@ -32,6 +42,7 @@ RCT_EXPORT_MODULE()
|
|
|
32
42
|
|
|
33
43
|
- (NSOperation *)sendRequest:(NSURLRequest *)request withDelegate:(id<RCTURLRequestDelegate>)delegate
|
|
34
44
|
{
|
|
45
|
+
std::lock_guard<std::mutex> lock(_operationHandlerMutexLock);
|
|
35
46
|
// Lazy setup
|
|
36
47
|
if (!_queue) {
|
|
37
48
|
_queue = [NSOperationQueue new];
|
|
@@ -69,7 +80,10 @@ RCT_EXPORT_MODULE()
|
|
|
69
80
|
|
|
70
81
|
- (void)cancelRequest:(NSOperation *)op
|
|
71
82
|
{
|
|
72
|
-
|
|
83
|
+
std::lock_guard<std::mutex> lock(_operationHandlerMutexLock);
|
|
84
|
+
if (!op.isCancelled && !op.isFinished) {
|
|
85
|
+
[op cancel];
|
|
86
|
+
}
|
|
73
87
|
}
|
|
74
88
|
|
|
75
89
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
#import <React/RCTFileRequestHandler.h>
|
|
9
9
|
|
|
10
|
+
#import <mutex>
|
|
11
|
+
|
|
10
12
|
#import <MobileCoreServices/MobileCoreServices.h>
|
|
11
13
|
|
|
12
14
|
#import <React/RCTUtils.h>
|
|
@@ -19,14 +21,22 @@
|
|
|
19
21
|
|
|
20
22
|
@implementation RCTFileRequestHandler {
|
|
21
23
|
NSOperationQueue *_fileQueue;
|
|
24
|
+
std::mutex _operationHandlerMutexLock;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
RCT_EXPORT_MODULE()
|
|
25
28
|
|
|
26
29
|
- (void)invalidate
|
|
27
30
|
{
|
|
28
|
-
|
|
29
|
-
_fileQueue
|
|
31
|
+
std::lock_guard<std::mutex> lock(_operationHandlerMutexLock);
|
|
32
|
+
if (_fileQueue) {
|
|
33
|
+
for (NSOperation *operation in _fileQueue.operations) {
|
|
34
|
+
if (!operation.isCancelled && !operation.isFinished) {
|
|
35
|
+
[operation cancel];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
_fileQueue = nil;
|
|
39
|
+
}
|
|
30
40
|
}
|
|
31
41
|
|
|
32
42
|
- (BOOL)canHandleRequest:(NSURLRequest *)request
|
|
@@ -36,6 +46,7 @@ RCT_EXPORT_MODULE()
|
|
|
36
46
|
|
|
37
47
|
- (NSOperation *)sendRequest:(NSURLRequest *)request withDelegate:(id<RCTURLRequestDelegate>)delegate
|
|
38
48
|
{
|
|
49
|
+
std::lock_guard<std::mutex> lock(_operationHandlerMutexLock);
|
|
39
50
|
// Lazy setup
|
|
40
51
|
if (!_fileQueue) {
|
|
41
52
|
_fileQueue = [NSOperationQueue new];
|
|
@@ -83,7 +94,10 @@ RCT_EXPORT_MODULE()
|
|
|
83
94
|
|
|
84
95
|
- (void)cancelRequest:(NSOperation *)op
|
|
85
96
|
{
|
|
86
|
-
|
|
97
|
+
std::lock_guard<std::mutex> lock(_operationHandlerMutexLock);
|
|
98
|
+
if (!op.isCancelled && !op.isFinished) {
|
|
99
|
+
[op cancel];
|
|
100
|
+
}
|
|
87
101
|
}
|
|
88
102
|
|
|
89
103
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -54,13 +54,11 @@
|
|
|
54
54
|
]];
|
|
55
55
|
|
|
56
56
|
UIButton *resumeButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
57
|
-
|
|
57
|
+
UIImage *image = [UIImage systemImageNamed:@"forward.frame.fill"];
|
|
58
|
+
[resumeButton setImage:image forState:UIControlStateNormal];
|
|
59
|
+
[resumeButton setImage:image forState:UIControlStateDisabled];
|
|
58
60
|
resumeButton.tintColor = [UIColor colorWithRed:0.37 green:0.37 blue:0.37 alpha:1];
|
|
59
61
|
|
|
60
|
-
resumeButton.configurationUpdateHandler = ^(UIButton *button) {
|
|
61
|
-
button.imageView.tintAdjustmentMode = UIViewTintAdjustmentModeNormal;
|
|
62
|
-
};
|
|
63
|
-
|
|
64
62
|
resumeButton.enabled = NO;
|
|
65
63
|
[NSLayoutConstraint activateConstraints:@[
|
|
66
64
|
[resumeButton.widthAnchor constraintEqualToConstant:48],
|
|
@@ -170,10 +170,24 @@ static NSString *const kRCTLegacyInteropChildIndexKey = @"index";
|
|
|
170
170
|
|
|
171
171
|
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
|
172
172
|
{
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
|
@@ -104,7 +104,6 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
|
|
104
104
|
BOOL _shouldAnimatePresentation;
|
|
105
105
|
BOOL _shouldPresent;
|
|
106
106
|
BOOL _isPresented;
|
|
107
|
-
UIView *_modalContentsSnapshot;
|
|
108
107
|
}
|
|
109
108
|
|
|
110
109
|
- (instancetype)initWithFrame:(CGRect)frame
|
|
@@ -141,7 +140,6 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
|
|
141
140
|
animated:(BOOL)animated
|
|
142
141
|
completion:(void (^)(void))completion
|
|
143
142
|
{
|
|
144
|
-
_modalContentsSnapshot = [self.viewController.view snapshotViewAfterScreenUpdates:NO];
|
|
145
143
|
[modalViewController dismissViewControllerAnimated:animated completion:completion];
|
|
146
144
|
}
|
|
147
145
|
|
|
@@ -167,8 +165,7 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
|
|
167
165
|
_isPresented = NO;
|
|
168
166
|
// To animate dismissal of view controller, snapshot of
|
|
169
167
|
// view hierarchy needs to be added to the UIViewController.
|
|
170
|
-
UIView *snapshot =
|
|
171
|
-
|
|
168
|
+
UIView *snapshot = [self.viewController.view snapshotViewAfterScreenUpdates:NO];
|
|
172
169
|
if (_shouldPresent) {
|
|
173
170
|
[self.viewController.view addSubview:snapshot];
|
|
174
171
|
}
|
|
@@ -547,6 +547,17 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
|
|
|
547
547
|
return metrics;
|
|
548
548
|
}
|
|
549
549
|
|
|
550
|
+
- (ScrollViewEventEmitter::EndDragMetrics)_scrollViewMetricsWithVelocity:(CGPoint)velocity
|
|
551
|
+
andTargetContentOffset:(CGPoint)targetContentOffset
|
|
552
|
+
{
|
|
553
|
+
ScrollViewEventEmitter::EndDragMetrics metrics = [self _scrollViewMetrics];
|
|
554
|
+
metrics.targetContentOffset.x = targetContentOffset.x;
|
|
555
|
+
metrics.targetContentOffset.y = targetContentOffset.y;
|
|
556
|
+
metrics.velocity.x = velocity.x;
|
|
557
|
+
metrics.velocity.y = velocity.y;
|
|
558
|
+
return metrics;
|
|
559
|
+
}
|
|
560
|
+
|
|
550
561
|
- (void)_updateStateWithContentOffset
|
|
551
562
|
{
|
|
552
563
|
if (!_state) {
|
|
@@ -602,6 +613,14 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
|
|
|
602
613
|
targetContentOffset->y = scrollView.contentOffset.y + travel * _endDraggingSensitivityMultiplier;
|
|
603
614
|
}
|
|
604
615
|
}
|
|
616
|
+
|
|
617
|
+
if (!_eventEmitter) {
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
auto metrics = [self _scrollViewMetricsWithVelocity:velocity andTargetContentOffset:*targetContentOffset];
|
|
622
|
+
|
|
623
|
+
static_cast<const ScrollViewEventEmitter &>(*_eventEmitter).onScrollEndDrag(metrics);
|
|
605
624
|
}
|
|
606
625
|
|
|
607
626
|
- (BOOL)touchesShouldCancelInContentView:(__unused UIView *)view
|
|
@@ -672,8 +691,6 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
|
|
|
672
691
|
return;
|
|
673
692
|
}
|
|
674
693
|
|
|
675
|
-
static_cast<const ScrollViewEventEmitter &>(*_eventEmitter).onScrollEndDrag([self _scrollViewMetrics]);
|
|
676
|
-
|
|
677
694
|
[self _updateStateWithContentOffset];
|
|
678
695
|
|
|
679
696
|
if (!decelerate) {
|
|
@@ -770,7 +787,9 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
|
|
|
770
787
|
return;
|
|
771
788
|
}
|
|
772
789
|
|
|
773
|
-
|
|
790
|
+
auto metrics = [self _scrollViewMetricsWithVelocity:{} andTargetContentOffset:{}];
|
|
791
|
+
static_cast<const ScrollViewEventEmitter &>(*_eventEmitter).onScrollEndDrag(metrics);
|
|
792
|
+
|
|
774
793
|
[self _updateStateWithContentOffset];
|
|
775
794
|
}
|
|
776
795
|
|
|
@@ -60,7 +60,7 @@ using namespace facebook::react;
|
|
|
60
60
|
const auto &newSwitchProps = static_cast<const SwitchProps &>(*props);
|
|
61
61
|
|
|
62
62
|
// `value`
|
|
63
|
-
if (oldSwitchProps.value != newSwitchProps.value) {
|
|
63
|
+
if (!_isInitialValueSet || oldSwitchProps.value != newSwitchProps.value) {
|
|
64
64
|
BOOL shouldAnimate = _isInitialValueSet == YES;
|
|
65
65
|
[_switchView setOn:newSwitchProps.value animated:shouldAnimate];
|
|
66
66
|
}
|
|
@@ -143,6 +143,7 @@ using namespace facebook::react;
|
|
|
143
143
|
|
|
144
144
|
if (!_view) {
|
|
145
145
|
_view = [[RCTSurfaceView alloc] initWithSurface:(RCTSurface *)self];
|
|
146
|
+
[self _updateLayoutContext];
|
|
146
147
|
_touchHandler = [RCTSurfaceTouchHandler new];
|
|
147
148
|
[_touchHandler attachToView:_view];
|
|
148
149
|
}
|
|
@@ -1409,14 +1409,14 @@ public class ReactInstanceManager {
|
|
|
1409
1409
|
new RuntimeException(
|
|
1410
1410
|
"detachRootViewFromInstance called with ReactRootView with invalid id"));
|
|
1411
1411
|
}
|
|
1412
|
-
|
|
1413
|
-
clearReactRoot(reactRoot);
|
|
1414
1412
|
} else {
|
|
1415
1413
|
reactContext
|
|
1416
1414
|
.getCatalystInstance()
|
|
1417
1415
|
.getJSModule(AppRegistry.class)
|
|
1418
1416
|
.unmountApplicationComponentAtRootTag(reactRoot.getRootViewTag());
|
|
1419
1417
|
}
|
|
1418
|
+
|
|
1419
|
+
clearReactRoot(reactRoot);
|
|
1420
1420
|
}
|
|
1421
1421
|
|
|
1422
1422
|
@ThreadConfined(UI)
|
|
@@ -171,7 +171,7 @@ public class FabricUIManager
|
|
|
171
171
|
private final CopyOnWriteArrayList<UIManagerListener> mListeners = new CopyOnWriteArrayList<>();
|
|
172
172
|
|
|
173
173
|
private boolean mMountNotificationScheduled = false;
|
|
174
|
-
private
|
|
174
|
+
private List<Integer> mSurfaceIdsWithPendingMountNotification = new ArrayList<>();
|
|
175
175
|
|
|
176
176
|
@ThreadConfined(UI)
|
|
177
177
|
@NonNull
|
|
@@ -1261,12 +1261,15 @@ public class FabricUIManager
|
|
|
1261
1261
|
|
|
1262
1262
|
// Collect surface IDs for all the mount items
|
|
1263
1263
|
for (MountItem mountItem : mountItems) {
|
|
1264
|
-
if (mountItem != null
|
|
1265
|
-
|
|
1264
|
+
if (mountItem != null
|
|
1265
|
+
&& !mSurfaceIdsWithPendingMountNotification.contains(mountItem.getSurfaceId())) {
|
|
1266
|
+
mSurfaceIdsWithPendingMountNotification.add(mountItem.getSurfaceId());
|
|
1266
1267
|
}
|
|
1267
1268
|
}
|
|
1268
1269
|
|
|
1269
|
-
if (!mMountNotificationScheduled && !
|
|
1270
|
+
if (!mMountNotificationScheduled && !mSurfaceIdsWithPendingMountNotification.isEmpty()) {
|
|
1271
|
+
mMountNotificationScheduled = true;
|
|
1272
|
+
|
|
1270
1273
|
// Notify mount when the effects are visible and prevent mount hooks to
|
|
1271
1274
|
// delay paint.
|
|
1272
1275
|
UiThreadUtil.getUiThreadHandler()
|
|
@@ -1276,17 +1279,19 @@ public class FabricUIManager
|
|
|
1276
1279
|
public void run() {
|
|
1277
1280
|
mMountNotificationScheduled = false;
|
|
1278
1281
|
|
|
1282
|
+
// Create a copy in case mount hooks trigger more mutations
|
|
1283
|
+
final List<Integer> surfaceIdsToReportMount =
|
|
1284
|
+
mSurfaceIdsWithPendingMountNotification;
|
|
1285
|
+
mSurfaceIdsWithPendingMountNotification = new ArrayList<>();
|
|
1286
|
+
|
|
1279
1287
|
final @Nullable FabricUIManagerBinding binding = mBinding;
|
|
1280
1288
|
if (binding == null || mDestroyed) {
|
|
1281
|
-
mMountedSurfaceIds.clear();
|
|
1282
1289
|
return;
|
|
1283
1290
|
}
|
|
1284
1291
|
|
|
1285
|
-
for (int surfaceId :
|
|
1292
|
+
for (int surfaceId : surfaceIdsToReportMount) {
|
|
1286
1293
|
binding.reportMount(surfaceId);
|
|
1287
1294
|
}
|
|
1288
|
-
|
|
1289
|
-
mMountedSurfaceIds.clear();
|
|
1290
1295
|
}
|
|
1291
1296
|
});
|
|
1292
1297
|
}
|
|
@@ -13,8 +13,6 @@ import android.os.Build
|
|
|
13
13
|
import android.view.View
|
|
14
14
|
import android.view.WindowInsetsController
|
|
15
15
|
import android.view.WindowManager
|
|
16
|
-
import androidx.core.view.ViewCompat
|
|
17
|
-
import androidx.core.view.WindowInsetsCompat
|
|
18
16
|
import com.facebook.common.logging.FLog
|
|
19
17
|
import com.facebook.fbreact.specs.NativeStatusBarManagerAndroidSpec
|
|
20
18
|
import com.facebook.react.bridge.GuardedRunnable
|
|
@@ -23,6 +21,7 @@ import com.facebook.react.bridge.ReactApplicationContext
|
|
|
23
21
|
import com.facebook.react.bridge.UiThreadUtil
|
|
24
22
|
import com.facebook.react.common.ReactConstants
|
|
25
23
|
import com.facebook.react.module.annotations.ReactModule
|
|
24
|
+
import com.facebook.react.uimanager.DisplayMetricsHolder.getStatusBarHeightPx
|
|
26
25
|
import com.facebook.react.uimanager.PixelUtil
|
|
27
26
|
import com.facebook.react.views.view.setStatusBarTranslucency
|
|
28
27
|
import com.facebook.react.views.view.setStatusBarVisibility
|
|
@@ -34,29 +33,17 @@ public class StatusBarModule(reactContext: ReactApplicationContext?) :
|
|
|
34
33
|
|
|
35
34
|
@Suppress("DEPRECATION")
|
|
36
35
|
override fun getTypedExportedConstants(): Map<String, Any> {
|
|
36
|
+
val currentActivity = reactApplicationContext.currentActivity
|
|
37
37
|
val statusBarColor =
|
|
38
38
|
currentActivity?.window?.statusBarColor?.let { color ->
|
|
39
39
|
String.format("#%06X", 0xFFFFFF and color)
|
|
40
40
|
} ?: "black"
|
|
41
41
|
return mapOf(
|
|
42
|
-
HEIGHT_KEY to PixelUtil.toDIPFromPixel(getStatusBarHeightPx()),
|
|
42
|
+
HEIGHT_KEY to PixelUtil.toDIPFromPixel(getStatusBarHeightPx(currentActivity).toFloat()),
|
|
43
43
|
DEFAULT_BACKGROUND_COLOR_KEY to statusBarColor,
|
|
44
44
|
)
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
@Suppress("DEPRECATION")
|
|
48
|
-
private fun getStatusBarHeightPx(): Float {
|
|
49
|
-
val windowInsets =
|
|
50
|
-
currentActivity?.window?.decorView?.let(ViewCompat::getRootWindowInsets) ?: return 0f
|
|
51
|
-
return windowInsets
|
|
52
|
-
.getInsets(
|
|
53
|
-
WindowInsetsCompat.Type.statusBars() or
|
|
54
|
-
WindowInsetsCompat.Type.navigationBars() or
|
|
55
|
-
WindowInsetsCompat.Type.displayCutout())
|
|
56
|
-
.top
|
|
57
|
-
.toFloat()
|
|
58
|
-
}
|
|
59
|
-
|
|
60
47
|
@Suppress("DEPRECATION")
|
|
61
48
|
override fun setColor(colorDouble: Double, animated: Boolean) {
|
|
62
49
|
val color = colorDouble.toInt()
|
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
package com.facebook.react.uimanager
|
|
9
9
|
|
|
10
|
+
import android.app.Activity
|
|
10
11
|
import android.content.Context
|
|
11
12
|
import android.util.DisplayMetrics
|
|
12
13
|
import android.view.WindowManager
|
|
14
|
+
import androidx.core.view.ViewCompat
|
|
15
|
+
import androidx.core.view.WindowInsetsCompat
|
|
13
16
|
import com.facebook.react.bridge.WritableMap
|
|
14
17
|
import com.facebook.react.bridge.WritableNativeMap
|
|
15
18
|
|
|
@@ -99,4 +102,14 @@ public object DisplayMetricsHolder {
|
|
|
99
102
|
putDouble("fontScale", fontScale)
|
|
100
103
|
putDouble("densityDpi", displayMetrics.densityDpi.toDouble())
|
|
101
104
|
}
|
|
105
|
+
|
|
106
|
+
internal fun getStatusBarHeightPx(activity: Activity?): Int {
|
|
107
|
+
val windowInsets = activity?.window?.decorView?.let(ViewCompat::getRootWindowInsets) ?: return 0
|
|
108
|
+
return windowInsets
|
|
109
|
+
.getInsets(
|
|
110
|
+
WindowInsetsCompat.Type.statusBars() or
|
|
111
|
+
WindowInsetsCompat.Type.navigationBars() or
|
|
112
|
+
WindowInsetsCompat.Type.displayCutout())
|
|
113
|
+
.top
|
|
114
|
+
}
|
|
102
115
|
}
|
|
@@ -136,10 +136,10 @@ public data class BorderRadiusStyle(
|
|
|
136
136
|
(startStart ?: topStart ?: topLeft ?: uniform)?.resolve(width, height)
|
|
137
137
|
?: zeroRadii,
|
|
138
138
|
bottomLeft =
|
|
139
|
-
(endEnd ?:
|
|
139
|
+
(endEnd ?: bottomEnd ?: bottomRight ?: uniform)?.resolve(width, height)
|
|
140
140
|
?: zeroRadii,
|
|
141
141
|
bottomRight =
|
|
142
|
-
(startEnd ?:
|
|
142
|
+
(startEnd ?: bottomStart ?: bottomLeft ?: uniform)?.resolve(width, height)
|
|
143
143
|
?: zeroRadii,
|
|
144
144
|
width = width,
|
|
145
145
|
height = height,
|
|
@@ -37,6 +37,8 @@ import com.facebook.react.bridge.WritableNativeMap
|
|
|
37
37
|
import com.facebook.react.common.ReactConstants
|
|
38
38
|
import com.facebook.react.common.annotations.VisibleForTesting
|
|
39
39
|
import com.facebook.react.config.ReactFeatureFlags
|
|
40
|
+
import com.facebook.react.uimanager.DisplayMetricsHolder
|
|
41
|
+
import com.facebook.react.uimanager.DisplayMetricsHolder.getStatusBarHeightPx
|
|
40
42
|
import com.facebook.react.uimanager.JSPointerDispatcher
|
|
41
43
|
import com.facebook.react.uimanager.JSTouchDispatcher
|
|
42
44
|
import com.facebook.react.uimanager.PixelUtil.pxToDp
|
|
@@ -49,6 +51,7 @@ import com.facebook.react.views.common.ContextUtils
|
|
|
49
51
|
import com.facebook.react.views.view.ReactViewGroup
|
|
50
52
|
import com.facebook.react.views.view.setStatusBarTranslucency
|
|
51
53
|
import com.facebook.react.views.view.setSystemBarsTranslucency
|
|
54
|
+
import com.facebook.yoga.annotations.DoNotStrip
|
|
52
55
|
import java.util.Objects
|
|
53
56
|
|
|
54
57
|
/**
|
|
@@ -119,6 +122,7 @@ public class ReactModalHostView(context: ThemedReactContext) :
|
|
|
119
122
|
private var createNewDialog = false
|
|
120
123
|
|
|
121
124
|
init {
|
|
125
|
+
initStatusBarHeight(context)
|
|
122
126
|
dialogRootViewGroup = DialogRootViewGroup(context)
|
|
123
127
|
}
|
|
124
128
|
|
|
@@ -220,6 +224,15 @@ public class ReactModalHostView(context: ThemedReactContext) :
|
|
|
220
224
|
|
|
221
225
|
private fun getCurrentActivity(): Activity? = (context as ThemedReactContext).currentActivity
|
|
222
226
|
|
|
227
|
+
private fun isFlagSecureSet(activity: Activity?): Boolean {
|
|
228
|
+
if (activity == null) {
|
|
229
|
+
return false
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
val flags = activity.window.attributes.flags
|
|
233
|
+
return (flags and WindowManager.LayoutParams.FLAG_SECURE) != 0
|
|
234
|
+
}
|
|
235
|
+
|
|
223
236
|
/**
|
|
224
237
|
* showOrUpdate will display the Dialog. It is called by the manager once all properties are set
|
|
225
238
|
* because we need to know all of them before creating the Dialog. It is also smart during updates
|
|
@@ -293,6 +306,11 @@ public class ReactModalHostView(context: ThemedReactContext) :
|
|
|
293
306
|
if (hardwareAccelerated) {
|
|
294
307
|
newDialog.window?.addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
|
|
295
308
|
}
|
|
309
|
+
val flagSecureSet = isFlagSecureSet(currentActivity)
|
|
310
|
+
if (flagSecureSet) {
|
|
311
|
+
newDialog.window?.setFlags(
|
|
312
|
+
WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
|
|
313
|
+
}
|
|
296
314
|
if (currentActivity?.isFinishing == false) {
|
|
297
315
|
newDialog.show()
|
|
298
316
|
updateSystemAppearance()
|
|
@@ -395,6 +413,26 @@ public class ReactModalHostView(context: ThemedReactContext) :
|
|
|
395
413
|
|
|
396
414
|
private companion object {
|
|
397
415
|
private const val TAG = "ReactModalHost"
|
|
416
|
+
|
|
417
|
+
// We store the status bar height to be able to properly position
|
|
418
|
+
// the modal on the first render.
|
|
419
|
+
private var statusBarHeight = 0
|
|
420
|
+
|
|
421
|
+
private fun initStatusBarHeight(reactContext: ReactContext) {
|
|
422
|
+
statusBarHeight = getStatusBarHeightPx(reactContext.currentActivity)
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
@JvmStatic
|
|
426
|
+
@DoNotStrip
|
|
427
|
+
private fun getScreenDisplayMetricsWithoutInsets(): Long {
|
|
428
|
+
val displayMetrics = DisplayMetricsHolder.getScreenDisplayMetrics()
|
|
429
|
+
return encodeFloatsToLong(
|
|
430
|
+
displayMetrics.widthPixels.toFloat().pxToDp(),
|
|
431
|
+
(displayMetrics.heightPixels - statusBarHeight).toFloat().pxToDp())
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
private fun encodeFloatsToLong(width: Float, height: Float): Long =
|
|
435
|
+
(width.toRawBits().toLong()) shl 32 or (height.toRawBits().toLong())
|
|
398
436
|
}
|
|
399
437
|
|
|
400
438
|
/**
|
|
@@ -410,6 +448,7 @@ public class ReactModalHostView(context: ThemedReactContext) :
|
|
|
410
448
|
*/
|
|
411
449
|
public class DialogRootViewGroup internal constructor(context: Context) :
|
|
412
450
|
ReactViewGroup(context), RootView {
|
|
451
|
+
|
|
413
452
|
internal var stateWrapper: StateWrapper? = null
|
|
414
453
|
internal var eventDispatcher: EventDispatcher? = null
|
|
415
454
|
|
|
@@ -112,7 +112,7 @@ Pod::Spec.new do |s|
|
|
|
112
112
|
ss.subspec "modal" do |sss|
|
|
113
113
|
sss.dependency folly_dep_name, folly_version
|
|
114
114
|
sss.compiler_flags = folly_compiler_flags
|
|
115
|
-
sss.source_files = "react/renderer/components/modal
|
|
115
|
+
sss.source_files = "react/renderer/components/modal/*.{m,mm,cpp,h}"
|
|
116
116
|
sss.exclude_files = "react/renderer/components/modal/tests"
|
|
117
117
|
sss.header_dir = "react/renderer/components/modal"
|
|
118
118
|
end
|
|
@@ -14,7 +14,10 @@ add_compile_options(
|
|
|
14
14
|
-Wpedantic
|
|
15
15
|
-DLOG_TAG=\"Fabric\")
|
|
16
16
|
|
|
17
|
-
file(GLOB rrc_modal_SRC CONFIGURE_DEPENDS
|
|
17
|
+
file(GLOB rrc_modal_SRC CONFIGURE_DEPENDS
|
|
18
|
+
*.cpp
|
|
19
|
+
platform/android/*.cpp)
|
|
20
|
+
|
|
18
21
|
add_library(rrc_modal STATIC ${rrc_modal_SRC})
|
|
19
22
|
|
|
20
23
|
target_include_directories(rrc_modal PUBLIC ${REACT_COMMON_DIR})
|
|
@@ -30,8 +30,9 @@ class ModalHostViewComponentDescriptor final
|
|
|
30
30
|
*shadowNode.getState())
|
|
31
31
|
.getData();
|
|
32
32
|
|
|
33
|
-
layoutableShadowNode.setSize(
|
|
34
|
-
|
|
33
|
+
layoutableShadowNode.setSize(Size{
|
|
34
|
+
.width = stateData.screenSize.width,
|
|
35
|
+
.height = stateData.screenSize.height});
|
|
35
36
|
layoutableShadowNode.setPositionType(YGPositionTypeAbsolute);
|
|
36
37
|
|
|
37
38
|
ConcreteComponentDescriptor::adopt(shadowNode);
|
|
@@ -9,15 +9,12 @@
|
|
|
9
9
|
|
|
10
10
|
#include <react/renderer/core/graphicsConversions.h>
|
|
11
11
|
#include <react/renderer/graphics/Float.h>
|
|
12
|
+
#include "ModalHostViewUtils.h"
|
|
12
13
|
|
|
13
14
|
#ifdef ANDROID
|
|
14
15
|
#include <folly/dynamic.h>
|
|
15
16
|
#endif
|
|
16
17
|
|
|
17
|
-
#if defined(__APPLE__) && TARGET_OS_IOS
|
|
18
|
-
#include "ModalHostViewUtils.h"
|
|
19
|
-
#endif
|
|
20
|
-
|
|
21
18
|
namespace facebook::react {
|
|
22
19
|
|
|
23
20
|
/*
|
|
@@ -27,12 +24,7 @@ class ModalHostViewState final {
|
|
|
27
24
|
public:
|
|
28
25
|
using Shared = std::shared_ptr<const ModalHostViewState>;
|
|
29
26
|
|
|
30
|
-
|
|
31
|
-
ModalHostViewState() : screenSize(RCTModalHostViewScreenSize()) {
|
|
32
|
-
#else
|
|
33
|
-
ModalHostViewState(){
|
|
34
|
-
#endif
|
|
35
|
-
};
|
|
27
|
+
ModalHostViewState() : screenSize(ModalHostViewScreenSize()) {}
|
|
36
28
|
ModalHostViewState(Size screenSize_) : screenSize(screenSize_){};
|
|
37
29
|
|
|
38
30
|
#ifdef ANDROID
|
|
@@ -40,8 +32,8 @@ class ModalHostViewState final {
|
|
|
40
32
|
const ModalHostViewState& previousState,
|
|
41
33
|
folly::dynamic data)
|
|
42
34
|
: screenSize(Size{
|
|
43
|
-
(Float)data["screenWidth"].getDouble(),
|
|
44
|
-
(Float)data["screenHeight"].getDouble()}){};
|
|
35
|
+
.width = (Float)data["screenWidth"].getDouble(),
|
|
36
|
+
.height = (Float)data["screenHeight"].getDouble()}){};
|
|
45
37
|
#endif
|
|
46
38
|
|
|
47
39
|
const Size screenSize{};
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
|
-
#include <react/renderer/
|
|
10
|
+
#include <react/renderer/graphics/Size.h>
|
|
11
11
|
|
|
12
12
|
namespace facebook::react {
|
|
13
13
|
|
|
14
|
-
Size
|
|
14
|
+
Size ModalHostViewScreenSize(void);
|
|
15
15
|
|
|
16
16
|
} // namespace facebook::react
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include <fbjni/fbjni.h>
|
|
11
|
+
#include <react/renderer/graphics/Size.h>
|
|
12
|
+
|
|
13
|
+
namespace facebook::react {
|
|
14
|
+
|
|
15
|
+
class JReactModalHostView
|
|
16
|
+
: public facebook::jni::JavaClass<JReactModalHostView> {
|
|
17
|
+
public:
|
|
18
|
+
static auto constexpr kJavaDescriptor =
|
|
19
|
+
"Lcom/facebook/react/views/modal/ReactModalHostView;";
|
|
20
|
+
|
|
21
|
+
static Size getDisplayMetrics() {
|
|
22
|
+
static auto method =
|
|
23
|
+
JReactModalHostView::javaClassStatic()->getStaticMethod<jlong()>(
|
|
24
|
+
"getScreenDisplayMetricsWithoutInsets");
|
|
25
|
+
auto result = method(javaClassStatic());
|
|
26
|
+
|
|
27
|
+
// Inspired from yogaMeassureToSize from conversions.h
|
|
28
|
+
int32_t wBits = 0xFFFFFFFF & (result >> 32);
|
|
29
|
+
int32_t hBits = 0xFFFFFFFF & result;
|
|
30
|
+
|
|
31
|
+
auto* measuredWidth = reinterpret_cast<float*>(&wBits);
|
|
32
|
+
auto* measuredHeight = reinterpret_cast<float*>(&hBits);
|
|
33
|
+
|
|
34
|
+
return Size{.width = *measuredWidth, .height = *measuredHeight};
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#include <react/renderer/components/modal/ModalHostViewUtils.h>
|
|
9
|
+
#include <react/renderer/graphics/Size.h>
|
|
10
|
+
#include "JReactModalHostView.h"
|
|
11
|
+
|
|
12
|
+
namespace facebook::react {
|
|
13
|
+
|
|
14
|
+
Size ModalHostViewScreenSize() {
|
|
15
|
+
return JReactModalHostView::getDisplayMetrics();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#include <react/renderer/components/modal/ModalHostViewUtils.h>
|
|
9
|
+
#include <react/renderer/graphics/Size.h>
|
|
10
|
+
|
|
11
|
+
namespace facebook::react {
|
|
12
|
+
|
|
13
|
+
Size ModalHostViewScreenSize() {
|
|
14
|
+
return Size{0, 0};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
} // namespace facebook::react
|
|
@@ -76,6 +76,39 @@ EventPayloadType ScrollEvent::getType() const {
|
|
|
76
76
|
return EventPayloadType::ScrollEvent;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
jsi::Value ScrollEndDragEvent::asJSIValue(jsi::Runtime& runtime) const {
|
|
80
|
+
auto payload = ScrollEvent::asJSIValue(runtime).asObject(runtime);
|
|
81
|
+
|
|
82
|
+
{
|
|
83
|
+
auto targetContentOffsetObj = jsi::Object(runtime);
|
|
84
|
+
targetContentOffsetObj.setProperty(runtime, "x", targetContentOffset.x);
|
|
85
|
+
targetContentOffsetObj.setProperty(runtime, "y", targetContentOffset.y);
|
|
86
|
+
payload.setProperty(runtime, "targetContentOffset", targetContentOffsetObj);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
{
|
|
90
|
+
auto velocityObj = jsi::Object(runtime);
|
|
91
|
+
velocityObj.setProperty(runtime, "x", velocity.x);
|
|
92
|
+
velocityObj.setProperty(runtime, "y", velocity.y);
|
|
93
|
+
payload.setProperty(runtime, "velocity", velocityObj);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return payload;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
folly::dynamic ScrollEndDragEvent::asDynamic() const {
|
|
100
|
+
auto metrics = ScrollEvent::asDynamic();
|
|
101
|
+
|
|
102
|
+
auto targetContentOffsetObj = folly::dynamic::object(
|
|
103
|
+
"x", targetContentOffset.x)("y", targetContentOffset.y);
|
|
104
|
+
metrics["targetContentOffset"] = std::move(targetContentOffsetObj);
|
|
105
|
+
|
|
106
|
+
auto velocityObj = folly::dynamic::object("x", velocity.x)("y", velocity.y);
|
|
107
|
+
metrics["velocity"] = std::move(velocityObj);
|
|
108
|
+
|
|
109
|
+
return metrics;
|
|
110
|
+
};
|
|
111
|
+
|
|
79
112
|
#if RN_DEBUG_STRING_CONVERTIBLE
|
|
80
113
|
|
|
81
114
|
std::string getDebugName(const ScrollEvent& /*scrollEvent*/) {
|
|
@@ -37,6 +37,23 @@ struct ScrollEvent : public EventPayload {
|
|
|
37
37
|
EventPayloadType getType() const override;
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
+
struct ScrollEndDragEvent : public ScrollEvent {
|
|
41
|
+
Point targetContentOffset;
|
|
42
|
+
Point velocity;
|
|
43
|
+
|
|
44
|
+
ScrollEndDragEvent() = default;
|
|
45
|
+
|
|
46
|
+
ScrollEndDragEvent(const ScrollEvent& scrollEvent)
|
|
47
|
+
: ScrollEvent(scrollEvent), targetContentOffset({}), velocity({}) {}
|
|
48
|
+
|
|
49
|
+
folly::dynamic asDynamic() const;
|
|
50
|
+
|
|
51
|
+
/*
|
|
52
|
+
* EventPayload implementations
|
|
53
|
+
*/
|
|
54
|
+
jsi::Value asJSIValue(jsi::Runtime& runtime) const override;
|
|
55
|
+
};
|
|
56
|
+
|
|
40
57
|
#if RN_DEBUG_STRING_CONVERTIBLE
|
|
41
58
|
|
|
42
59
|
std::string getDebugName(const ScrollEvent& scrollEvent);
|
|
@@ -25,8 +25,9 @@ void ScrollViewEventEmitter::onScrollBeginDrag(
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
void ScrollViewEventEmitter::onScrollEndDrag(
|
|
28
|
-
const
|
|
29
|
-
|
|
28
|
+
const ScrollEndDragEvent& scrollEvent) const {
|
|
29
|
+
dispatchEvent(
|
|
30
|
+
"scrollEndDrag", std::make_shared<ScrollEndDragEvent>(scrollEvent));
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
void ScrollViewEventEmitter::onMomentumScrollBegin(
|
|
@@ -21,10 +21,11 @@ class ScrollViewEventEmitter : public ViewEventEmitter {
|
|
|
21
21
|
using ViewEventEmitter::ViewEventEmitter;
|
|
22
22
|
|
|
23
23
|
using Metrics = ScrollEvent;
|
|
24
|
+
using EndDragMetrics = ScrollEndDragEvent;
|
|
24
25
|
|
|
25
26
|
void onScroll(const ScrollEvent& scrollEvent) const;
|
|
26
27
|
void onScrollBeginDrag(const ScrollEvent& scrollEvent) const;
|
|
27
|
-
void onScrollEndDrag(const
|
|
28
|
+
void onScrollEndDrag(const ScrollEndDragEvent& scrollEvent) const;
|
|
28
29
|
void onMomentumScrollBegin(const ScrollEvent& scrollEvent) const;
|
|
29
30
|
void onMomentumScrollEnd(const ScrollEvent& scrollEvent) const;
|
|
30
31
|
void onScrollToTop(const ScrollEvent& scrollEvent) const;
|
|
@@ -300,8 +300,9 @@ void TimerManager::attachGlobals(jsi::Runtime& runtime) {
|
|
|
300
300
|
}
|
|
301
301
|
|
|
302
302
|
if (!args[0].isObject() || !args[0].asObject(rt).isFunction(rt)) {
|
|
303
|
-
// Do not throw any error to match web spec
|
|
304
|
-
|
|
303
|
+
// Do not throw any error to match web spec; instead return 0, an
|
|
304
|
+
// invalid timer id
|
|
305
|
+
return 0;
|
|
305
306
|
}
|
|
306
307
|
|
|
307
308
|
auto callback = args[0].getObject(rt).getFunction(rt);
|
|
@@ -358,8 +359,9 @@ void TimerManager::attachGlobals(jsi::Runtime& runtime) {
|
|
|
358
359
|
}
|
|
359
360
|
|
|
360
361
|
if (!args[0].isObject() || !args[0].asObject(rt).isFunction(rt)) {
|
|
361
|
-
throw
|
|
362
|
-
|
|
362
|
+
// Do not throw any error to match web spec; instead return 0, an
|
|
363
|
+
// invalid timer id
|
|
364
|
+
return 0;
|
|
363
365
|
}
|
|
364
366
|
auto callback = args[0].getObject(rt).getFunction(rt);
|
|
365
367
|
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
|
-
|
|
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
|
|
@@ -266,7 +266,9 @@ TEST_F(ReactInstanceTest, testSetTimeoutWithoutDelay) {
|
|
|
266
266
|
EXPECT_CALL(
|
|
267
267
|
*mockRegistry_,
|
|
268
268
|
createTimer(_, 0)); // If delay is not provided, it should use 0
|
|
269
|
-
eval("setTimeout(() => {});");
|
|
269
|
+
auto val = eval("setTimeout(() => {});");
|
|
270
|
+
expectNoError();
|
|
271
|
+
EXPECT_EQ(val.asNumber(), 1); // First timer id should start at 1
|
|
270
272
|
}
|
|
271
273
|
|
|
272
274
|
TEST_F(ReactInstanceTest, testSetTimeoutWithPassThroughArgs) {
|
|
@@ -298,8 +300,9 @@ TEST_F(ReactInstanceTest, testSetTimeoutWithInvalidArgs) {
|
|
|
298
300
|
getErrorMessage("setTimeout();"),
|
|
299
301
|
"setTimeout must be called with at least one argument (the function to call).");
|
|
300
302
|
|
|
301
|
-
eval("setTimeout('invalid')
|
|
303
|
+
auto val = eval("setTimeout('invalid')");
|
|
302
304
|
expectNoError();
|
|
305
|
+
EXPECT_EQ(val.asNumber(), 0);
|
|
303
306
|
|
|
304
307
|
eval("setTimeout(() => {}, 'invalid');");
|
|
305
308
|
expectNoError();
|
|
@@ -416,9 +419,10 @@ TEST_F(ReactInstanceTest, testSetIntervalWithInvalidArgs) {
|
|
|
416
419
|
EXPECT_EQ(
|
|
417
420
|
getErrorMessage("setInterval();"),
|
|
418
421
|
"setInterval must be called with at least one argument (the function to call).");
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
+
|
|
423
|
+
auto val = eval("setInterval('invalid', 100)");
|
|
424
|
+
expectNoError();
|
|
425
|
+
EXPECT_EQ(val.asNumber(), 0);
|
|
422
426
|
}
|
|
423
427
|
|
|
424
428
|
TEST_F(ReactInstanceTest, testClearInterval) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native",
|
|
3
|
-
"version": "0.77.
|
|
3
|
+
"version": "0.77.3",
|
|
4
4
|
"description": "A framework for building native apps using React",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -108,13 +108,13 @@
|
|
|
108
108
|
},
|
|
109
109
|
"dependencies": {
|
|
110
110
|
"@jest/create-cache-key-function": "^29.6.3",
|
|
111
|
-
"@react-native/assets-registry": "0.77.
|
|
112
|
-
"@react-native/codegen": "0.77.
|
|
113
|
-
"@react-native/community-cli-plugin": "0.77.
|
|
114
|
-
"@react-native/gradle-plugin": "0.77.
|
|
115
|
-
"@react-native/js-polyfills": "0.77.
|
|
116
|
-
"@react-native/normalize-colors": "0.77.
|
|
117
|
-
"@react-native/virtualized-lists": "0.77.
|
|
111
|
+
"@react-native/assets-registry": "0.77.3",
|
|
112
|
+
"@react-native/codegen": "0.77.3",
|
|
113
|
+
"@react-native/community-cli-plugin": "0.77.3",
|
|
114
|
+
"@react-native/gradle-plugin": "0.77.3",
|
|
115
|
+
"@react-native/js-polyfills": "0.77.3",
|
|
116
|
+
"@react-native/normalize-colors": "0.77.3",
|
|
117
|
+
"@react-native/virtualized-lists": "0.77.3",
|
|
118
118
|
"abort-controller": "^3.0.0",
|
|
119
119
|
"anser": "^1.4.9",
|
|
120
120
|
"ansi-regex": "^5.0.0",
|
|
@@ -130,8 +130,8 @@
|
|
|
130
130
|
"jest-environment-node": "^29.6.3",
|
|
131
131
|
"jsc-android": "^250231.0.0",
|
|
132
132
|
"memoize-one": "^5.0.0",
|
|
133
|
-
"metro-runtime": "^0.81.
|
|
134
|
-
"metro-source-map": "^0.81.
|
|
133
|
+
"metro-runtime": "^0.81.5",
|
|
134
|
+
"metro-source-map": "^0.81.5",
|
|
135
135
|
"nullthrows": "^1.1.1",
|
|
136
136
|
"pretty-format": "^29.7.0",
|
|
137
137
|
"promise": "^8.3.0",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|