mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-28 12:15:37 +08:00
NSNumber arguments must now be nonnull
Summary: The bridge implementation on React Android does not currently support boxed numeric/boolean types (the equivalent of NSNumber arguments on iOS), nor does Java support Objective-C's nil messaging system that transparently casts nil to zero, false, etc for primitive types. To avoid platform incompatibilities, we now treat all primitive arguments as non-nullable rather than silently converting NSNull -> nil -> 0/false. We also now enforce that NSNumber * objects must be explicitly marked as `nonnull` (this restriction may be lifted in future if/when Android supports boxed numbers). Other object types are still assumed to be nullable unless specifically annotated with `nonnull`.
This commit is contained in:
@@ -166,7 +166,7 @@ RCT_EXPORT_MODULE()
|
||||
* calculating the timer's target time. We calculate this by passing in
|
||||
* Date.now() from JS and then subtracting that from the current time here.
|
||||
*/
|
||||
RCT_EXPORT_METHOD(createTimer:(NSNumber *)callbackID
|
||||
RCT_EXPORT_METHOD(createTimer:(nonnull NSNumber *)callbackID
|
||||
duration:(NSTimeInterval)jsDuration
|
||||
jsSchedulingTime:(NSDate *)jsSchedulingTime
|
||||
repeats:(BOOL)repeats)
|
||||
@@ -200,15 +200,11 @@ RCT_EXPORT_METHOD(createTimer:(NSNumber *)callbackID
|
||||
[self startTimers];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(deleteTimer:(NSNumber *)timerID)
|
||||
RCT_EXPORT_METHOD(deleteTimer:(nonnull NSNumber *)timerID)
|
||||
{
|
||||
if (timerID) {
|
||||
_timers[timerID] = nil;
|
||||
if (_timers.count == 0) {
|
||||
[self stopTimers];
|
||||
}
|
||||
} else {
|
||||
RCTLogWarn(@"Called deleteTimer: with a nil timerID");
|
||||
_timers[timerID] = nil;
|
||||
if (_timers.count == 0) {
|
||||
[self stopTimers];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -597,7 +597,7 @@ static NSDictionary *RCTViewConfigForModule(Class managerClass)
|
||||
* A method to be called from JS, which takes a container ID and then releases
|
||||
* all subviews for that container upon receipt.
|
||||
*/
|
||||
RCT_EXPORT_METHOD(removeSubviewsFromContainerWithID:(NSNumber *)containerID)
|
||||
RCT_EXPORT_METHOD(removeSubviewsFromContainerWithID:(nonnull NSNumber *)containerID)
|
||||
{
|
||||
id<RCTViewNodeProtocol> container = _shadowViewRegistry[containerID];
|
||||
RCTAssert(container != nil, @"container view (for ID %@) not found", containerID);
|
||||
@@ -653,7 +653,7 @@ RCT_EXPORT_METHOD(removeSubviewsFromContainerWithID:(NSNumber *)containerID)
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(removeRootView:(NSNumber *)rootReactTag)
|
||||
RCT_EXPORT_METHOD(removeRootView:(nonnull NSNumber *)rootReactTag)
|
||||
{
|
||||
RCTShadowView *rootShadowView = _shadowViewRegistry[rootReactTag];
|
||||
RCTAssert(rootShadowView.superview == nil, @"root view cannot have superview (ID %@)", rootReactTag);
|
||||
@@ -669,7 +669,7 @@ RCT_EXPORT_METHOD(removeRootView:(NSNumber *)rootReactTag)
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(replaceExistingNonRootView:(NSNumber *)reactTag withView:(NSNumber *)newReactTag)
|
||||
RCT_EXPORT_METHOD(replaceExistingNonRootView:(nonnull NSNumber *)reactTag withView:(nonnull NSNumber *)newReactTag)
|
||||
{
|
||||
RCTShadowView *shadowView = _shadowViewRegistry[reactTag];
|
||||
RCTAssert(shadowView != nil, @"shadowView (for ID %@) not found", reactTag);
|
||||
@@ -689,7 +689,7 @@ RCT_EXPORT_METHOD(replaceExistingNonRootView:(NSNumber *)reactTag withView:(NSNu
|
||||
removeAtIndices:removeAtIndices];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(manageChildren:(NSNumber *)containerReactTag
|
||||
RCT_EXPORT_METHOD(manageChildren:(nonnull NSNumber *)containerReactTag
|
||||
moveFromIndices:(NSArray *)moveFromIndices
|
||||
moveToIndices:(NSArray *)moveToIndices
|
||||
addChildReactTags:(NSArray *)addChildReactTags
|
||||
@@ -809,7 +809,7 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
[shadowView updateLayout];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(createView:(NSNumber *)reactTag
|
||||
RCT_EXPORT_METHOD(createView:(nonnull NSNumber *)reactTag
|
||||
viewName:(NSString *)viewName
|
||||
rootTag:(__unused NSNumber *)rootTag
|
||||
props:(NSDictionary *)props)
|
||||
@@ -876,7 +876,7 @@ RCT_EXPORT_METHOD(createView:(NSNumber *)reactTag
|
||||
}
|
||||
|
||||
// TODO: remove viewName param as it isn't needed
|
||||
RCT_EXPORT_METHOD(updateView:(NSNumber *)reactTag
|
||||
RCT_EXPORT_METHOD(updateView:(nonnull NSNumber *)reactTag
|
||||
viewName:(__unused NSString *)_
|
||||
props:(NSDictionary *)props)
|
||||
{
|
||||
@@ -892,9 +892,8 @@ RCT_EXPORT_METHOD(updateView:(NSNumber *)reactTag
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(focus:(NSNumber *)reactTag)
|
||||
RCT_EXPORT_METHOD(focus:(nonnull NSNumber *)reactTag)
|
||||
{
|
||||
if (!reactTag) return;
|
||||
[self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
UIView *newResponder = viewRegistry[reactTag];
|
||||
[newResponder reactWillMakeFirstResponder];
|
||||
@@ -903,21 +902,16 @@ RCT_EXPORT_METHOD(focus:(NSNumber *)reactTag)
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(blur:(NSNumber *)reactTag)
|
||||
RCT_EXPORT_METHOD(blur:(nonnull NSNumber *)reactTag)
|
||||
{
|
||||
if (!reactTag) return;
|
||||
[self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry){
|
||||
UIView *currentResponder = viewRegistry[reactTag];
|
||||
[currentResponder resignFirstResponder];
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(findSubviewIn:(NSNumber *)reactTag atPoint:(CGPoint)point callback:(RCTResponseSenderBlock)callback) {
|
||||
if (!reactTag) {
|
||||
callback(@[(id)kCFNull]);
|
||||
return;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(findSubviewIn:(nonnull NSNumber *)reactTag atPoint:(CGPoint)point callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
[self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
UIView *view = viewRegistry[reactTag];
|
||||
UIView *target = [view hitTest:point withEvent:nil];
|
||||
@@ -1000,14 +994,9 @@ RCT_EXPORT_METHOD(findSubviewIn:(NSNumber *)reactTag atPoint:(CGPoint)point call
|
||||
});
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(measure:(NSNumber *)reactTag
|
||||
RCT_EXPORT_METHOD(measure:(nonnull NSNumber *)reactTag
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
if (!callback) {
|
||||
RCTLogError(@"Called measure with no callback");
|
||||
return;
|
||||
}
|
||||
|
||||
[self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
UIView *view = viewRegistry[reactTag];
|
||||
if (!view) {
|
||||
@@ -1075,8 +1064,8 @@ static void RCTMeasureLayout(RCTShadowView *view,
|
||||
* anything on the main UI thread. Invokes supplied callback with (x, y, width,
|
||||
* height).
|
||||
*/
|
||||
RCT_EXPORT_METHOD(measureLayout:(NSNumber *)reactTag
|
||||
relativeTo:(NSNumber *)ancestorReactTag
|
||||
RCT_EXPORT_METHOD(measureLayout:(nonnull NSNumber *)reactTag
|
||||
relativeTo:(nonnull NSNumber *)ancestorReactTag
|
||||
errorCallback:(__unused RCTResponseSenderBlock)errorCallback
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
@@ -1092,7 +1081,7 @@ RCT_EXPORT_METHOD(measureLayout:(NSNumber *)reactTag
|
||||
* anything on the main UI thread. Invokes supplied callback with (x, y, width,
|
||||
* height).
|
||||
*/
|
||||
RCT_EXPORT_METHOD(measureLayoutRelativeToParent:(NSNumber *)reactTag
|
||||
RCT_EXPORT_METHOD(measureLayoutRelativeToParent:(nonnull NSNumber *)reactTag
|
||||
errorCallback:(__unused RCTResponseSenderBlock)errorCallback
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
@@ -1108,7 +1097,7 @@ RCT_EXPORT_METHOD(measureLayoutRelativeToParent:(NSNumber *)reactTag
|
||||
* passed in parent view does not exist. Invokes the supplied callback with the array of computed layouts.
|
||||
*/
|
||||
RCT_EXPORT_METHOD(measureViewsInRect:(CGRect)rect
|
||||
parentView:(NSNumber *)reactTag
|
||||
parentView:(nonnull NSNumber *)reactTag
|
||||
errorCallback:(__unused RCTResponseSenderBlock)errorCallback
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
@@ -1120,7 +1109,6 @@ RCT_EXPORT_METHOD(measureViewsInRect:(CGRect)rect
|
||||
NSArray *childShadowViews = [shadowView reactSubviews];
|
||||
NSMutableArray *results = [[NSMutableArray alloc] initWithCapacity:[childShadowViews count]];
|
||||
|
||||
|
||||
[childShadowViews enumerateObjectsUsingBlock:
|
||||
^(RCTShadowView *childShadowView, NSUInteger idx, __unused BOOL *stop) {
|
||||
CGRect childLayout = [childShadowView measureLayoutRelativeToAncestor:shadowView];
|
||||
@@ -1153,9 +1141,9 @@ RCT_EXPORT_METHOD(measureViewsInRect:(CGRect)rect
|
||||
callback(@[results]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setMainScrollViewTag:(NSNumber *)reactTag)
|
||||
RCT_EXPORT_METHOD(setMainScrollViewTag:(nonnull NSNumber *)reactTag)
|
||||
{
|
||||
[self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){
|
||||
[self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
// - There should be at most one designated "main scroll view"
|
||||
// - There should be at most one designated "`nativeMainScrollDelegate`"
|
||||
// - The one designated main scroll view should have the one designated
|
||||
@@ -1163,8 +1151,8 @@ RCT_EXPORT_METHOD(setMainScrollViewTag:(NSNumber *)reactTag)
|
||||
if (uiManager.mainScrollView) {
|
||||
uiManager.mainScrollView.nativeMainScrollDelegate = nil;
|
||||
}
|
||||
if (reactTag) {
|
||||
id view = viewRegistry[reactTag];
|
||||
id view = viewRegistry[reactTag];
|
||||
if (view) {
|
||||
if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) {
|
||||
uiManager.mainScrollView = (id<RCTScrollableProtocol>)view;
|
||||
uiManager.mainScrollView.nativeMainScrollDelegate = uiManager.nativeMainScrollDelegate;
|
||||
@@ -1178,7 +1166,7 @@ RCT_EXPORT_METHOD(setMainScrollViewTag:(NSNumber *)reactTag)
|
||||
}
|
||||
|
||||
// TODO: we could just pass point property
|
||||
RCT_EXPORT_METHOD(scrollTo:(NSNumber *)reactTag
|
||||
RCT_EXPORT_METHOD(scrollTo:(nonnull NSNumber *)reactTag
|
||||
withOffsetX:(CGFloat)offsetX
|
||||
offsetY:(CGFloat)offsetY)
|
||||
{
|
||||
@@ -1193,7 +1181,7 @@ RCT_EXPORT_METHOD(scrollTo:(NSNumber *)reactTag
|
||||
}
|
||||
|
||||
// TODO: we could just pass point property
|
||||
RCT_EXPORT_METHOD(scrollWithoutAnimationTo:(NSNumber *)reactTag
|
||||
RCT_EXPORT_METHOD(scrollWithoutAnimationTo:(nonnull NSNumber *)reactTag
|
||||
offsetX:(CGFloat)offsetX
|
||||
offsetY:(CGFloat)offsetY)
|
||||
{
|
||||
@@ -1207,7 +1195,7 @@ RCT_EXPORT_METHOD(scrollWithoutAnimationTo:(NSNumber *)reactTag
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(zoomToRect:(NSNumber *)reactTag
|
||||
RCT_EXPORT_METHOD(zoomToRect:(nonnull NSNumber *)reactTag
|
||||
withRect:(CGRect)rect)
|
||||
{
|
||||
[self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry){
|
||||
@@ -1224,7 +1212,7 @@ RCT_EXPORT_METHOD(zoomToRect:(NSNumber *)reactTag
|
||||
* JS sets what *it* considers to be the responder. Later, scroll views can use
|
||||
* this in order to determine if scrolling is appropriate.
|
||||
*/
|
||||
RCT_EXPORT_METHOD(setJSResponder:(NSNumber *)reactTag
|
||||
RCT_EXPORT_METHOD(setJSResponder:(nonnull NSNumber *)reactTag
|
||||
blockNativeResponder:(__unused BOOL)blockNativeResponder)
|
||||
{
|
||||
[self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
|
||||
Reference in New Issue
Block a user