[ReactNative] Use RCTNullIfNill and (id)kCFNull

Summary:
@public

Use consistent `null` handling:

`value || null`                ->  `RCTNullIfNil(value)`
`value == null ? nil : value`  ->  `RCTNilIfNull(value)`
`[NSNull null]`                ->  `(id)kCFNull`

Test Plan: The tests should be enough.
This commit is contained in:
Tadeu Zagallo 2015-06-12 11:05:01 -07:00 committed by Spencer Ahrens
parent 6e451e253f
commit 0c9c6e89e3
13 changed files with 41 additions and 37 deletions

View File

@ -57,7 +57,7 @@ static uint64_t _get_time_nanoseconds(void)
JSContextGroupRef group = JSContextGroupCreate(); JSContextGroupRef group = JSContextGroupCreate();
JSGlobalContextRef context = JSGlobalContextCreateInGroup(group, NULL); JSGlobalContextRef context = JSGlobalContextCreateInGroup(group, NULL);
id message = @[@[@1, @2, @3, @4], @[@{@"a": @1}, @{@"b": @2}], [NSNull null]]; id message = @[@[@1, @2, @3, @4], @[@{@"a": @1}, @{@"b": @2}], (id)kCFNull];
NSString *code = RCTJSONStringify(message, NULL); NSString *code = RCTJSONStringify(message, NULL);
JSStringRef script = JSStringCreateWithCFString((__bridge CFStringRef)code); JSStringRef script = JSStringCreateWithCFString((__bridge CFStringRef)code);
JSValueRef error = NULL; JSValueRef error = NULL;

View File

@ -28,7 +28,7 @@ TEST_PATH(name, _input, [[[NSBundle mainBundle] bundlePath] stringByAppendingPat
// Basic tests // Basic tests
TEST_URL(basic, @"http://example.com", @"http://example.com") TEST_URL(basic, @"http://example.com", @"http://example.com")
TEST_URL(null, [NSNull null], nil) TEST_URL(null, (id)kCFNull, nil)
// Local files // Local files
TEST_PATH(fileURL, @"file:///blah/hello.jsbundle", @"/blah/hello.jsbundle") TEST_PATH(fileURL, @"file:///blah/hello.jsbundle", @"/blah/hello.jsbundle")

View File

@ -10,6 +10,7 @@
#import "RCTActionSheetManager.h" #import "RCTActionSheetManager.h"
#import "RCTLog.h" #import "RCTLog.h"
#import "RCTUtils.h"
@interface RCTActionSheetManager () <UIActionSheetDelegate> @interface RCTActionSheetManager () <UIActionSheetDelegate>
@ -90,7 +91,7 @@ RCT_EXPORT_METHOD(showShareActionSheetWithOptions:(NSDictionary *)options
if (activityError) { if (activityError) {
failureCallback(@[[activityError localizedDescription]]); failureCallback(@[[activityError localizedDescription]]);
} else { } else {
successCallback(@[@(completed), (activityType ?: [NSNull null])]); successCallback(@[@(completed), RCTNullIfNil(activityType)]);
} }
}; };
} else { } else {
@ -100,7 +101,7 @@ RCT_EXPORT_METHOD(showShareActionSheetWithOptions:(NSDictionary *)options
if (![UIActivityViewController instancesRespondToSelector:@selector(completionWithItemsHandler)]) { if (![UIActivityViewController instancesRespondToSelector:@selector(completionWithItemsHandler)]) {
// Legacy iOS 7 implementation // Legacy iOS 7 implementation
share.completionHandler = ^(NSString *activityType, BOOL completed) { share.completionHandler = ^(NSString *activityType, BOOL completed) {
successCallback(@[@(completed), (activityType ?: [NSNull null])]); successCallback(@[@(completed), RCTNullIfNil(activityType)]);
}; };
} else } else
@ -109,7 +110,7 @@ RCT_EXPORT_METHOD(showShareActionSheetWithOptions:(NSDictionary *)options
{ {
// iOS 8 version // iOS 8 version
share.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) { share.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
successCallback(@[@(completed), (activityType ?: [NSNull null])]); successCallback(@[@(completed), RCTNullIfNil(activityType)]);
}; };
} }
} }

