diff --git a/Examples/UIExplorer/AppStateExample.js b/Examples/UIExplorer/AppStateExample.js
index b409e8364..0f9c3c321 100644
--- a/Examples/UIExplorer/AppStateExample.js
+++ b/Examples/UIExplorer/AppStateExample.js
@@ -1,4 +1,11 @@
/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -16,9 +23,9 @@
*/
'use strict';
-var React = require('react');
-var ReactNative = require('react-native');
-var {
+const React = require('react');
+const ReactNative = require('react-native');
+const {
AppState,
Text,
View
@@ -29,13 +36,19 @@ var AppStateSubscription = React.createClass({
return {
appState: AppState.currentState,
previousAppStates: [],
+ memoryWarnings: 0,
};
},
componentDidMount: function() {
AppState.addEventListener('change', this._handleAppStateChange);
+ AppState.addEventListener('memoryWarning', this._handleMemoryWarning);
},
componentWillUnmount: function() {
AppState.removeEventListener('change', this._handleAppStateChange);
+ AppState.removeEventListener('memoryWarning', this._handleMemoryWarning);
+ },
+ _handleMemoryWarning: function() {
+ this.setState({memoryWarnings: this.state.memoryWarnings + 1});
},
_handleAppStateChange: function(appState) {
var previousAppStates = this.state.previousAppStates.slice();
@@ -46,6 +59,13 @@ var AppStateSubscription = React.createClass({
});
},
render() {
+ if (this.props.showMemoryWarnings) {
+ return (
+
+ {this.state.memoryWarnings}
+
+ );
+ }
if (this.props.showCurrentOnly) {
return (
@@ -78,4 +98,10 @@ exports.examples = [
title: 'Previous states:',
render(): ReactElement { return ; }
},
+ {
+ platform: 'ios',
+ title: 'Memory Warnings',
+ description: 'In the IOS simulator, hit Shift+Command+M to simulate a memory warning.',
+ render(): ReactElement { return ; }
+ },
];
diff --git a/Examples/UIExplorer/AppStateIOSExample.js b/Examples/UIExplorer/AppStateIOSExample.js
deleted file mode 100644
index 7598df7fb..000000000
--- a/Examples/UIExplorer/AppStateIOSExample.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * The examples provided by Facebook are for non-commercial testing and
- * evaluation purposes only.
- *
- * Facebook reserves all rights not expressly granted.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
- * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * @providesModule AppStateIOSExample
- * @flow
- */
-'use strict';
-
-var React = require('react');
-var ReactNative = require('react-native');
-var {
- AppStateIOS,
- Text,
- View
-} = ReactNative;
-
-var AppStateSubscription = React.createClass({
- getInitialState() {
- return {
- appState: AppStateIOS.currentState,
- previousAppStates: [],
- memoryWarnings: 0,
- };
- },
- componentDidMount: function() {
- AppStateIOS.addEventListener('change', this._handleAppStateChange);
- AppStateIOS.addEventListener('memoryWarning', this._handleMemoryWarning);
- },
- componentWillUnmount: function() {
- AppStateIOS.removeEventListener('change', this._handleAppStateChange);
- AppStateIOS.removeEventListener('memoryWarning', this._handleMemoryWarning);
- },
- _handleMemoryWarning: function() {
- this.setState({memoryWarnings: this.state.memoryWarnings + 1});
- },
- _handleAppStateChange: function(appState) {
- var previousAppStates = this.state.previousAppStates.slice();
- previousAppStates.push(this.state.appState);
- this.setState({
- appState,
- previousAppStates,
- });
- },
- render() {
- if (this.props.showMemoryWarnings) {
- return (
-
- {this.state.memoryWarnings}
-
- );
- }
- if (this.props.showCurrentOnly) {
- return (
-
- {this.state.appState}
-
- );
- }
- return (
-
- {JSON.stringify(this.state.previousAppStates)}
-
- );
- }
-});
-
-exports.title = 'AppStateIOS';
-exports.description = 'iOS app background status';
-exports.examples = [
- {
- title: 'AppStateIOS.currentState',
- description: 'Can be null on app initialization',
- render() { return {AppStateIOS.currentState}; }
- },
- {
- title: 'Subscribed AppStateIOS:',
- description: 'This changes according to the current state, so you can only ever see it rendered as "active"',
- render(): ReactElement { return ; }
- },
- {
- title: 'Previous states:',
- render(): ReactElement { return ; }
- },
- {
- title: 'Memory Warnings',
- description: 'In the simulator, hit Shift+Command+M to simulate a memory warning.',
- render(): ReactElement { return ; }
- },
-];
diff --git a/Examples/UIExplorer/UIExplorerList.ios.js b/Examples/UIExplorer/UIExplorerList.ios.js
index c63763e1e..e9ddd367b 100644
--- a/Examples/UIExplorer/UIExplorerList.ios.js
+++ b/Examples/UIExplorer/UIExplorerList.ios.js
@@ -171,10 +171,6 @@ const APIExamples: Array = [
key: 'AnExApp',
module: require('./AnimatedGratuitousApp/AnExApp'),
},
- {
- key: 'AppStateIOSExample',
- module: require('./AppStateIOSExample'),
- },
{
key: 'AppStateExample',
module: require('./AppStateExample'),
diff --git a/Examples/UIExplorer/UIExplorerUnitTests/RCTEventDispatcherTests.m b/Examples/UIExplorer/UIExplorerUnitTests/RCTEventDispatcherTests.m
index 4fe88ee93..e9559d558 100644
--- a/Examples/UIExplorer/UIExplorerUnitTests/RCTEventDispatcherTests.m
+++ b/Examples/UIExplorer/UIExplorerUnitTests/RCTEventDispatcherTests.m
@@ -105,9 +105,7 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-
[_eventDispatcher sendDeviceEventWithName:_eventName body:_body];
-
#pragma clang diagnostic pop
[_bridge verify];
diff --git a/Examples/UIExplorer/XHRExample.ios.js b/Examples/UIExplorer/XHRExample.ios.js
index b84c8b0a0..0deaa4eed 100644
--- a/Examples/UIExplorer/XHRExample.ios.js
+++ b/Examples/UIExplorer/XHRExample.ios.js
@@ -1,4 +1,11 @@
/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -21,7 +28,7 @@ var {
AlertIOS,
CameraRoll,
Image,
- LinkingIOS,
+ Linking,
ProgressViewIOS,
StyleSheet,
Text,
@@ -215,7 +222,7 @@ class FormUploader extends React.Component {
return;
}
var url = xhr.responseText.slice(index).split('\n')[0];
- LinkingIOS.openURL(url);
+ Linking.openURL(url);
};
var formdata = new FormData();
if (this.state.randomPhoto) {
diff --git a/Libraries/Geolocation/Geolocation.js b/Libraries/Geolocation/Geolocation.js
index f49a9ebf0..f2eed384b 100644
--- a/Libraries/Geolocation/Geolocation.js
+++ b/Libraries/Geolocation/Geolocation.js
@@ -11,15 +11,16 @@
*/
'use strict';
-var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
-var RCTLocationObserver = require('NativeModules').LocationObserver;
+const NativeEventEmitter = require('NativeEventEmitter');
+const RCTLocationObserver = require('NativeModules').LocationObserver;
-var invariant = require('fbjs/lib/invariant');
-var logError = require('logError');
-var warning = require('fbjs/lib/warning');
+const invariant = require('fbjs/lib/invariant');
+const logError = require('logError');
+const warning = require('fbjs/lib/warning');
+
+const LocationEventEmitter = new NativeEventEmitter(RCTLocationObserver);
var subscriptions = [];
-
var updatesEnabled = false;
type GeoOptions = {
@@ -80,11 +81,11 @@ var Geolocation = {
}
var watchID = subscriptions.length;
subscriptions.push([
- RCTDeviceEventEmitter.addListener(
+ LocationEventEmitter.addListener(
'geolocationDidChange',
success
),
- error ? RCTDeviceEventEmitter.addListener(
+ error ? LocationEventEmitter.addListener(
'geolocationError',
error
) : null,
diff --git a/Libraries/Geolocation/RCTLocationObserver.h b/Libraries/Geolocation/RCTLocationObserver.h
index 873eeff6a..a60715558 100644
--- a/Libraries/Geolocation/RCTLocationObserver.h
+++ b/Libraries/Geolocation/RCTLocationObserver.h
@@ -7,8 +7,8 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
-#import "RCTBridgeModule.h"
+#import "RCTEventEmitter.h"
-@interface RCTLocationObserver : NSObject
+@interface RCTLocationObserver : RCTEventEmitter
@end
diff --git a/Libraries/Geolocation/RCTLocationObserver.m b/Libraries/Geolocation/RCTLocationObserver.m
index 23179c5ca..319477c99 100644
--- a/Libraries/Geolocation/RCTLocationObserver.m
+++ b/Libraries/Geolocation/RCTLocationObserver.m
@@ -113,8 +113,6 @@ static NSDictionary *RCTPositionError(RCTPositionErrorCode code,
RCT_EXPORT_MODULE()
-@synthesize bridge = _bridge;
-
#pragma mark - Lifecycle
- (void)dealloc
@@ -128,8 +126,12 @@ RCT_EXPORT_MODULE()
return dispatch_get_main_queue();
}
-#pragma mark - Private API
+- (NSArray *)supportedEvents
+{
+ return @[@"geolocationDidChange", @"geolocationError"];
+}
+#pragma mark - Private API
- (void)beginLocationUpdatesWithDesiredAccuracy:(CLLocationAccuracy)desiredAccuracy distanceFilter:(CLLocationDistance)distanceFilter
{
@@ -279,11 +281,7 @@ RCT_EXPORT_METHOD(getCurrentPosition:(RCTLocationOptions)options
// Send event
if (_observingLocation) {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- [_bridge.eventDispatcher sendDeviceEventWithName:@"geolocationDidChange"
- body:_lastLocationEvent];
-#pragma clang diagnostic pop
+ [self sendEventWithName:@"geolocationDidChange" body:_lastLocationEvent];
}
// Fire all queued callbacks
@@ -324,11 +322,7 @@ RCT_EXPORT_METHOD(getCurrentPosition:(RCTLocationOptions)options
// Send event
if (_observingLocation) {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- [_bridge.eventDispatcher sendDeviceEventWithName:@"geolocationError"
- body:jsError];
-#pragma clang diagnostic pop
+ [self sendEventWithName:@"geolocationError" body:jsError];
}
// Fire all queued error callbacks
diff --git a/Libraries/LinkingIOS/RCTLinkingManager.m b/Libraries/LinkingIOS/RCTLinkingManager.m
index 96f9e75b4..ca4112fc7 100644
--- a/Libraries/LinkingIOS/RCTLinkingManager.m
+++ b/Libraries/LinkingIOS/RCTLinkingManager.m
@@ -88,8 +88,11 @@ continueUserActivity:(NSUserActivity *)userActivity
- (void)handleOpenURLNotification:(NSNotification *)notification
{
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"openURL"
body:notification.userInfo];
+#pragma clang diagnostic pop
}
RCT_EXPORT_METHOD(openURL:(NSURL *)URL
diff --git a/Libraries/Network/NetInfo.js b/Libraries/Network/NetInfo.js
index 7d4900f8e..0cbb88f48 100644
--- a/Libraries/Network/NetInfo.js
+++ b/Libraries/Network/NetInfo.js
@@ -12,12 +12,14 @@
'use strict';
const Map = require('Map');
+const NativeEventEmitter = require('NativeEventEmitter');
const NativeModules = require('NativeModules');
const Platform = require('Platform');
-const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
const RCTNetInfo = NativeModules.NetInfo;
const deprecatedCallback = require('deprecatedCallback');
+const NetInfoEventEmitter = new NativeEventEmitter(RCTNetInfo);
+
const DEVICE_CONNECTIVITY_EVENT = 'networkStatusDidChange';
type ChangeEventName = $Enum<{
@@ -176,7 +178,7 @@ const NetInfo = {
eventName: ChangeEventName,
handler: Function
): {remove: () => void} {
- const listener = RCTDeviceEventEmitter.addListener(
+ const listener = NetInfoEventEmitter.addListener(
DEVICE_CONNECTIVITY_EVENT,
(appStateData) => {
handler(appStateData.network_info);
diff --git a/Libraries/Network/RCTNetInfo.h b/Libraries/Network/RCTNetInfo.h
index 6c2556e0a..9c280b2cf 100644
--- a/Libraries/Network/RCTNetInfo.h
+++ b/Libraries/Network/RCTNetInfo.h
@@ -9,10 +9,10 @@
#import
-#import "RCTBridgeModule.h"
+#import "RCTEventEmitter.h"
-@interface RCTNetInfo : NSObject
+@interface RCTNetInfo : RCTEventEmitter
-- (instancetype)initWithHost:(NSString *)host NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithHost:(NSString *)host;
@end
diff --git a/Libraries/Network/RCTNetInfo.m b/Libraries/Network/RCTNetInfo.m
index 28d0fc073..5981e9f7f 100644
--- a/Libraries/Network/RCTNetInfo.m
+++ b/Libraries/Network/RCTNetInfo.m
@@ -22,10 +22,9 @@ static NSString *const RCTReachabilityStateCell = @"cell";
{
SCNetworkReachabilityRef _reachability;
NSString *_status;
+ NSString *_host;
}
-@synthesize bridge = _bridge;
-
RCT_EXPORT_MODULE()
static void RCTReachabilityCallback(__unused SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info)
@@ -51,11 +50,7 @@ static void RCTReachabilityCallback(__unused SCNetworkReachabilityRef target, SC
if (![status isEqualToString:self->_status]) {
self->_status = status;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- [self->_bridge.eventDispatcher sendDeviceEventWithName:@"networkStatusDidChange"
- body:@{@"network_info": status}];
-#pragma clang diagnostic pop
+ [self sendEventWithName:@"networkStatusDidChange" body:@{@"network_info": status}];
}
}
@@ -66,34 +61,40 @@ static void RCTReachabilityCallback(__unused SCNetworkReachabilityRef target, SC
RCTAssertParam(host);
RCTAssert(![host hasPrefix:@"http"], @"Host value should just contain the domain, not the URL scheme.");
- if ((self = [super init])) {
- _status = RCTReachabilityStateUnknown;
- _reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, host.UTF8String);
- SCNetworkReachabilityContext context = { 0, ( __bridge void *)self, NULL, NULL, NULL };
- SCNetworkReachabilitySetCallback(_reachability, RCTReachabilityCallback, &context);
- SCNetworkReachabilityScheduleWithRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
+ if ((self = [self init])) {
+ _host = [host copy];
}
return self;
}
-- (instancetype)init
+- (NSArray *)supportedEvents
{
- return [self initWithHost:@"apple.com"];
+ return @[@"networkStatusDidChange"];
}
-- (void)dealloc
+- (void)startObserving
{
- SCNetworkReachabilityUnscheduleFromRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
- CFRelease(_reachability);
+ _status = RCTReachabilityStateUnknown;
+ _reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, _host.UTF8String ?: "apple.com");
+ SCNetworkReachabilityContext context = { 0, ( __bridge void *)self, NULL, NULL, NULL };
+ SCNetworkReachabilitySetCallback(_reachability, RCTReachabilityCallback, &context);
+ SCNetworkReachabilityScheduleWithRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
+}
+
+- (void)stopObserving
+{
+ if (_reachability) {
+ SCNetworkReachabilityUnscheduleFromRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
+ CFRelease(_reachability);
+ }
}
#pragma mark - Public API
-// TODO: remove error callback - not needed except by Subscribable interface
RCT_EXPORT_METHOD(getCurrentConnectivity:(RCTPromiseResolveBlock)resolve
reject:(__unused RCTPromiseRejectBlock)reject)
{
- resolve(@{@"network_info": _status});
+ resolve(@{@"network_info": _status ?: RCTReachabilityStateUnknown});
}
@end
diff --git a/Libraries/Network/RCTNetworking.android.js b/Libraries/Network/RCTNetworking.android.js
index 38f694d54..23aa9e8bf 100644
--- a/Libraries/Network/RCTNetworking.android.js
+++ b/Libraries/Network/RCTNetworking.android.js
@@ -12,39 +12,66 @@
// Do not require the native RCTNetworking module directly! Use this wrapper module instead.
// It will add the necessary requestId, so that you don't have to generate it yourself.
-var RCTNetworkingNative = require('NativeModules').Networking;
+const FormData = require('FormData');
+const NativeEventEmitter = require('NativeEventEmitter');
+const RCTNetworkingNative = require('NativeModules').Networking;
-var _requestId = 1;
-var generateRequestId = function() {
+type Header = [string, string];
+
+function convertHeadersMapToArray(headers: Object): Array {
+ const headerArray = [];
+ for (const name in headers) {
+ headerArray.push([name, headers[name]]);
+ }
+ return headerArray;
+}
+
+let _requestId = 1;
+function generateRequestId() {
return _requestId++;
-};
+}
/**
* This class is a wrapper around the native RCTNetworking module. It adds a necessary unique
* requestId to each network request that can be used to abort that request later on.
*/
-class RCTNetworking {
+class RCTNetworking extends NativeEventEmitter {
- static sendRequest(method, url, headers, data, useIncrementalUpdates, timeout) {
- var requestId = generateRequestId();
+ constructor() {
+ super(RCTNetworkingNative);
+ }
+
+ sendRequest(method, url, headers, data, incrementalUpdates, timeout, callback) {
+ if (typeof data === 'string') {
+ data = {string: data};
+ } else if (data instanceof FormData) {
+ data = {
+ formData: data.getParts().map((part) => {
+ part.headers = convertHeadersMapToArray(part.headers);
+ return part;
+ }),
+ };
+ }
+ const requestId = generateRequestId();
RCTNetworkingNative.sendRequest(
method,
url,
requestId,
- headers,
+ convertHeadersMapToArray(headers),
data,
- useIncrementalUpdates,
- timeout);
- return requestId;
+ incrementalUpdates,
+ timeout
+ );
+ callback(requestId);
}
- static abortRequest(requestId) {
+ abortRequest(requestId) {
RCTNetworkingNative.abortRequest(requestId);
}
- static clearCookies(callback) {
+ clearCookies(callback) {
RCTNetworkingNative.clearCookies(callback);
}
}
-module.exports = RCTNetworking;
+module.exports = new RCTNetworking();
diff --git a/Libraries/Network/RCTNetworking.h b/Libraries/Network/RCTNetworking.h
index cd8b99dde..a06a1eeab 100644
--- a/Libraries/Network/RCTNetworking.h
+++ b/Libraries/Network/RCTNetworking.h
@@ -7,12 +7,10 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
-#import
-
-#import "RCTBridge.h"
+#import "RCTEventEmitter.h"
#import "RCTNetworkTask.h"
-@interface RCTNetworking : NSObject
+@interface RCTNetworking : RCTEventEmitter
/**
* Does a handler exist for the specified request?
diff --git a/Libraries/Network/RCTNetworking.ios.js b/Libraries/Network/RCTNetworking.ios.js
index 677f2c1c9..3e0e4c352 100644
--- a/Libraries/Network/RCTNetworking.ios.js
+++ b/Libraries/Network/RCTNetworking.ios.js
@@ -10,21 +10,39 @@
*/
'use strict';
-var RCTNetworkingNative = require('NativeModules').Networking;
+const FormData = require('FormData');
+const NativeEventEmitter = require('NativeEventEmitter');
+const RCTNetworkingNative = require('NativeModules').Networking;
-/**
- * This class is a wrapper around the native RCTNetworking module.
- */
-class RCTNetworking {
+class RCTNetworking extends NativeEventEmitter {
- static sendRequest(query, callback) {
- RCTNetworkingNative.sendRequest(query, callback);
+ constructor() {
+ super(RCTNetworkingNative);
}
- static abortRequest(requestId) {
- RCTNetworkingNative.cancelRequest(requestId);
+ sendRequest(method, url, headers, data, incrementalUpdates, timeout, callback) {
+ if (typeof data === 'string') {
+ data = {string: data};
+ } else if (data instanceof FormData) {
+ data = {formData: data.getParts()};
+ }
+ RCTNetworkingNative.sendRequest({
+ method,
+ url,
+ data,
+ headers,
+ incrementalUpdates,
+ timeout
+ }, callback);
}
+ abortRequest(requestId) {
+ RCTNetworkingNative.abortRequest(requestId);
+ }
+
+ clearCookies(callback) {
+ console.warn('RCTNetworking.clearCookies is not supported on iOS');
+ }
}
-module.exports = RCTNetworking;
+module.exports = new RCTNetworking();
diff --git a/Libraries/Network/RCTNetworking.m b/Libraries/Network/RCTNetworking.m
index 5c7e3b9ee..07c21f095 100644
--- a/Libraries/Network/RCTNetworking.m
+++ b/Libraries/Network/RCTNetworking.m
@@ -129,11 +129,18 @@ static NSString *RCTGenerateFormBoundary()
NSArray> *_handlers;
}
-@synthesize bridge = _bridge;
@synthesize methodQueue = _methodQueue;
RCT_EXPORT_MODULE()
+- (NSArray *)supportedEvents
+{
+ return @[@"didCompleteNetworkResponse",
+ @"didReceiveNetworkResponse",
+ @"didSendNetworkData",
+ @"didReceiveNetworkData"];
+}
+
- (id)handlerForRequest:(NSURLRequest *)request
{
if (!request.URL) {
@@ -142,7 +149,7 @@ RCT_EXPORT_MODULE()
if (!_handlers) {
// Get handlers, sorted in reverse priority order (highest priority first)
- _handlers = [[_bridge modulesConformingToProtocol:@protocol(RCTURLRequestHandler)] sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
+ _handlers = [[self.bridge modulesConformingToProtocol:@protocol(RCTURLRequestHandler)] sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
float priorityA = [a respondsToSelector:@selector(handlerPriority)] ? [a handlerPriority] : 0;
float priorityB = [b respondsToSelector:@selector(handlerPriority)] ? [b handlerPriority] : 0;
if (priorityA > priorityB) {
@@ -346,11 +353,7 @@ RCT_EXPORT_MODULE()
}
NSArray *responseJSON = @[task.requestID, responseText ?: @""];
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- [_bridge.eventDispatcher sendDeviceEventWithName:@"didReceiveNetworkData"
- body:responseJSON];
-#pragma clang diagnostic pop
+ [self sendEventWithName:@"didReceiveNetworkData" body:responseJSON];
}
- (void)sendRequest:(NSURLRequest *)request
@@ -364,10 +367,7 @@ RCT_EXPORT_MODULE()
RCTURLRequestProgressBlock uploadProgressBlock = ^(int64_t progress, int64_t total) {
dispatch_async(_methodQueue, ^{
NSArray *responseJSON = @[task.requestID, @((double)progress), @((double)total)];
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- [_bridge.eventDispatcher sendDeviceEventWithName:@"didSendNetworkData" body:responseJSON];
-#pragma clang diagnostic pop
+ [self sendEventWithName:@"didSendNetworkData" body:responseJSON];
});
};
@@ -385,11 +385,7 @@ RCT_EXPORT_MODULE()
}
id responseURL = response.URL ? response.URL.absoluteString : [NSNull null];
NSArray *responseJSON = @[task.requestID, @(status), headers, responseURL];
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- [_bridge.eventDispatcher sendDeviceEventWithName:@"didReceiveNetworkResponse"
- body:responseJSON];
-#pragma clang diagnostic pop
+ [self sendEventWithName:@"didReceiveNetworkResponse" body:responseJSON];
});
};
@@ -410,12 +406,7 @@ RCT_EXPORT_MODULE()
error.code == kCFURLErrorTimedOut ? @YES : @NO
];
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- [_bridge.eventDispatcher sendDeviceEventWithName:@"didCompleteNetworkResponse"
- body:responseJSON];
-#pragma clang diagnostic pop
-
+ [self sendEventWithName:@"didCompleteNetworkResponse" body:responseJSON];
[_tasksByRequestID removeObjectForKey:task.requestID];
});
};
@@ -469,7 +460,7 @@ RCT_EXPORT_METHOD(sendRequest:(NSDictionary *)query
}];
}
-RCT_EXPORT_METHOD(cancelRequest:(nonnull NSNumber *)requestID)
+RCT_EXPORT_METHOD(abortRequest:(nonnull NSNumber *)requestID)
{
[_tasksByRequestID[requestID] cancel];
[_tasksByRequestID removeObjectForKey:requestID];
diff --git a/Libraries/Network/XMLHttpRequest.android.js b/Libraries/Network/XMLHttpRequest.android.js
deleted file mode 100644
index 099df7526..000000000
--- a/Libraries/Network/XMLHttpRequest.android.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @providesModule XMLHttpRequest
- * @flow
- */
-'use strict';
-
-var FormData = require('FormData');
-var RCTNetworking = require('RCTNetworking');
-var XMLHttpRequestBase = require('XMLHttpRequestBase');
-
-type Header = [string, string];
-
-function convertHeadersMapToArray(headers: Object): Array {
- var headerArray = [];
- for (var name in headers) {
- headerArray.push([name, headers[name]]);
- }
- return headerArray;
-}
-
-class XMLHttpRequest extends XMLHttpRequestBase {
- sendImpl(
- method: ?string,
- url: ?string,
- headers: Object,
- data: any,
- useIncrementalUpdates: boolean,
- timeout: number,
- ): void {
- var body;
- if (typeof data === 'string') {
- body = {string: data};
- } else if (data instanceof FormData) {
- body = {
- formData: data.getParts().map((part) => {
- part.headers = convertHeadersMapToArray(part.headers);
- return part;
- }),
- };
- } else {
- body = data;
- }
- var requestId = RCTNetworking.sendRequest(
- method,
- url,
- convertHeadersMapToArray(headers),
- body,
- useIncrementalUpdates,
- timeout
- );
- this.didCreateRequest(requestId);
- }
-}
-
-module.exports = XMLHttpRequest;
diff --git a/Libraries/Network/XMLHttpRequest.ios.js b/Libraries/Network/XMLHttpRequest.ios.js
deleted file mode 100644
index dd4ee0dd6..000000000
--- a/Libraries/Network/XMLHttpRequest.ios.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @providesModule XMLHttpRequest
- * @flow
- */
-'use strict';
-
-var FormData = require('FormData');
-var RCTNetworking = require('RCTNetworking');
-
-var XMLHttpRequestBase = require('XMLHttpRequestBase');
-
-class XMLHttpRequest extends XMLHttpRequestBase {
- sendImpl(
- method: ?string,
- url: ?string,
- headers: Object,
- data: any,
- incrementalUpdates: boolean,
- timeout: number,
- ): void {
- if (typeof data === 'string') {
- data = {string: data};
- } else if (data instanceof FormData) {
- data = {formData: data.getParts()};
- }
- RCTNetworking.sendRequest(
- {
- method,
- url,
- data,
- headers,
- incrementalUpdates,
- timeout
- },
- this.didCreateRequest.bind(this)
- );
- }
-}
-
-module.exports = XMLHttpRequest;
diff --git a/Libraries/Network/XMLHttpRequestBase.js b/Libraries/Network/XMLHttpRequest.js
similarity index 94%
rename from Libraries/Network/XMLHttpRequestBase.js
rename to Libraries/Network/XMLHttpRequest.js
index d5d5da5c5..24c944512 100644
--- a/Libraries/Network/XMLHttpRequestBase.js
+++ b/Libraries/Network/XMLHttpRequest.js
@@ -6,13 +6,12 @@
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
- * @providesModule XMLHttpRequestBase
+ * @providesModule XMLHttpRequest
* @flow
*/
'use strict';
-var RCTNetworking = require('RCTNetworking');
-var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
+const RCTNetworking = require('RCTNetworking');
const EventTarget = require('event-target-shim');
const invariant = require('fbjs/lib/invariant');
@@ -61,7 +60,7 @@ class XMLHttpRequestEventTarget extends EventTarget(...REQUEST_EVENTS) {
/**
* Shared base for platform-specific XMLHttpRequest implementations.
*/
-class XMLHttpRequestBase extends EventTarget(...XHR_EVENTS) {
+class XMLHttpRequest extends EventTarget(...XHR_EVENTS) {
static UNSENT: number = UNSENT;
static OPENED: number = OPENED;
@@ -210,21 +209,22 @@ class XMLHttpRequestBase extends EventTarget(...XHR_EVENTS) {
return this._cachedResponse;
}
- didCreateRequest(requestId: number): void {
+ // exposed for testing
+ __didCreateRequest(requestId: number): void {
this._requestId = requestId;
- this._subscriptions.push(RCTDeviceEventEmitter.addListener(
+ this._subscriptions.push(RCTNetworking.addListener(
'didSendNetworkData',
(args) => this.__didUploadProgress(...args)
));
- this._subscriptions.push(RCTDeviceEventEmitter.addListener(
+ this._subscriptions.push(RCTNetworking.addListener(
'didReceiveNetworkResponse',
(args) => this._didReceiveResponse(...args)
));
- this._subscriptions.push(RCTDeviceEventEmitter.addListener(
+ this._subscriptions.push(RCTNetworking.addListener(
'didReceiveNetworkData',
(args) => this._didReceiveData(...args)
));
- this._subscriptions.push(RCTDeviceEventEmitter.addListener(
+ this._subscriptions.push(RCTNetworking.addListener(
'didCompleteNetworkResponse',
(args) => this.__didCompleteResponse(...args)
));
@@ -337,10 +337,18 @@ class XMLHttpRequestBase extends EventTarget(...XHR_EVENTS) {
url: ?string,
headers: Object,
data: any,
- incrementalEvents: boolean,
- timeout: number
+ useIncrementalUpdates: boolean,
+ timeout: number,
): void {
- throw new Error('Subclass must define sendImpl method');
+ RCTNetworking.sendRequest(
+ method,
+ url,
+ headers,
+ data,
+ useIncrementalUpdates,
+ timeout,
+ this.__didCreateRequest.bind(this),
+ );
}
send(data: any): void {
@@ -439,4 +447,4 @@ function toArrayBuffer(text: string, contentType: string): ArrayBuffer {
}
}
-module.exports = XMLHttpRequestBase;
+module.exports = XMLHttpRequest;
diff --git a/Libraries/Network/__tests__/XMLHttpRequestBase-test.js b/Libraries/Network/__tests__/XMLHttpRequest-test.js
similarity index 91%
rename from Libraries/Network/__tests__/XMLHttpRequestBase-test.js
rename to Libraries/Network/__tests__/XMLHttpRequest-test.js
index 9d967d4b3..a7c1a9956 100644
--- a/Libraries/Network/__tests__/XMLHttpRequestBase-test.js
+++ b/Libraries/Network/__tests__/XMLHttpRequest-test.js
@@ -12,13 +12,16 @@
jest
.disableAutomock()
.dontMock('event-target-shim')
- .dontMock('XMLHttpRequestBase');
+ .setMock('NativeModules', {
+ Networking: {
+ addListener: function(){},
+ removeListeners: function(){},
+ }
+ });
-const XMLHttpRequestBase = require('XMLHttpRequestBase');
+const XMLHttpRequest = require('XMLHttpRequest');
-class XMLHttpRequest extends XMLHttpRequestBase {}
-
-describe('XMLHttpRequestBase', function(){
+describe('XMLHttpRequest', function(){
var xhr;
var handleTimeout;
var handleError;
@@ -43,7 +46,7 @@ describe('XMLHttpRequestBase', function(){
xhr.addEventListener('load', handleLoad);
xhr.addEventListener('readystatechange', handleReadyStateChange);
- xhr.didCreateRequest(1);
+ xhr.__didCreateRequest(1);
});
afterEach(() => {
@@ -53,7 +56,7 @@ describe('XMLHttpRequestBase', function(){
handleLoad = null;
});
- it('should transition readyState correctly', function() {
+ it('should transition readyState correctly', function() {
expect(xhr.readyState).toBe(xhr.UNSENT);
xhr.open('GET', 'blabla');
diff --git a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m
index 0d6453a36..ac360e254 100644
--- a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m
+++ b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m
@@ -137,20 +137,29 @@ RCT_EXPORT_MODULE()
- (void)handleLocalNotificationReceived:(NSNotification *)notification
{
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"localNotificationReceived"
body:notification.userInfo];
+#pragma clang diagnostic pop
}
- (void)handleRemoteNotificationReceived:(NSNotification *)notification
{
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"remoteNotificationReceived"
body:notification.userInfo];
+#pragma clang diagnostic pop
}
- (void)handleRemoteNotificationsRegistered:(NSNotification *)notification
{
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"remoteNotificationsRegistered"
body:notification.userInfo];
+#pragma clang diagnostic pop
}
/**
diff --git a/Libraries/react-native/react-native.js b/Libraries/react-native/react-native.js
index d867bd595..6200bd42d 100644
--- a/Libraries/react-native/react-native.js
+++ b/Libraries/react-native/react-native.js
@@ -10,11 +10,11 @@
*/
'use strict';
-var warning = require('fbjs/lib/warning');
+const warning = require('fbjs/lib/warning');
if (__DEV__) {
- var warningDedupe = {};
- var addonWarn = function(prevName, newPackageName) {
+ const warningDedupe = {};
+ const addonWarn = function(prevName, newPackageName) {
warning(
warningDedupe[prevName],
'React.addons.' + prevName + ' is deprecated. Please import the "' +
@@ -25,7 +25,7 @@ if (__DEV__) {
}
// Export React, plus some native additions.
-var ReactNative = {
+const ReactNative = {
// Components
get ActivityIndicatorIOS() { return require('ActivityIndicatorIOS'); },
get ART() { return require('ReactNativeART'); },
@@ -87,9 +87,11 @@ var ReactNative = {
get ImagePickerIOS() { return require('ImagePickerIOS'); },
get IntentAndroid() { return require('IntentAndroid'); },
get InteractionManager() { return require('InteractionManager'); },
+ get Keyboard() { return require('Keyboard'); },
get LayoutAnimation() { return require('LayoutAnimation'); },
get Linking() { return require('Linking'); },
get LinkingIOS() { return require('LinkingIOS'); },
+ get NativeEventEmitter() { return require('NativeEventEmitter'); },
get NavigationExperimental() { return require('NavigationExperimental'); },
get NetInfo() { return require('NetInfo'); },
get PanResponder() { return require('PanResponder'); },
@@ -171,7 +173,7 @@ var ReactNative = {
// Preserve getters with warnings on the internal ReactNative copy without
// invoking them.
-var ReactNativeInternal = require('ReactNative');
+const ReactNativeInternal = require('ReactNative');
function applyForwarding(key) {
if (__DEV__) {
Object.defineProperty(
@@ -183,7 +185,7 @@ function applyForwarding(key) {
}
ReactNative[key] = ReactNativeInternal[key];
}
-for (var key in ReactNativeInternal) {
+for (const key in ReactNativeInternal) {
applyForwarding(key);
}
diff --git a/Libraries/react-native/react-native.js.flow b/Libraries/react-native/react-native.js.flow
index d300af0c4..066736dac 100644
--- a/Libraries/react-native/react-native.js.flow
+++ b/Libraries/react-native/react-native.js.flow
@@ -85,9 +85,11 @@ var ReactNative = Object.assign(Object.create(require('ReactNative')), {
ImagePickerIOS: require('ImagePickerIOS'),
IntentAndroid: require('IntentAndroid'),
InteractionManager: require('InteractionManager'),
+ Keyboard: require('Keyboard'),
LayoutAnimation: require('LayoutAnimation'),
Linking: require('Linking'),
LinkingIOS: require('LinkingIOS'),
+ NativeEventEmitter: require('NativeEventEmitter'),
NavigationExperimental: require('NavigationExperimental'),
NetInfo: require('NetInfo'),
PanResponder: require('PanResponder'),
diff --git a/React/Modules/RCTAccessibilityManager.m b/React/Modules/RCTAccessibilityManager.m
index fd629cae3..3fcef1e5d 100644
--- a/React/Modules/RCTAccessibilityManager.m
+++ b/React/Modules/RCTAccessibilityManager.m
@@ -92,8 +92,11 @@ RCT_EXPORT_MODULE()
BOOL newIsVoiceOverEnabled = UIAccessibilityIsVoiceOverRunning();
if (_isVoiceOverEnabled != newIsVoiceOverEnabled) {
_isVoiceOverEnabled = newIsVoiceOverEnabled;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"voiceOverDidChange"
body:@(_isVoiceOverEnabled)];
+#pragma clang diagnostic pop
}
}
diff --git a/React/Modules/RCTDevMenu.m b/React/Modules/RCTDevMenu.m
index e853659a5..f574f7b06 100644
--- a/React/Modules/RCTDevMenu.m
+++ b/React/Modules/RCTDevMenu.m
@@ -182,7 +182,10 @@ RCT_EXPORT_MODULE()
selectedTitle:@"Hide Inspector"
handler:^(__unused BOOL enabled)
{
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[weakSelf.bridge.eventDispatcher sendDeviceEventWithName:@"toggleElementInspector" body:nil];
+#pragma clang diagnostic pop
}]];
_webSocketExecutorName = [_defaults objectForKey:@"websocket-executor-name"] ?: @"JS Remotely";
@@ -214,8 +217,11 @@ RCT_EXPORT_MODULE()
modifierFlags:UIKeyModifierCommand
action:^(__unused UIKeyCommand *command) {
[weakSelf.bridge.eventDispatcher
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
sendDeviceEventWithName:@"toggleElementInspector"
body:nil];
+#pragma clang diagnostic pop
}];
// Reload in normal mode
@@ -388,7 +394,10 @@ RCT_EXPORT_MODULE()
// Inspector can only be shown after JS has loaded
if ([_settings[@"showInspector"] boolValue]) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[self.bridge.eventDispatcher sendDeviceEventWithName:@"toggleElementInspector" body:nil];
+#pragma clang diagnostic pop
}
});
}
diff --git a/React/Modules/RCTEventEmitter.m b/React/Modules/RCTEventEmitter.m
index 5f399e830..3d4f70a5f 100644
--- a/React/Modules/RCTEventEmitter.m
+++ b/React/Modules/RCTEventEmitter.m
@@ -37,7 +37,9 @@
- (void)sendEventWithName:(NSString *)eventName body:(id)body
{
- RCTAssert(_bridge != nil, @"bridge is not set.");
+ RCTAssert(_bridge != nil, @"bridge is not set. This is probably because you've "
+ "explicitly synthesized the bridge in %@, even though it's inherited "
+ "from RCTEventEmitter.", [self class]);
if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) {
RCTLogError(@"`%@` is not a supported event type for %@. Supported events are: `%@`",
diff --git a/React/Modules/RCTUIManager.m b/React/Modules/RCTUIManager.m
index a819847d0..11112f92a 100644
--- a/React/Modules/RCTUIManager.m
+++ b/React/Modules/RCTUIManager.m
@@ -253,8 +253,11 @@ RCT_EXPORT_MODULE()
!UIInterfaceOrientationIsPortrait(nextOrientation)) ||
(UIInterfaceOrientationIsLandscape(_currentInterfaceOrientation) &&
!UIInterfaceOrientationIsLandscape(nextOrientation))) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions"
body:RCTExportedDimensions(YES)];
+#pragma clang diagnostic pop
}
_currentInterfaceOrientation = nextOrientation;