View File

@ -11,6 +11,7 @@
#import "RCTBridge.h" #import "RCTBridge.h"
#import "RCTEventDispatcher.h" #import "RCTEventDispatcher.h"
#import "RCTUtils.h"
NSString *const RCTOpenURLNotification = @"RCTOpenURLNotification"; NSString *const RCTOpenURLNotification = @"RCTOpenURLNotification";
@ -76,7 +77,7 @@ RCT_EXPORT_METHOD(canOpenURL:(NSURL *)URL
- (NSDictionary *)constantsToExport - (NSDictionary *)constantsToExport
{ {
NSURL *initialURL = _bridge.launchOptions[UIApplicationLaunchOptionsURLKey]; NSURL *initialURL = _bridge.launchOptions[UIApplicationLaunchOptionsURLKey];
return @{@"initialURL": [initialURL absoluteString] ?: [NSNull null]}; return @{@"initialURL": RCTNullIfNil([initialURL absoluteString])};
} }
@end @end

View File

@ -436,7 +436,7 @@ RCT_EXPORT_MODULE()
NSArray *responseJSON = @[ NSArray *responseJSON = @[
request.requestID, request.requestID,
error.localizedDescription ?: [NSNull null], RCTNullIfNil(error.localizedDescription),
]; ];
[_bridge.eventDispatcher sendDeviceEventWithName:@"didCompleteNetworkResponse" [_bridge.eventDispatcher sendDeviceEventWithName:@"didCompleteNetworkResponse"

View File

@ -11,6 +11,7 @@
#import "RCTBridge.h" #import "RCTBridge.h"
#import "RCTEventDispatcher.h" #import "RCTEventDispatcher.h"
#import "RCTUtils.h"
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0 #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
@ -172,7 +173,7 @@ RCT_EXPORT_METHOD(checkPermissions:(RCTResponseSenderBlock)callback)
- (NSDictionary *)constantsToExport - (NSDictionary *)constantsToExport
{ {
return @{ return @{
@"initialNotification": _initialNotification ?: [NSNull null] @"initialNotification": RCTNullIfNil(_initialNotification),
}; };
} }

View File

@ -13,6 +13,7 @@
#import "RCTEventDispatcher.h" #import "RCTEventDispatcher.h"
#import "RCTSRWebSocket.h" #import "RCTSRWebSocket.h"
#import "RCTSparseArray.h" #import "RCTSparseArray.h"
#import "RCTUtils.h"
@implementation RCTSRWebSocket (React) @implementation RCTSRWebSocket (React)
@ -107,7 +108,7 @@ RCT_EXPORT_METHOD(close:(NSNumber *)socketID)
{ {
[_bridge.eventDispatcher sendDeviceEventWithName:@"websocketClosed" body:@{ [_bridge.eventDispatcher sendDeviceEventWithName:@"websocketClosed" body:@{
@"code": @(code), @"code": @(code),
@"reason": reason ? reason : [NSNull null], @"reason": RCTNullIfNil(reason),
@"clean": @(wasClean), @"clean": @(wasClean),
@"id": webSocket.reactTag @"id": webSocket.reactTag
}]; }];

View File

@ -449,7 +449,7 @@ case _value: { \
// Set arguments // Set arguments
NSUInteger index = 0; NSUInteger index = 0;
for (id json in arguments) { for (id json in arguments) {
id arg = (json == [NSNull null]) ? nil : json; id arg = RCTNilIfNull(json);
void (^block)(RCTBridge *, NSNumber *, NSInvocation *, NSUInteger, id) = _argumentBlocks[index]; void (^block)(RCTBridge *, NSNumber *, NSInvocation *, NSUInteger, id) = _argumentBlocks[index];
block(bridge, context, invocation, index + 2, arg); block(bridge, context, invocation, index + 2, arg);
index++; index++;
@ -1012,7 +1012,7 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
if (queue) { if (queue) {
_queuesByID[moduleID] = queue; _queuesByID[moduleID] = queue;
} else { } else {
_queuesByID[moduleID] = [NSNull null]; _queuesByID[moduleID] = (id)kCFNull;
} }
} }
@ -1266,8 +1266,8 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
context:context context:context
callback:^(id json, NSError *error) { callback:^(id json, NSError *error) {
RCTProfileEndEvent(@"FetchApplicationScriptCallbacks", @"js_call,init", @{ RCTProfileEndEvent(@"FetchApplicationScriptCallbacks", @"js_call,init", @{
@"json": json ?: [NSNull null], @"json": RCTNullIfNil(json),
@"error": error ?: [NSNull null], @"error": RCTNullIfNil(error),
}); });
[self _handleBuffer:json context:context]; [self _handleBuffer:json context:context];
@ -1293,7 +1293,7 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
queue = _queuesByID[moduleID]; queue = _queuesByID[moduleID];
} }
if (queue == [NSNull null]) { if (queue == (id)kCFNull) {
[_javaScriptExecutor executeBlockOnJavaScriptQueue:block]; [_javaScriptExecutor executeBlockOnJavaScriptQueue:block];
} else { } else {
dispatch_async(queue ?: _methodQueue, block); dispatch_async(queue ?: _methodQueue, block);
@ -1509,7 +1509,7 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
@"module": method.moduleClassName, @"module": method.moduleClassName,
@"method": method.JSMethodName, @"method": method.JSMethodName,
@"selector": NSStringFromSelector(method.selector), @"selector": NSStringFromSelector(method.selector),
@"args": RCTJSONStringify(params ?: [NSNull null], NULL), @"args": RCTJSONStringify(RCTNullIfNil(params), NULL),
}); });
return YES; return YES;

View File

@ -54,7 +54,7 @@ RCT_CONVERTER(NSString *, NSString, description)
RCTLogConvertError(json, "a number"); RCTLogConvertError(json, "a number");
} }
return number; return number;
} else if (json && json != [NSNull null]) { } else if (json && json != (id)kCFNull) {
RCTLogConvertError(json, "a number"); RCTLogConvertError(json, "a number");
} }
return nil; return nil;
@ -141,7 +141,7 @@ RCT_CONVERTER(NSString *, NSString, description)
"Expected format: YYYY-MM-DD'T'HH:mm:ss.sssZ", json); "Expected format: YYYY-MM-DD'T'HH:mm:ss.sssZ", json);
} }
return date; return date;
} else if (json && json != [NSNull null]) { } else if (json && json != (id)kCFNull) {
RCTLogConvertError(json, "a date"); RCTLogConvertError(json, "a date");
} }
return nil; return nil;

View File

@ -107,8 +107,8 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) {
NSMutableDictionary *reactTouch = [[NSMutableDictionary alloc] initWithCapacity:9]; NSMutableDictionary *reactTouch = [[NSMutableDictionary alloc] initWithCapacity:9];
reactTouch[@"target"] = reactTag; reactTouch[@"target"] = reactTag;
reactTouch[@"identifier"] = @(touchID); reactTouch[@"identifier"] = @(touchID);
reactTouch[@"touches"] = [NSNull null]; // We hijack this touchObj to serve both as an event reactTouch[@"touches"] = (id)kCFNull; // We hijack this touchObj to serve both as an event
reactTouch[@"changedTouches"] = [NSNull null]; // and as a Touch object, so making this JIT friendly. reactTouch[@"changedTouches"] = (id)kCFNull; // and as a Touch object, so making this JIT friendly.
// Add to arrays // Add to arrays
[_touchViews addObject:targetView]; [_touchViews addObject:targetView];

View File

@ -137,7 +137,7 @@ static JSValueRef RCTConsoleProfile(JSContextRef context, JSObjectRef object, JS
profileName = [NSString stringWithFormat:@"Profile %d", profileCounter++]; profileName = [NSString stringWithFormat:@"Profile %d", profileCounter++];
} }
id profileInfo = [NSNull null]; id profileInfo = (id)kCFNull;
if (argumentCount > 1 && !JSValueIsUndefined(context, arguments[1])) { if (argumentCount > 1 && !JSValueIsUndefined(context, arguments[1])) {
profileInfo = @[RCTJSValueToNSString(context, arguments[1])]; profileInfo = @[RCTJSValueToNSString(context, arguments[1])];
} }

View File

@ -164,14 +164,14 @@ RCT_EXPORT_MODULE()
return errorOut; return errorOut;
} }
id value = [self _getValueForKey:key errorOut:&errorOut]; id value = [self _getValueForKey:key errorOut:&errorOut];
[result addObject:@[key, value ?: [NSNull null]]]; // Insert null if missing or failure. [result addObject:@[key, RCTNullIfNil(value)]]; // Insert null if missing or failure.
return errorOut; return errorOut;
} }
- (NSString *)_getValueForKey:(NSString *)key errorOut:(NSDictionary **)errorOut - (NSString *)_getValueForKey:(NSString *)key errorOut:(NSDictionary **)errorOut
{ {
id value = _manifest[key]; // nil means missing, null means there is a data file, anything else is an inline value. id value = _manifest[key]; // nil means missing, null means there is a data file, anything else is an inline value.
if (value == [NSNull null]) { if (value == (id)kCFNull) {
NSString *filePath = [self _filePathForKey:key]; NSString *filePath = [self _filePathForKey:key];
value = RCTReadFile(filePath, key, errorOut); value = RCTReadFile(filePath, key, errorOut);
} }
@ -195,7 +195,7 @@ RCT_EXPORT_MODULE()
NSString *filePath = [self _filePathForKey:key]; NSString *filePath = [self _filePathForKey:key];
NSError *error; NSError *error;
if (value.length <= kInlineValueThreshold) { if (value.length <= kInlineValueThreshold) {
if (_manifest[key] && _manifest[key] != [NSNull null]) { if (_manifest[key] && _manifest[key] != (id)kCFNull) {
// If the value already existed but wasn't inlined, remove the old file. // If the value already existed but wasn't inlined, remove the old file.
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil]; [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
} }
@ -206,7 +206,7 @@ RCT_EXPORT_MODULE()
if (error) { if (error) {
errorOut = RCTMakeError(@"Failed to write value.", error, @{@"key": key}); errorOut = RCTMakeError(@"Failed to write value.", error, @{@"key": key});
} else { } else {
_manifest[key] = [NSNull null]; // Mark existence of file with null, any other value is inline data. _manifest[key] = (id)kCFNull; // Mark existence of file with null, any other value is inline data.
} }
return errorOut; return errorOut;
} }
@ -223,7 +223,7 @@ RCT_EXPORT_METHOD(multiGet:(NSArray *)keys
id errorOut = [self _ensureSetup]; id errorOut = [self _ensureSetup];
if (errorOut) { if (errorOut) {
callback(@[@[errorOut], [NSNull null]]); callback(@[@[errorOut], (id)kCFNull]);
return; return;
} }
NSMutableArray *errors; NSMutableArray *errors;
@ -232,7 +232,7 @@ RCT_EXPORT_METHOD(multiGet:(NSArray *)keys
id keyError = [self _appendItemForKey:key toArray:result]; id keyError = [self _appendItemForKey:key toArray:result];
RCTAppendError(keyError, &errors); RCTAppendError(keyError, &errors);
} }
callback(@[errors ?: [NSNull null], result]); callback(@[RCTNullIfNil(errors), result]);
} }
RCT_EXPORT_METHOD(multiSet:(NSArray *)kvPairs RCT_EXPORT_METHOD(multiSet:(NSArray *)kvPairs
@ -250,7 +250,7 @@ RCT_EXPORT_METHOD(multiSet:(NSArray *)kvPairs
} }
[self _writeManifest:&errors]; [self _writeManifest:&errors];
if (callback) { if (callback) {
callback(@[errors ?: [NSNull null]]); callback(@[RCTNullIfNil(errors)]);
} }
} }
@ -282,7 +282,7 @@ RCT_EXPORT_METHOD(multiMerge:(NSArray *)kvPairs
} }
[self _writeManifest:&errors]; [self _writeManifest:&errors];
if (callback) { if (callback) {
callback(@[errors ?: [NSNull null]]); callback(@[RCTNullIfNil(errors)]);
} }
} }
@ -306,7 +306,7 @@ RCT_EXPORT_METHOD(multiRemove:(NSArray *)keys
} }
[self _writeManifest:&errors]; [self _writeManifest:&errors];
if (callback) { if (callback) {
callback(@[errors ?: [NSNull null]]); callback(@[RCTNullIfNil(errors)]);
} }
} }
@ -323,7 +323,7 @@ RCT_EXPORT_METHOD(clear:(RCTResponseSenderBlock)callback)
errorOut = [self _writeManifest:nil]; errorOut = [self _writeManifest:nil];
} }
if (callback) { if (callback) {
callback(@[errorOut ?: [NSNull null]]); callback(@[RCTNullIfNil(errorOut)]);
} }
} }
@ -331,9 +331,9 @@ RCT_EXPORT_METHOD(getAllKeys:(RCTResponseSenderBlock)callback)
{ {
id errorOut = [self _ensureSetup]; id errorOut = [self _ensureSetup];
if (errorOut) { if (errorOut) {
callback(@[errorOut, [NSNull null]]); callback(@[errorOut, (id)kCFNull]);
} else { } else {
callback(@[[NSNull null], [_manifest allKeys]]); callback(@[(id)kCFNull, [_manifest allKeys]]);
} }
} }

View File

@ -471,7 +471,7 @@ static NSDictionary *RCTViewConfigForModule(Class managerClass, NSString *viewNa
[frames addObject:[NSValue valueWithCGRect:shadowView.frame]]; [frames addObject:[NSValue valueWithCGRect:shadowView.frame]];
[areNew addObject:@(shadowView.isNewView)]; [areNew addObject:@(shadowView.isNewView)];
[parentsAreNew addObject:@(shadowView.superview.isNewView)]; [parentsAreNew addObject:@(shadowView.superview.isNewView)];
id event = [NSNull null]; id event = (id)kCFNull;
if (shadowView.hasOnLayout) { if (shadowView.hasOnLayout) {
event = @{ event = @{
@"target": shadowView.reactTag, @"target": shadowView.reactTag,
@ -519,7 +519,7 @@ static NSDictionary *RCTViewConfigForModule(Class managerClass, NSString *viewNa
void (^completion)(BOOL finished) = ^(BOOL finished) { void (^completion)(BOOL finished) = ^(BOOL finished) {
completionsCalled++; completionsCalled++;
if (event != [NSNull null]) { if (event != (id)kCFNull) {
[self.bridge.eventDispatcher sendInputEventWithName:@"topLayout" body:event]; [self.bridge.eventDispatcher sendInputEventWithName:@"topLayout" body:event];
} }
if (callback && completionsCalled == frames.count - 1) { if (callback && completionsCalled == frames.count - 1) {
@ -753,7 +753,7 @@ static BOOL RCTCallPropertySetter(NSString *key, SEL setter, id value, id view,
// TODO: cache respondsToSelector tests // TODO: cache respondsToSelector tests
if ([manager respondsToSelector:setter]) { if ([manager respondsToSelector:setter]) {
if (value == [NSNull null]) { if (value == (id)kCFNull) {
value = nil; value = nil;
} }
@ -906,7 +906,7 @@ RCT_EXPORT_METHOD(blur:(NSNumber *)reactTag)
RCT_EXPORT_METHOD(findSubviewIn:(NSNumber *)reactTag atPoint:(CGPoint)point callback:(RCTResponseSenderBlock)callback) { RCT_EXPORT_METHOD(findSubviewIn:(NSNumber *)reactTag atPoint:(CGPoint)point callback:(RCTResponseSenderBlock)callback) {
if (!reactTag) { if (!reactTag) {
callback(@[[NSNull null]]); callback(@[(id)kCFNull]);
return; return;
} }
@ -920,7 +920,7 @@ RCT_EXPORT_METHOD(findSubviewIn:(NSNumber *)reactTag atPoint:(CGPoint)point call
} }
callback(@[ callback(@[
target.reactTag ?: [NSNull null], RCTNullIfNil(target.reactTag),
@(frame.origin.x), @(frame.origin.x),
@(frame.origin.y), @(frame.origin.y),
@(frame.size.width), @(frame.size.width),