Updates from Tue 9 Jun
|
@ -45,7 +45,7 @@ var NavigatorIOSColors = React.createClass({
|
|||
|
||||
render: function() {
|
||||
// Set StatusBar with light contents to get better contrast
|
||||
StatusBarIOS.setStyle(StatusBarIOS.Style.lightContent);
|
||||
StatusBarIOS.setStyle('light-content');
|
||||
|
||||
return (
|
||||
<NavigatorIOS
|
||||
|
@ -55,7 +55,7 @@ var NavigatorIOSColors = React.createClass({
|
|||
title: '<NavigatorIOS>',
|
||||
rightButtonTitle: 'Done',
|
||||
onRightButtonPress: () => {
|
||||
StatusBarIOS.setStyle(StatusBarIOS.Style['default']);
|
||||
StatusBarIOS.setStyle('default');
|
||||
this.props.onExampleExit();
|
||||
},
|
||||
passProps: {
|
||||
|
|
|
@ -7,20 +7,42 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
004D28A31AAF61C70097A701 /* UIExplorerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 004D28A21AAF61C70097A701 /* UIExplorerTests.m */; };
|
||||
13417FE91AA91432003F314A /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FE81AA91428003F314A /* libRCTImage.a */; };
|
||||
134180011AA9153C003F314A /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FEF1AA914B8003F314A /* libRCTText.a */; };
|
||||
1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341802B1AA91779003F314A /* libRCTNetwork.a */; };
|
||||
134454601AAFCABD003F0779 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1344545A1AAFCAAE003F0779 /* libRCTAdSupport.a */; };
|
||||
134A8A2A1AACED7A00945AAE /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 134A8A251AACED6A00945AAE /* libRCTGeolocation.a */; };
|
||||
1353F5461B0E64F9009B4FAC /* ClippingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1353F5451B0E64F9009B4FAC /* ClippingTests.m */; };
|
||||
139FDEDB1B0651FB00C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDED91B0651EA00C62182 /* libRCTWebSocket.a */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
141FC1211B222EBB004D5FFB /* IntegrationTestsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 141FC1201B222EBB004D5FFB /* IntegrationTestsTests.m */; };
|
||||
143BC5A11B21E45C00462512 /* UIExplorerIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 143BC5A01B21E45C00462512 /* UIExplorerIntegrationTests.m */; };
|
||||
144D21241B2204C5006DB32B /* RCTClippingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 144D21231B2204C5006DB32B /* RCTClippingTests.m */; };
|
||||
147CED4C1AB3532B00DA3E4C /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 147CED4B1AB34F8C00DA3E4C /* libRCTActionSheet.a */; };
|
||||
1497CFAC1B21F5E400C1F8F2 /* RCTAllocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA41B21F5E400C1F8F2 /* RCTAllocationTests.m */; };
|
||||
1497CFAD1B21F5E400C1F8F2 /* RCTBridgeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA51B21F5E400C1F8F2 /* RCTBridgeTests.m */; };
|
||||
1497CFAE1B21F5E400C1F8F2 /* RCTContextExecutorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA61B21F5E400C1F8F2 /* RCTContextExecutorTests.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
1497CFAF1B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA71B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m */; };
|
||||
1497CFB01B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA81B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m */; };
|
||||
1497CFB11B21F5E400C1F8F2 /* RCTEventDispatcherTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA91B21F5E400C1F8F2 /* RCTEventDispatcherTests.m */; };
|
||||
1497CFB21B21F5E400C1F8F2 /* RCTSparseArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFAA1B21F5E400C1F8F2 /* RCTSparseArrayTests.m */; };
|
||||
1497CFB31B21F5E400C1F8F2 /* RCTUIManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFAB1B21F5E400C1F8F2 /* RCTUIManagerTests.m */; };
|
||||
14AADF051AC3DBB1002390C9 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14AADF041AC3DB95002390C9 /* libReact.a */; };
|
||||
14D6D7111B220EB3001FB087 /* libOCMock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14D6D7101B220EB3001FB087 /* libOCMock.a */; };
|
||||
14D6D71E1B2222EF001FB087 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 147CED4B1AB34F8C00DA3E4C /* libRCTActionSheet.a */; };
|
||||
14D6D71F1B2222EF001FB087 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1344545A1AAFCAAE003F0779 /* libRCTAdSupport.a */; };
|
||||
14D6D7201B2222EF001FB087 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 134A8A251AACED6A00945AAE /* libRCTGeolocation.a */; };
|
||||
14D6D7211B2222EF001FB087 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FE81AA91428003F314A /* libRCTImage.a */; };
|
||||
14D6D7221B2222EF001FB087 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341802B1AA91779003F314A /* libRCTNetwork.a */; };
|
||||
14D6D7231B2222EF001FB087 /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14DC67F11AB71876001358AB /* libRCTPushNotification.a */; };
|
||||
14D6D7241B2222EF001FB087 /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 834C36D21AF8DA610019C93C /* libRCTSettings.a */; };
|
||||
14D6D7251B2222EF001FB087 /* libRCTTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58005BEE1ABA80530062E044 /* libRCTTest.a */; };
|
||||
14D6D7261B2222EF001FB087 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FEF1AA914B8003F314A /* libRCTText.a */; };
|
||||
14D6D7271B2222EF001FB087 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */; };
|
||||
14D6D7281B2222EF001FB087 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDED91B0651EA00C62182 /* libRCTWebSocket.a */; };
|
||||
14D6D7291B2222EF001FB087 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14AADF041AC3DB95002390C9 /* libReact.a */; };
|
||||
14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14DC67F11AB71876001358AB /* libRCTPushNotification.a */; };
|
||||
58005BF21ABA80A60062E044 /* libRCTTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58005BEE1ABA80530062E044 /* libRCTTest.a */; };
|
||||
834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 834C36D21AF8DA610019C93C /* libRCTSettings.a */; };
|
||||
|
@ -28,13 +50,6 @@
|
|||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
004D28A41AAF61C70097A701 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
||||
remoteInfo = UIExplorer;
|
||||
};
|
||||
13417FE71AA91428003F314A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 13417FE31AA91428003F314A /* RCTImage.xcodeproj */;
|
||||
|
@ -77,6 +92,13 @@
|
|||
remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
|
||||
remoteInfo = RCTWebSocket;
|
||||
};
|
||||
143BC59B1B21E3E100462512 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
||||
remoteInfo = UIExplorer;
|
||||
};
|
||||
147CED4A1AB34F8C00DA3E4C /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 14E0EEC81AB118F7000DECC3 /* RCTActionSheet.xcodeproj */;
|
||||
|
@ -122,15 +144,12 @@
|
|||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
004D289E1AAF61C70097A701 /* UIExplorerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UIExplorerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
004D28A11AAF61C70097A701 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
004D28A21AAF61C70097A701 /* UIExplorerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UIExplorerTests.m; sourceTree = "<group>"; };
|
||||
004D289E1AAF61C70097A701 /* UIExplorerUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UIExplorerUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13417FE31AA91428003F314A /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = "<group>"; };
|
||||
13417FEA1AA914B8003F314A /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = "<group>"; };
|
||||
134180261AA91779003F314A /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = "<group>"; };
|
||||
134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = ../../Libraries/AdSupport/RCTAdSupport.xcodeproj; sourceTree = "<group>"; };
|
||||
134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../../Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = "<group>"; };
|
||||
1353F5451B0E64F9009B4FAC /* ClippingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ClippingTests.m; sourceTree = "<group>"; };
|
||||
139FDECA1B0651EA00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = ../../Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* UIExplorer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UIExplorer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = UIExplorer/AppDelegate.h; sourceTree = "<group>"; };
|
||||
|
@ -140,7 +159,37 @@
|
|||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = UIExplorer/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = UIExplorer/main.m; sourceTree = "<group>"; };
|
||||
13CC9D481AEED2B90020D1C2 /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = ../../Libraries/Settings/RCTSettings.xcodeproj; sourceTree = "<group>"; };
|
||||
141FC1201B222EBB004D5FFB /* IntegrationTestsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IntegrationTestsTests.m; sourceTree = "<group>"; };
|
||||
143BC57E1B21E18100462512 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
143BC5811B21E18100462512 /* testLayoutExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testLayoutExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
143BC5821B21E18100462512 /* testSliderExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testSliderExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
143BC5831B21E18100462512 /* testSwitchExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testSwitchExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
143BC5841B21E18100462512 /* testTabBarExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testTabBarExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
143BC5851B21E18100462512 /* testTextExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testTextExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
143BC5861B21E18100462512 /* testViewExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testViewExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
143BC5951B21E3E100462512 /* UIExplorerIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UIExplorerIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
143BC5981B21E3E100462512 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
143BC5A01B21E45C00462512 /* UIExplorerIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIExplorerIntegrationTests.m; sourceTree = "<group>"; };
|
||||
144D21231B2204C5006DB32B /* RCTClippingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTClippingTests.m; sourceTree = "<group>"; };
|
||||
1497CFA41B21F5E400C1F8F2 /* RCTAllocationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAllocationTests.m; sourceTree = "<group>"; };
|
||||
1497CFA51B21F5E400C1F8F2 /* RCTBridgeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTBridgeTests.m; sourceTree = "<group>"; };
|
||||
1497CFA61B21F5E400C1F8F2 /* RCTContextExecutorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTContextExecutorTests.m; sourceTree = "<group>"; };
|
||||
1497CFA71B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert_NSURLTests.m; sourceTree = "<group>"; };
|
||||
1497CFA81B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert_UIFontTests.m; sourceTree = "<group>"; };
|
||||
1497CFA91B21F5E400C1F8F2 /* RCTEventDispatcherTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTEventDispatcherTests.m; sourceTree = "<group>"; };
|
||||
1497CFAA1B21F5E400C1F8F2 /* RCTSparseArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSparseArrayTests.m; sourceTree = "<group>"; };
|
||||
1497CFAB1B21F5E400C1F8F2 /* RCTUIManagerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIManagerTests.m; sourceTree = "<group>"; };
|
||||
14AADEFF1AC3DB95002390C9 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = ../../React/React.xcodeproj; sourceTree = "<group>"; };
|
||||
14D6D7021B220AE3001FB087 /* NSNotificationCenter+OCMAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+OCMAdditions.h"; sourceTree = "<group>"; };
|
||||
14D6D7031B220AE3001FB087 /* OCMArg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMArg.h; sourceTree = "<group>"; };
|
||||
14D6D7041B220AE3001FB087 /* OCMConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMConstraint.h; sourceTree = "<group>"; };
|
||||
14D6D7051B220AE3001FB087 /* OCMLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMLocation.h; sourceTree = "<group>"; };
|
||||
14D6D7061B220AE3001FB087 /* OCMMacroState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMMacroState.h; sourceTree = "<group>"; };
|
||||
14D6D7071B220AE3001FB087 /* OCMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMock.h; sourceTree = "<group>"; };
|
||||
14D6D7081B220AE3001FB087 /* OCMockObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMockObject.h; sourceTree = "<group>"; };
|
||||
14D6D7091B220AE3001FB087 /* OCMRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMRecorder.h; sourceTree = "<group>"; };
|
||||
14D6D70A1B220AE3001FB087 /* OCMStubRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMStubRecorder.h; sourceTree = "<group>"; };
|
||||
14D6D7101B220EB3001FB087 /* libOCMock.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libOCMock.a; sourceTree = "<group>"; };
|
||||
14DC67E71AB71876001358AB /* RCTPushNotification.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTPushNotification.xcodeproj; path = ../../Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj; sourceTree = "<group>"; };
|
||||
14E0EEC81AB118F7000DECC3 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../../Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = "<group>"; };
|
||||
58005BE41ABA80530062E044 /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = ../../Libraries/RCTTest/RCTTest.xcodeproj; sourceTree = "<group>"; };
|
||||
|
@ -152,6 +201,19 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
14D6D71E1B2222EF001FB087 /* libRCTActionSheet.a in Frameworks */,
|
||||
14D6D71F1B2222EF001FB087 /* libRCTAdSupport.a in Frameworks */,
|
||||
14D6D7201B2222EF001FB087 /* libRCTGeolocation.a in Frameworks */,
|
||||
14D6D7211B2222EF001FB087 /* libRCTImage.a in Frameworks */,
|
||||
14D6D7221B2222EF001FB087 /* libRCTNetwork.a in Frameworks */,
|
||||
14D6D7231B2222EF001FB087 /* libRCTPushNotification.a in Frameworks */,
|
||||
14D6D7241B2222EF001FB087 /* libRCTSettings.a in Frameworks */,
|
||||
14D6D7251B2222EF001FB087 /* libRCTTest.a in Frameworks */,
|
||||
14D6D7261B2222EF001FB087 /* libRCTText.a in Frameworks */,
|
||||
14D6D7271B2222EF001FB087 /* libRCTVibration.a in Frameworks */,
|
||||
14D6D7281B2222EF001FB087 /* libRCTWebSocket.a in Frameworks */,
|
||||
14D6D7291B2222EF001FB087 /* libReact.a in Frameworks */,
|
||||
14D6D7111B220EB3001FB087 /* libOCMock.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -174,27 +236,16 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
143BC5921B21E3E100462512 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
004D289F1AAF61C70097A701 /* UIExplorerTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
004D28A21AAF61C70097A701 /* UIExplorerTests.m */,
|
||||
1353F5451B0E64F9009B4FAC /* ClippingTests.m */,
|
||||
004D28A01AAF61C70097A701 /* Supporting Files */,
|
||||
);
|
||||
path = UIExplorerTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
004D28A01AAF61C70097A701 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
004D28A11AAF61C70097A701 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1316A21D1AA397F400C0188E /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -275,6 +326,65 @@
|
|||
name = UIExplorer;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
143BC57C1B21E18100462512 /* UIExplorerUnitTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1497CFA41B21F5E400C1F8F2 /* RCTAllocationTests.m */,
|
||||
1497CFA51B21F5E400C1F8F2 /* RCTBridgeTests.m */,
|
||||
144D21231B2204C5006DB32B /* RCTClippingTests.m */,
|
||||
1497CFA61B21F5E400C1F8F2 /* RCTContextExecutorTests.m */,
|
||||
1497CFA71B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m */,
|
||||
1497CFA81B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m */,
|
||||
1497CFA91B21F5E400C1F8F2 /* RCTEventDispatcherTests.m */,
|
||||
1497CFAA1B21F5E400C1F8F2 /* RCTSparseArrayTests.m */,
|
||||
1497CFAB1B21F5E400C1F8F2 /* RCTUIManagerTests.m */,
|
||||
143BC57E1B21E18100462512 /* Info.plist */,
|
||||
14D6D7101B220EB3001FB087 /* libOCMock.a */,
|
||||
14D6D7011B220AE3001FB087 /* OCMock */,
|
||||
143BC57F1B21E18100462512 /* ReferenceImages */,
|
||||
);
|
||||
path = UIExplorerUnitTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
143BC57F1B21E18100462512 /* ReferenceImages */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
143BC5801B21E18100462512 /* Examples-UIExplorer-UIExplorerApp */,
|
||||
);
|
||||
path = ReferenceImages;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
143BC5801B21E18100462512 /* Examples-UIExplorer-UIExplorerApp */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
143BC5811B21E18100462512 /* testLayoutExampleSnapshot_1@2x.png */,
|
||||
143BC5821B21E18100462512 /* testSliderExampleSnapshot_1@2x.png */,
|
||||
143BC5831B21E18100462512 /* testSwitchExampleSnapshot_1@2x.png */,
|
||||
143BC5841B21E18100462512 /* testTabBarExampleSnapshot_1@2x.png */,
|
||||
143BC5851B21E18100462512 /* testTextExampleSnapshot_1@2x.png */,
|
||||
143BC5861B21E18100462512 /* testViewExampleSnapshot_1@2x.png */,
|
||||
);
|
||||
path = "Examples-UIExplorer-UIExplorerApp";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
143BC5961B21E3E100462512 /* UIExplorerIntegrationTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
141FC1201B222EBB004D5FFB /* IntegrationTestsTests.m */,
|
||||
143BC5A01B21E45C00462512 /* UIExplorerIntegrationTests.m */,
|
||||
143BC5971B21E3E100462512 /* Supporting Files */,
|
||||
);
|
||||
path = UIExplorerIntegrationTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
143BC5971B21E3E100462512 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
143BC5981B21E3E100462512 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
147CED471AB34F8C00DA3E4C /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -291,6 +401,29 @@
|
|||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
14D6D6EA1B2205C0001FB087 /* OCMock */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
path = OCMock;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
14D6D7011B220AE3001FB087 /* OCMock */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
14D6D7021B220AE3001FB087 /* NSNotificationCenter+OCMAdditions.h */,
|
||||
14D6D7031B220AE3001FB087 /* OCMArg.h */,
|
||||
14D6D7041B220AE3001FB087 /* OCMConstraint.h */,
|
||||
14D6D7051B220AE3001FB087 /* OCMLocation.h */,
|
||||
14D6D7061B220AE3001FB087 /* OCMMacroState.h */,
|
||||
14D6D7071B220AE3001FB087 /* OCMock.h */,
|
||||
14D6D7081B220AE3001FB087 /* OCMockObject.h */,
|
||||
14D6D7091B220AE3001FB087 /* OCMRecorder.h */,
|
||||
14D6D70A1B220AE3001FB087 /* OCMStubRecorder.h */,
|
||||
);
|
||||
path = OCMock;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
14DC67E81AB71876001358AB /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -320,7 +453,9 @@
|
|||
children = (
|
||||
13B07FAE1A68108700A75B9A /* UIExplorer */,
|
||||
1316A21D1AA397F400C0188E /* Libraries */,
|
||||
004D289F1AAF61C70097A701 /* UIExplorerTests */,
|
||||
143BC57C1B21E18100462512 /* UIExplorerUnitTests */,
|
||||
143BC5961B21E3E100462512 /* UIExplorerIntegrationTests */,
|
||||
14D6D6EA1B2205C0001FB087 /* OCMock */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
|
@ -331,7 +466,8 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* UIExplorer.app */,
|
||||
004D289E1AAF61C70097A701 /* UIExplorerTests.xctest */,
|
||||
004D289E1AAF61C70097A701 /* UIExplorerUnitTests.xctest */,
|
||||
143BC5951B21E3E100462512 /* UIExplorerIntegrationTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
@ -347,9 +483,9 @@
|
|||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
004D289D1AAF61C70097A701 /* UIExplorerTests */ = {
|
||||
004D289D1AAF61C70097A701 /* UIExplorerUnitTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 004D28AD1AAF61C70097A701 /* Build configuration list for PBXNativeTarget "UIExplorerTests" */;
|
||||
buildConfigurationList = 004D28AD1AAF61C70097A701 /* Build configuration list for PBXNativeTarget "UIExplorerUnitTests" */;
|
||||
buildPhases = (
|
||||
004D289A1AAF61C70097A701 /* Sources */,
|
||||
004D289B1AAF61C70097A701 /* Frameworks */,
|
||||
|
@ -358,11 +494,10 @@
|
|||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
004D28A51AAF61C70097A701 /* PBXTargetDependency */,
|
||||
);
|
||||
name = UIExplorerTests;
|
||||
name = UIExplorerUnitTests;
|
||||
productName = UIExplorerTests;
|
||||
productReference = 004D289E1AAF61C70097A701 /* UIExplorerTests.xctest */;
|
||||
productReference = 004D289E1AAF61C70097A701 /* UIExplorerUnitTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
13B07F861A680F5B00A75B9A /* UIExplorer */ = {
|
||||
|
@ -382,6 +517,24 @@
|
|||
productReference = 13B07F961A680F5B00A75B9A /* UIExplorer.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
143BC5941B21E3E100462512 /* UIExplorerIntegrationTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 143BC59D1B21E3E100462512 /* Build configuration list for PBXNativeTarget "UIExplorerIntegrationTests" */;
|
||||
buildPhases = (
|
||||
143BC5911B21E3E100462512 /* Sources */,
|
||||
143BC5921B21E3E100462512 /* Frameworks */,
|
||||
143BC5931B21E3E100462512 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
143BC59C1B21E3E100462512 /* PBXTargetDependency */,
|
||||
);
|
||||
name = UIExplorerIntegrationTests;
|
||||
productName = UIExplorerIntegrationTests;
|
||||
productReference = 143BC5951B21E3E100462512 /* UIExplorerIntegrationTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
|
@ -393,6 +546,9 @@
|
|||
TargetAttributes = {
|
||||
004D289D1AAF61C70097A701 = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
143BC5941B21E3E100462512 = {
|
||||
CreatedOnToolsVersion = 6.3.2;
|
||||
TestTargetID = 13B07F861A680F5B00A75B9A;
|
||||
};
|
||||
};
|
||||
|
@ -461,7 +617,8 @@
|
|||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* UIExplorer */,
|
||||
004D289D1AAF61C70097A701 /* UIExplorerTests */,
|
||||
004D289D1AAF61C70097A701 /* UIExplorerUnitTests */,
|
||||
143BC5941B21E3E100462512 /* UIExplorerIntegrationTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
@ -570,6 +727,13 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
143BC5931B21E3E100462512 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
|
@ -577,8 +741,15 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
004D28A31AAF61C70097A701 /* UIExplorerTests.m in Sources */,
|
||||
1353F5461B0E64F9009B4FAC /* ClippingTests.m in Sources */,
|
||||
1497CFB01B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m in Sources */,
|
||||
144D21241B2204C5006DB32B /* RCTClippingTests.m in Sources */,
|
||||
1497CFB21B21F5E400C1F8F2 /* RCTSparseArrayTests.m in Sources */,
|
||||
1497CFAF1B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m in Sources */,
|
||||
1497CFAE1B21F5E400C1F8F2 /* RCTContextExecutorTests.m in Sources */,
|
||||
1497CFAD1B21F5E400C1F8F2 /* RCTBridgeTests.m in Sources */,
|
||||
1497CFB11B21F5E400C1F8F2 /* RCTEventDispatcherTests.m in Sources */,
|
||||
1497CFB31B21F5E400C1F8F2 /* RCTUIManagerTests.m in Sources */,
|
||||
1497CFAC1B21F5E400C1F8F2 /* RCTAllocationTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -591,13 +762,22 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
143BC5911B21E3E100462512 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
141FC1211B222EBB004D5FFB /* IntegrationTestsTests.m in Sources */,
|
||||
143BC5A11B21E45C00462512 /* UIExplorerIntegrationTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
004D28A51AAF61C70097A701 /* PBXTargetDependency */ = {
|
||||
143BC59C1B21E3E100462512 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 13B07F861A680F5B00A75B9A /* UIExplorer */;
|
||||
targetProxy = 004D28A41AAF61C70097A701 /* PBXContainerItemProxy */;
|
||||
targetProxy = 143BC59B1B21E3E100462512 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
|
@ -617,47 +797,59 @@
|
|||
004D28A61AAF61C70097A701 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"FB_REFERENCE_IMAGE_DIR=\"\\\"$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages\\\"\"",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../React/**",
|
||||
"$(SRCROOT)/UIExplorerUnitTests/**",
|
||||
);
|
||||
INFOPLIST_FILE = UIExplorerTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
INFOPLIST_FILE = UIExplorerUnitTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/UIExplorerUnitTests",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-framework",
|
||||
XCTest,
|
||||
"-ObjC",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UIExplorer.app/UIExplorer";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
004D28A71AAF61C70097A701 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../React/**",
|
||||
"$(SRCROOT)/UIExplorerUnitTests/**",
|
||||
);
|
||||
INFOPLIST_FILE = UIExplorerTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
INFOPLIST_FILE = UIExplorerUnitTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/UIExplorerUnitTests",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-framework",
|
||||
XCTest,
|
||||
"-ObjC",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UIExplorer.app/UIExplorer";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
@ -698,6 +890,47 @@
|
|||
};
|
||||
name = Release;
|
||||
};
|
||||
143BC59E1B21E3E100462512 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
"FB_REFERENCE_IMAGE_DIR=\"\\\"$(SOURCE_ROOT)/$(PROJECT_NAME)IntegrationTests/ReferenceImages\\\"\"",
|
||||
);
|
||||
INFOPLIST_FILE = UIExplorerIntegrationTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UIExplorer.app/UIExplorer";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
143BC59F1B21E3E100462512 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = UIExplorerIntegrationTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UIExplorer.app/UIExplorer";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
|
@ -787,7 +1020,7 @@
|
|||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
004D28AD1AAF61C70097A701 /* Build configuration list for PBXNativeTarget "UIExplorerTests" */ = {
|
||||
004D28AD1AAF61C70097A701 /* Build configuration list for PBXNativeTarget "UIExplorerUnitTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
004D28A61AAF61C70097A701 /* Debug */,
|
||||
|
@ -805,6 +1038,15 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
143BC59D1B21E3E100462512 /* Build configuration list for PBXNativeTarget "UIExplorerIntegrationTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
143BC59E1B21E3E100462512 /* Debug */,
|
||||
143BC59F1B21E3E100462512 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "UIExplorer" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
|
@ -29,8 +29,22 @@
|
|||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "004D289D1AAF61C70097A701"
|
||||
BuildableName = "UIExplorerTests.xctest"
|
||||
BlueprintName = "UIExplorerTests"
|
||||
BuildableName = "UIExplorerUnitTests.xctest"
|
||||
BlueprintName = "UIExplorerUnitTests"
|
||||
ReferencedContainer = "container:UIExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "143BC5941B21E3E100462512"
|
||||
BuildableName = "UIExplorerIntegrationTests.xctest"
|
||||
BlueprintName = "UIExplorerIntegrationTests"
|
||||
ReferencedContainer = "container:UIExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
|
@ -47,8 +61,18 @@
|
|||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "004D289D1AAF61C70097A701"
|
||||
BuildableName = "UIExplorerTests.xctest"
|
||||
BlueprintName = "UIExplorerTests"
|
||||
BuildableName = "UIExplorerUnitTests.xctest"
|
||||
BlueprintName = "UIExplorerUnitTests"
|
||||
ReferencedContainer = "container:UIExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "143BC5941B21E3E100462512"
|
||||
BuildableName = "UIExplorerIntegrationTests.xctest"
|
||||
BlueprintName = "UIExplorerIntegrationTests"
|
||||
ReferencedContainer = "container:UIExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
* on the same Wi-Fi network.
|
||||
*/
|
||||
|
||||
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/UIExplorer/UIExplorerApp.includeRequire.runModule.bundle?dev=true"];
|
||||
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/UIExplorer/UIExplorerApp.ios.includeRequire.runModule.bundle?dev=true"];
|
||||
|
||||
/**
|
||||
* OPTION 2
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* 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 UIExplorerApp
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var Dimensions = require('Dimensions');
|
||||
var DrawerLayoutAndroid = require('DrawerLayoutAndroid');
|
||||
var ToolbarAndroid = require('ToolbarAndroid');
|
||||
var UIExplorerList = require('./UIExplorerList');
|
||||
var {
|
||||
StyleSheet,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var DRAWER_WIDTH_LEFT = 56;
|
||||
|
||||
var UIExplorerApp = React.createClass({
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
example: {
|
||||
title: 'UIExplorer',
|
||||
component: this._renderHome(),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<DrawerLayoutAndroid
|
||||
drawerPosition={DrawerLayoutAndroid.positions.Left}
|
||||
drawerWidth={Dimensions.get('window').width - DRAWER_WIDTH_LEFT}
|
||||
ref={(drawer) => { this.drawer = drawer; }}
|
||||
renderNavigationView={this._renderNavigationView}>
|
||||
{this._renderNavigation()}
|
||||
</DrawerLayoutAndroid>
|
||||
);
|
||||
},
|
||||
|
||||
_renderNavigationView: function() {
|
||||
return (
|
||||
<UIExplorerList
|
||||
onSelectExample={this.onSelectExample}
|
||||
isInDrawer={true}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
onSelectExample: function(example) {
|
||||
this.drawer.closeDrawer();
|
||||
if (example.title === 'UIExplorer') {
|
||||
example.component = this._renderHome();
|
||||
}
|
||||
this.setState({
|
||||
example: {
|
||||
title: example.title,
|
||||
component: example.component,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
_renderHome: function() {
|
||||
var onSelectExample = this.onSelectExample;
|
||||
return React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerList
|
||||
onSelectExample={onSelectExample}
|
||||
isInDrawer={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_renderNavigation: function() {
|
||||
var Component = this.state.example.component;
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ToolbarAndroid
|
||||
logo={require('image!launcher_icon')}
|
||||
navIcon={require('image!ic_menu_black_24dp')}
|
||||
onIconClicked={() => this.drawer.openDrawer()}
|
||||
style={styles.toolbar}
|
||||
title={this.state.example.title}
|
||||
/>
|
||||
<Component />
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
messageText: {
|
||||
fontSize: 17,
|
||||
fontWeight: '500',
|
||||
padding: 15,
|
||||
marginTop: 50,
|
||||
marginLeft: 15,
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
toolbar: {
|
||||
backgroundColor: '#E9EAED',
|
||||
height: 56,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = UIExplorerApp;
|
|
@ -43,22 +43,22 @@ var UIExplorerApp = React.createClass({
|
|||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<NavigatorIOS
|
||||
style={styles.container}
|
||||
initialRoute={{
|
||||
title: 'UIExplorer',
|
||||
component: UIExplorerList,
|
||||
passProps: {
|
||||
onExternalExampleRequested: (example) => {
|
||||
this.setState({ openExternalExample: example, });
|
||||
},
|
||||
}
|
||||
}}
|
||||
itemWrapperStyle={styles.itemWrapper}
|
||||
tintColor='#008888'
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<NavigatorIOS
|
||||
style={styles.container}
|
||||
initialRoute={{
|
||||
title: 'UIExplorer',
|
||||
component: UIExplorerList,
|
||||
passProps: {
|
||||
onExternalExampleRequested: (example) => {
|
||||
this.setState({ openExternalExample: example, });
|
||||
},
|
||||
}
|
||||
}}
|
||||
itemWrapperStyle={styles.itemWrapper}
|
||||
tintColor="#008888"
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.facebook.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<string>com.facebook.React.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
|
@ -30,10 +30,10 @@
|
|||
#endif
|
||||
NSString *version = [[UIDevice currentDevice] systemVersion];
|
||||
RCTAssert([version integerValue] == 8, @"Tests should be run on iOS 8.x, found %@", version);
|
||||
_runner = RCTInitRunnerForApp(@"IntegrationTests/IntegrationTestsApp");
|
||||
_runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerIntegrationTests/js/IntegrationTestsApp");
|
||||
|
||||
// If tests have changes, set recordMode = YES below and run the affected
|
||||
// tests on an iPhone5, iOS 8.1 simulator.
|
||||
// tests on an iPhone5, iOS 8.3 simulator.
|
||||
_runner.recordMode = NO;
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@
|
|||
[_runner runTest:_cmd module:@"AsyncStorageTest"];
|
||||
}
|
||||
|
||||
- (void)testLayoutEvents
|
||||
- (void)DISABLED_testLayoutEvents // #7149037
|
||||
{
|
||||
[_runner runTest:_cmd module:@"LayoutEventsTest"];
|
||||
}
|
||||
|
@ -81,6 +81,11 @@
|
|||
[_runner runTest:_cmd module:@"AppEventsTest"];
|
||||
}
|
||||
|
||||
- (void)testPromises
|
||||
{
|
||||
[_runner runTest:_cmd module:@"PromiseTest"];
|
||||
}
|
||||
|
||||
#pragma mark Snapshot Tests
|
||||
|
||||
- (void)testSimpleSnapshot
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 269 KiB After Width: | Height: | Size: 269 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
@ -39,7 +39,7 @@
|
|||
#endif
|
||||
NSString *version = [[UIDevice currentDevice] systemVersion];
|
||||
RCTAssert([version isEqualToString:@"8.3"], @"Snapshot tests should be run on iOS 8.3, found %@", version);
|
||||
_runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerApp");
|
||||
_runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerApp.ios");
|
||||
|
||||
// If tests have changes, set recordMode = YES below and run the affected
|
||||
// tests on an iPhone5, iOS 8.1 simulator.
|
|
@ -28,6 +28,7 @@ var TESTS = [
|
|||
require('./LayoutEventsTest'),
|
||||
require('./AppEventsTest'),
|
||||
require('./SimpleSnapshotTest'),
|
||||
require('./PromiseTest'),
|
||||
];
|
||||
|
||||
TESTS.forEach(
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* 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 PromiseTest
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var RCTTestModule = require('NativeModules').TestModule;
|
||||
var React = require('react-native');
|
||||
|
||||
var PromiseTest = React.createClass({
|
||||
|
||||
shouldResolve: false,
|
||||
shouldReject: false,
|
||||
|
||||
componentDidMount() {
|
||||
Promise.all([
|
||||
this.testShouldResolve(),
|
||||
this.testShouldReject(),
|
||||
]).then(() => RCTTestModule.finish(
|
||||
this.shouldResolve && this.shouldReject
|
||||
));
|
||||
},
|
||||
|
||||
testShouldResolve() {
|
||||
return RCTTestModule
|
||||
.shouldResolve()
|
||||
.then(() => this.shouldResolve = true)
|
||||
.catch(() => this.shouldResolve = false);
|
||||
},
|
||||
|
||||
testShouldReject() {
|
||||
return RCTTestModule
|
||||
.shouldReject()
|
||||
.then(() => this.shouldReject = false)
|
||||
.catch(() => this.shouldReject = true);
|
||||
},
|
||||
|
||||
render() {
|
||||
return <React.View />;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = PromiseTest;
|
|
@ -20,6 +20,7 @@ var {
|
|||
AppRegistry,
|
||||
ListView,
|
||||
PixelRatio,
|
||||
Platform,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
|
@ -34,51 +35,67 @@ import type { ExampleModule } from 'ExampleTypes';
|
|||
|
||||
var createExamplePage = require('./createExamplePage');
|
||||
|
||||
var COMPONENTS = [
|
||||
require('./ActivityIndicatorIOSExample'),
|
||||
require('./DatePickerIOSExample'),
|
||||
require('./ImageExample'),
|
||||
require('./ListViewExample'),
|
||||
require('./ListViewPagingExample'),
|
||||
require('./MapViewExample'),
|
||||
require('./Navigator/NavigatorExample'),
|
||||
require('./NavigatorIOSColorsExample'),
|
||||
require('./NavigatorIOSExample'),
|
||||
require('./PickerIOSExample'),
|
||||
require('./ProgressViewIOSExample'),
|
||||
require('./ScrollViewExample'),
|
||||
require('./SegmentedControlIOSExample'),
|
||||
require('./SliderIOSExample'),
|
||||
require('./SwitchIOSExample'),
|
||||
require('./TabBarIOSExample'),
|
||||
require('./TextExample.ios'),
|
||||
require('./TextInputExample'),
|
||||
require('./TouchableExample'),
|
||||
var COMMON_COMPONENTS = [
|
||||
require('./ViewExample'),
|
||||
require('./WebViewExample'),
|
||||
];
|
||||
|
||||
var APIS = [
|
||||
require('./AccessibilityIOSExample'),
|
||||
require('./ActionSheetIOSExample'),
|
||||
require('./AdSupportIOSExample'),
|
||||
require('./AlertIOSExample'),
|
||||
require('./AppStateIOSExample'),
|
||||
require('./AsyncStorageExample'),
|
||||
require('./BorderExample'),
|
||||
require('./CameraRollExample.ios'),
|
||||
var COMMON_APIS = [
|
||||
require('./GeolocationExample'),
|
||||
require('./LayoutEventsExample'),
|
||||
require('./LayoutExample'),
|
||||
require('./NetInfoExample'),
|
||||
require('./PanResponderExample'),
|
||||
require('./PointerEventsExample'),
|
||||
require('./PushNotificationIOSExample'),
|
||||
require('./StatusBarIOSExample'),
|
||||
require('./TimerExample'),
|
||||
require('./VibrationIOSExample'),
|
||||
];
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
var COMPONENTS = COMMON_COMPONENTS.concat([
|
||||
require('./ActivityIndicatorIOSExample'),
|
||||
require('./DatePickerIOSExample'),
|
||||
require('./ImageExample'),
|
||||
require('./ListViewExample'),
|
||||
require('./ListViewPagingExample'),
|
||||
require('./MapViewExample'),
|
||||
require('./Navigator/NavigatorExample'),
|
||||
require('./NavigatorIOSColorsExample'),
|
||||
require('./NavigatorIOSExample'),
|
||||
require('./PickerIOSExample'),
|
||||
require('./ProgressViewIOSExample'),
|
||||
require('./ScrollViewExample'),
|
||||
require('./SegmentedControlIOSExample'),
|
||||
require('./SliderIOSExample'),
|
||||
require('./SwitchIOSExample'),
|
||||
require('./TabBarIOSExample'),
|
||||
require('./TextExample.ios'),
|
||||
require('./TextInputExample'),
|
||||
require('./TouchableExample'),
|
||||
]);
|
||||
|
||||
var APIS = COMMON_APIS.concat([
|
||||
require('./AccessibilityIOSExample'),
|
||||
require('./ActionSheetIOSExample'),
|
||||
require('./AdSupportIOSExample'),
|
||||
require('./AlertIOSExample'),
|
||||
require('./AppStateIOSExample'),
|
||||
require('./AsyncStorageExample'),
|
||||
require('./BorderExample'),
|
||||
require('./CameraRollExample.ios'),
|
||||
require('./LayoutEventsExample'),
|
||||
require('./NetInfoExample'),
|
||||
require('./PointerEventsExample'),
|
||||
require('./PushNotificationIOSExample'),
|
||||
require('./StatusBarIOSExample'),
|
||||
require('./TimerExample'),
|
||||
require('./VibrationIOSExample'),
|
||||
require('./XHRExample'),
|
||||
]);
|
||||
|
||||
} else if (Platform.OS === 'android') {
|
||||
var COMPONENTS = COMMON_COMPONENTS.concat([
|
||||
]);
|
||||
|
||||
var APIS = COMMON_APIS.concat([
|
||||
]);
|
||||
}
|
||||
|
||||
var ds = new ListView.DataSource({
|
||||
rowHasChanged: (r1, r2) => r1 !== r2,
|
||||
sectionHeaderHasChanged: (h1, h2) => h1 !== h2,
|
||||
|
@ -114,10 +131,10 @@ COMPONENTS.concat(APIS).forEach((Example) => {
|
|||
type Props = {
|
||||
navigator: Array<{title: string, component: ReactClass<any,any,any>}>,
|
||||
onExternalExampleRequested: Function,
|
||||
onSelectExample: Function,
|
||||
isInDrawer: bool,
|
||||
};
|
||||
|
||||
|
||||
|
||||
class UIExplorerList extends React.Component {
|
||||
props: Props;
|
||||
|
||||
|
@ -128,7 +145,7 @@ class UIExplorerList extends React.Component {
|
|||
components: COMPONENTS,
|
||||
apis: APIS,
|
||||
}),
|
||||
searchText: Settings.get('searchText'),
|
||||
searchText: Platform.OS === 'ios' ? Settings.get('searchText') : '',
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -137,8 +154,12 @@ class UIExplorerList extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.listContainer}>
|
||||
if (Platform.OS === 'ios' ||
|
||||
(Platform.OS === 'android' && !this.props.isInDrawer)) {
|
||||
var platformTextInputStyle =
|
||||
Platform.OS === 'ios' ? styles.searchTextInputIOS :
|
||||
Platform.OS === 'android' ? styles.searchTextInputAndroid : {};
|
||||
var textInput = (
|
||||
<View style={styles.searchRow}>
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
|
@ -146,10 +167,24 @@ class UIExplorerList extends React.Component {
|
|||
clearButtonMode="always"
|
||||
onChangeText={this._search.bind(this)}
|
||||
placeholder="Search..."
|
||||
style={styles.searchTextInput}
|
||||
style={[styles.searchTextInput, platformTextInputStyle]}
|
||||
value={this.state.searchText}
|
||||
/>
|
||||
</View>
|
||||
</View>);
|
||||
}
|
||||
|
||||
var homePage;
|
||||
if (Platform.OS === 'android' && this.props.isInDrawer) {
|
||||
homePage = this._renderRow({
|
||||
title: 'UIExplorer',
|
||||
description: 'List of examples',
|
||||
}, -1);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.listContainer}>
|
||||
{textInput}
|
||||
{homePage}
|
||||
<ListView
|
||||
style={styles.list}
|
||||
dataSource={this.state.dataSource}
|
||||
|
@ -173,7 +208,7 @@ class UIExplorerList extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
_renderRow(example: ExampleModule, i: number) {
|
||||
_renderRow(example: any, i: number) {
|
||||
return (
|
||||
<View key={i}>
|
||||
<TouchableHighlight onPress={() => this._onPressRow(example)}>
|
||||
|
@ -205,16 +240,23 @@ class UIExplorerList extends React.Component {
|
|||
Settings.set({searchText: text});
|
||||
}
|
||||
|
||||
_onPressRow(example: ExampleModule) {
|
||||
_onPressRow(example: any) {
|
||||
if (example.external) {
|
||||
this.props.onExternalExampleRequested(example);
|
||||
return;
|
||||
}
|
||||
var Component = makeRenderable(example);
|
||||
this.props.navigator.push({
|
||||
title: Component.title,
|
||||
component: Component,
|
||||
});
|
||||
if (Platform.OS === 'ios') {
|
||||
this.props.navigator.push({
|
||||
title: Component.title,
|
||||
component: Component,
|
||||
});
|
||||
} else if (Platform.OS === 'android') {
|
||||
this.props.onSelectExample({
|
||||
title: Component.title,
|
||||
component: Component,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,9 +309,14 @@ var styles = StyleSheet.create({
|
|||
borderColor: '#cccccc',
|
||||
borderRadius: 3,
|
||||
borderWidth: 1,
|
||||
height: 30,
|
||||
paddingLeft: 8,
|
||||
},
|
||||
searchTextInputIOS: {
|
||||
height: 30,
|
||||
},
|
||||
searchTextInputAndroid: {
|
||||
padding: 2,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = UIExplorerList;
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import <OCMock/OCMock.h>
|
||||
|
||||
@interface LayoutSubviewsOrderingTest : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation LayoutSubviewsOrderingTest
|
||||
|
||||
/**
|
||||
* This test exists to insure that didLayoutSubviews is always called immediately after layoutSubviews for a VC:View
|
||||
* pair. In Catalyst we have multiple levels of ViewController containment, and we rely on this ordering
|
||||
* to insure that layoutGuides are set on RKViewControllers before Views further down in the heirarchy have
|
||||
* their layoutSubviews called (and need to use the aforementioned layoutGuides)
|
||||
*/
|
||||
- (void)testLayoutSubviewsOrdering
|
||||
{
|
||||
// create some Views and ViewControllers
|
||||
UIViewController *parentVC = [[UIViewController alloc] init];
|
||||
UIView *parentView = [[UIView alloc] init];
|
||||
UIViewController *childVC = [[UIViewController alloc] init];
|
||||
UIView *childView = [[UIView alloc] init];
|
||||
|
||||
// The ordering we expect is:
|
||||
// parentView::layoutSubviews
|
||||
// parentVC::didLayoutSubviews
|
||||
// childView::layoutSubviews
|
||||
// childVC::didLayoutSubviews
|
||||
|
||||
id parentViewMock = [OCMockObject partialMockForObject:parentView];
|
||||
id parentVCMock = [OCMockObject partialMockForObject:parentVC];
|
||||
id childViewMock = [OCMockObject partialMockForObject:childView];
|
||||
id childVCMock = [OCMockObject partialMockForObject:childVC];
|
||||
|
||||
__block int layoutOrderCount = 0;
|
||||
[[[parentViewMock stub] andDo:^(NSInvocation *inv) {
|
||||
if (layoutOrderCount < 4) {
|
||||
layoutOrderCount++;
|
||||
XCTAssertEqual(layoutOrderCount, 1, @"Expect parentView::layoutSubviews to be called first");
|
||||
}
|
||||
}] layoutSubviews];
|
||||
[[[parentVCMock stub] andDo:^(NSInvocation *inv) {
|
||||
if (layoutOrderCount < 4) {
|
||||
layoutOrderCount++;
|
||||
XCTAssertEqual(layoutOrderCount, 2, @"Expect parentVC::viewDidLayoutSubviews to be called 2nd");
|
||||
}
|
||||
}] viewDidLayoutSubviews];
|
||||
[[[childViewMock stub] andDo:^(NSInvocation *inv) {
|
||||
if (layoutOrderCount < 4) {
|
||||
layoutOrderCount++;
|
||||
XCTAssertEqual(layoutOrderCount, 3, @"Expect childView::layoutSubviews to be called 3rd");
|
||||
}
|
||||
}] layoutSubviews];
|
||||
[[[childVCMock stub] andDo:^(NSInvocation *inv) {
|
||||
if (layoutOrderCount < 4) {
|
||||
layoutOrderCount++;
|
||||
XCTAssertEqual(layoutOrderCount, 4, @"Expect childVC::viewDidLayoutSubviews to be called last");
|
||||
[childVCMock stopMocking];
|
||||
}
|
||||
}] viewDidLayoutSubviews];
|
||||
|
||||
// setup View heirarchy and force layout
|
||||
parentVC.view = parentView;
|
||||
childVC.view = childView;
|
||||
[parentVC addChildViewController:childVC];
|
||||
[childVC didMoveToParentViewController:parentVC];
|
||||
[parentView addSubview:childView];
|
||||
|
||||
[childViewMock setNeedsLayout];
|
||||
[parentViewMock layoutIfNeeded];
|
||||
|
||||
XCTAssertEqual(layoutOrderCount, 4, @"Expect layoutSubviews/viewDidLayoutSubviews to be called");
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class OCObserverMockObject;
|
||||
|
||||
|
||||
@interface NSNotificationCenter(OCMAdditions)
|
||||
|
||||
- (void)addMockObserver:(OCObserverMockObject *)notificationObserver name:(NSString *)notificationName object:(id)notificationSender;
|
||||
|
||||
@end
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface OCMArg : NSObject
|
||||
|
||||
// constraining arguments
|
||||
|
||||
+ (id)any;
|
||||
+ (SEL)anySelector;
|
||||
+ (void *)anyPointer;
|
||||
+ (id __autoreleasing *)anyObjectRef;
|
||||
+ (id)isNil;
|
||||
+ (id)isNotNil;
|
||||
+ (id)isEqual:(id)value;
|
||||
+ (id)isNotEqual:(id)value;
|
||||
+ (id)isKindOfClass:(Class)cls;
|
||||
+ (id)checkWithSelector:(SEL)selector onObject:(id)anObject;
|
||||
+ (id)checkWithBlock:(BOOL (^)(id obj))block;
|
||||
|
||||
// manipulating arguments
|
||||
|
||||
+ (id *)setTo:(id)value;
|
||||
+ (void *)setToValue:(NSValue *)value;
|
||||
|
||||
// internal use only
|
||||
|
||||
+ (id)resolveSpecialValues:(NSValue *)value;
|
||||
|
||||
@end
|
||||
|
||||
#define OCMOCK_ANY [OCMArg any]
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define OCMOCK_VALUE(variable) \
|
||||
({ __typeof__(variable) __v = (variable); [NSValue value:&__v withObjCType:@encode(__typeof__(__v))]; })
|
||||
#else
|
||||
#define OCMOCK_VALUE(variable) [NSValue value:&variable withObjCType:@encode(__typeof__(variable))]
|
||||
#endif
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2007-2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
@interface OCMConstraint : NSObject
|
||||
|
||||
+ (instancetype)constraint;
|
||||
- (BOOL)evaluate:(id)value;
|
||||
|
||||
// if you are looking for any, isNil, etc, they have moved to OCMArg
|
||||
|
||||
// try to use [OCMArg checkWith...] instead of the constraintWith... methods below
|
||||
|
||||
+ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject;
|
||||
+ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject withValue:(id)aValue;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@interface OCMAnyConstraint : OCMConstraint
|
||||
@end
|
||||
|
||||
@interface OCMIsNilConstraint : OCMConstraint
|
||||
@end
|
||||
|
||||
@interface OCMIsNotNilConstraint : OCMConstraint
|
||||
@end
|
||||
|
||||
@interface OCMIsNotEqualConstraint : OCMConstraint
|
||||
{
|
||||
@public
|
||||
id testValue;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface OCMInvocationConstraint : OCMConstraint
|
||||
{
|
||||
@public
|
||||
NSInvocation *invocation;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface OCMBlockConstraint : OCMConstraint
|
||||
{
|
||||
BOOL (^block)(id);
|
||||
}
|
||||
|
||||
- (instancetype)initWithConstraintBlock:(BOOL (^)(id))block;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#define CONSTRAINT(aSelector) [OCMConstraint constraintWithSelector:aSelector onObject:self]
|
||||
#define CONSTRAINTV(aSelector, aValue) [OCMConstraint constraintWithSelector:aSelector onObject:self withValue:(aValue)]
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface OCMLocation : NSObject
|
||||
{
|
||||
id testCase;
|
||||
NSString *file;
|
||||
NSUInteger line;
|
||||
}
|
||||
|
||||
+ (instancetype)locationWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine;
|
||||
|
||||
- (instancetype)initWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine;
|
||||
|
||||
- (id)testCase;
|
||||
- (NSString *)file;
|
||||
- (NSUInteger)line;
|
||||
|
||||
@end
|
||||
|
||||
extern OCMLocation *OCMMakeLocation(id testCase, const char *file, int line);
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class OCMLocation;
|
||||
@class OCMRecorder;
|
||||
@class OCMStubRecorder;
|
||||
@class OCMockObject;
|
||||
|
||||
|
||||
@interface OCMMacroState : NSObject
|
||||
{
|
||||
OCMRecorder *recorder;
|
||||
}
|
||||
|
||||
+ (void)beginStubMacro;
|
||||
+ (OCMStubRecorder *)endStubMacro;
|
||||
|
||||
+ (void)beginExpectMacro;
|
||||
+ (OCMStubRecorder *)endExpectMacro;
|
||||
|
||||
+ (void)beginVerifyMacroAtLocation:(OCMLocation *)aLocation;
|
||||
+ (void)endVerifyMacro;
|
||||
|
||||
+ (OCMMacroState *)globalState;
|
||||
|
||||
- (OCMRecorder *)recorder;
|
||||
|
||||
- (void)switchToClassMethod;
|
||||
|
||||
@end
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class OCMockObject;
|
||||
@class OCMInvocationMatcher;
|
||||
|
||||
|
||||
@interface OCMRecorder : NSProxy
|
||||
{
|
||||
OCMockObject *mockObject;
|
||||
OCMInvocationMatcher *invocationMatcher;
|
||||
}
|
||||
|
||||
- (instancetype)init;
|
||||
- (instancetype)initWithMockObject:(OCMockObject *)aMockObject;
|
||||
|
||||
- (void)setMockObject:(OCMockObject *)aMockObject;
|
||||
|
||||
- (OCMInvocationMatcher *)invocationMatcher;
|
||||
|
||||
- (id)classMethod;
|
||||
- (id)ignoringNonObjectArgs;
|
||||
|
||||
@end
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2004-2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import "OCMRecorder.h"
|
||||
|
||||
|
||||
@interface OCMStubRecorder : OCMRecorder
|
||||
|
||||
- (id)andReturn:(id)anObject;
|
||||
- (id)andReturnValue:(NSValue *)aValue;
|
||||
- (id)andThrow:(NSException *)anException;
|
||||
- (id)andPost:(NSNotification *)aNotification;
|
||||
- (id)andCall:(SEL)selector onObject:(id)anObject;
|
||||
- (id)andDo:(void (^)(NSInvocation *invocation))block;
|
||||
- (id)andForwardToRealObject;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface OCMStubRecorder (Properties)
|
||||
|
||||
#define andReturn(aValue) _andReturn(({ __typeof__(aValue) _v = (aValue); [NSValue value:&_v withObjCType:@encode(__typeof__(_v))]; }))
|
||||
@property (nonatomic, readonly) OCMStubRecorder *(^ _andReturn)(NSValue *);
|
||||
|
||||
#define andThrow(anException) _andThrow(anException)
|
||||
@property (nonatomic, readonly) OCMStubRecorder *(^ _andThrow)(NSException *);
|
||||
|
||||
#define andPost(aNotification) _andPost(aNotification)
|
||||
@property (nonatomic, readonly) OCMStubRecorder *(^ _andPost)(NSNotification *);
|
||||
|
||||
#define andCall(anObject, aSelector) _andCall(anObject, aSelector)
|
||||
@property (nonatomic, readonly) OCMStubRecorder *(^ _andCall)(id, SEL);
|
||||
|
||||
#define andDo(aBlock) _andDo(aBlock)
|
||||
@property (nonatomic, readonly) OCMStubRecorder *(^ _andDo)(void (^)(NSInvocation *));
|
||||
|
||||
#define andForwardToRealObject() _andForwardToRealObject()
|
||||
@property (nonatomic, readonly) OCMStubRecorder *(^ _andForwardToRealObject)(void);
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2004-2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <OCMock/OCMockObject.h>
|
||||
#import <OCMock/OCMRecorder.h>
|
||||
#import <OCMock/OCMStubRecorder.h>
|
||||
#import <OCMock/OCMConstraint.h>
|
||||
#import <OCMock/OCMArg.h>
|
||||
#import <OCMock/OCMLocation.h>
|
||||
#import <OCMock/OCMMacroState.h>
|
||||
#import <OCMock/NSNotificationCenter+OCMAdditions.h>
|
||||
|
||||
|
||||
#define OCMClassMock(cls) [OCMockObject niceMockForClass:cls]
|
||||
|
||||
#define OCMStrictClassMock(cls) [OCMockObject mockForClass:cls]
|
||||
|
||||
#define OCMProtocolMock(protocol) [OCMockObject niceMockForProtocol:protocol]
|
||||
|
||||
#define OCMStrictProtocolMock(protocol) [OCMockObject mockForProtocol:protocol]
|
||||
|
||||
#define OCMPartialMock(obj) [OCMockObject partialMockForObject:obj]
|
||||
|
||||
#define OCMObserverMock() [OCMockObject observerMock]
|
||||
|
||||
|
||||
#define OCMStub(invocation) \
|
||||
({ \
|
||||
_OCMSilenceWarnings( \
|
||||
[OCMMacroState beginStubMacro]; \
|
||||
invocation; \
|
||||
[OCMMacroState endStubMacro]; \
|
||||
); \
|
||||
})
|
||||
|
||||
#define OCMExpect(invocation) \
|
||||
({ \
|
||||
_OCMSilenceWarnings( \
|
||||
[OCMMacroState beginExpectMacro]; \
|
||||
invocation; \
|
||||
[OCMMacroState endExpectMacro]; \
|
||||
); \
|
||||
})
|
||||
|
||||
#define ClassMethod(invocation) \
|
||||
_OCMSilenceWarnings( \
|
||||
[[OCMMacroState globalState] switchToClassMethod]; \
|
||||
invocation; \
|
||||
);
|
||||
|
||||
|
||||
#define OCMVerifyAll(mock) [mock verifyAtLocation:OCMMakeLocation(self, __FILE__, __LINE__)]
|
||||
|
||||
#define OCMVerifyAllWithDelay(mock, delay) [mock verifyWithDelay:delay atLocation:OCMMakeLocation(self, __FILE__, __LINE__)]
|
||||
|
||||
#define OCMVerify(invocation) \
|
||||
({ \
|
||||
_OCMSilenceWarnings( \
|
||||
[OCMMacroState beginVerifyMacroAtLocation:OCMMakeLocation(self, __FILE__, __LINE__)]; \
|
||||
invocation; \
|
||||
[OCMMacroState endVerifyMacro]; \
|
||||
); \
|
||||
})
|
||||
|
||||
#define _OCMSilenceWarnings(macro) \
|
||||
({ \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wunused-value\"") \
|
||||
macro \
|
||||
_Pragma("clang diagnostic pop") \
|
||||
})
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2004-2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class OCMLocation;
|
||||
@class OCMInvocationStub;
|
||||
@class OCMStubRecorder;
|
||||
@class OCMInvocationMatcher;
|
||||
@class OCMInvocationExpectation;
|
||||
|
||||
|
||||
@interface OCMockObject : NSProxy
|
||||
{
|
||||
BOOL isNice;
|
||||
BOOL expectationOrderMatters;
|
||||
NSMutableArray *stubs;
|
||||
NSMutableArray *expectations;
|
||||
NSMutableArray *exceptions;
|
||||
NSMutableArray *invocations;
|
||||
}
|
||||
|
||||
+ (id)mockForClass:(Class)aClass;
|
||||
+ (id)mockForProtocol:(Protocol *)aProtocol;
|
||||
+ (id)partialMockForObject:(NSObject *)anObject;
|
||||
|
||||
+ (id)niceMockForClass:(Class)aClass;
|
||||
+ (id)niceMockForProtocol:(Protocol *)aProtocol;
|
||||
|
||||
+ (id)observerMock;
|
||||
|
||||
- (instancetype)init;
|
||||
|
||||
- (void)setExpectationOrderMatters:(BOOL)flag;
|
||||
|
||||
- (id)stub;
|
||||
- (id)expect;
|
||||
- (id)reject;
|
||||
|
||||
- (id)verify;
|
||||
- (id)verifyAtLocation:(OCMLocation *)location;
|
||||
|
||||
- (void)verifyWithDelay:(NSTimeInterval)delay;
|
||||
- (void)verifyWithDelay:(NSTimeInterval)delay atLocation:(OCMLocation *)location;
|
||||
|
||||
- (void)stopMocking;
|
||||
|
||||
// internal use only
|
||||
|
||||
- (void)addStub:(OCMInvocationStub *)aStub;
|
||||
- (void)addExpectation:(OCMInvocationExpectation *)anExpectation;
|
||||
|
||||
- (BOOL)handleInvocation:(NSInvocation *)anInvocation;
|
||||
- (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation;
|
||||
- (BOOL)handleSelector:(SEL)sel;
|
||||
|
||||
- (void)verifyInvocation:(OCMInvocationMatcher *)matcher;
|
||||
- (void)verifyInvocation:(OCMInvocationMatcher *)matcher atLocation:(OCMLocation *)location;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTContextExecutor.h"
|
||||
#import "RCTRootView.h"
|
||||
|
||||
#define RUN_RUNLOOP_WHILE(CONDITION, TIMEOUT) \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
|
||||
NSDate *timeout = [[NSDate date] dateByAddingTimeInterval:TIMEOUT]; \
|
||||
while ((CONDITION) && [timeout timeIntervalSinceNow] > 0) { \
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeout]; \
|
||||
} \
|
||||
_Pragma("clang diagnostic pop")
|
||||
|
||||
#define DEFAULT_TIMEOUT 2
|
||||
|
||||
@interface RCTBridge (RCTAllocationTests)
|
||||
|
||||
@property (nonatomic, weak) RCTBridge *batchedBridge;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTJavaScriptContext : NSObject
|
||||
|
||||
@property (nonatomic, assign, readonly) JSGlobalContextRef ctx;
|
||||
|
||||
@end
|
||||
|
||||
@interface AllocationTestModule : NSObject<RCTBridgeModule, RCTInvalidating>
|
||||
@end
|
||||
|
||||
@implementation AllocationTestModule
|
||||
|
||||
RCT_EXPORT_MODULE();
|
||||
|
||||
@synthesize valid = _valid;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_valid = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
_valid = NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTAllocationTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation RCTAllocationTests
|
||||
|
||||
- (void)testBridgeIsDeallocated
|
||||
{
|
||||
__weak RCTBridge *weakBridge;
|
||||
@autoreleasepool {
|
||||
RCTRootView *view = [[RCTRootView alloc] initWithBundleURL:nil
|
||||
moduleName:@""
|
||||
launchOptions:nil];
|
||||
weakBridge = view.bridge;
|
||||
XCTAssertNotNil(weakBridge, @"RCTBridge should have been created");
|
||||
(void)view;
|
||||
}
|
||||
|
||||
sleep(DEFAULT_TIMEOUT);
|
||||
XCTAssertNil(weakBridge, @"RCTBridge should have been deallocated");
|
||||
}
|
||||
|
||||
- (void)testModulesAreInvalidated
|
||||
{
|
||||
AllocationTestModule *module = [[AllocationTestModule alloc] init];
|
||||
@autoreleasepool {
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil
|
||||
moduleProvider:^{
|
||||
return @[module];
|
||||
}
|
||||
launchOptions:nil];
|
||||
XCTAssertTrue(module.isValid, @"AllocationTestModule should be valid");
|
||||
(void)bridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep on the main thread to allow js thread deallocations then run the runloop
|
||||
* to allow the module to be deallocated on the main thread
|
||||
*/
|
||||
sleep(1);
|
||||
RUN_RUNLOOP_WHILE(module.isValid, 1)
|
||||
XCTAssertFalse(module.isValid, @"AllocationTestModule should have been invalidated by the bridge");
|
||||
}
|
||||
|
||||
- (void)testModulesAreDeallocated
|
||||
{
|
||||
__weak AllocationTestModule *weakModule;
|
||||
@autoreleasepool {
|
||||
AllocationTestModule *module = [[AllocationTestModule alloc] init];
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil
|
||||
moduleProvider:^{
|
||||
return @[module];
|
||||
}
|
||||
launchOptions:nil];
|
||||
weakModule = module;
|
||||
XCTAssertNotNil(weakModule, @"AllocationTestModule should have been created");
|
||||
(void)bridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep on the main thread to allow js thread deallocations then run the runloop
|
||||
* to allow the module to be deallocated on the main thread
|
||||
*/
|
||||
sleep(1);
|
||||
RUN_RUNLOOP_WHILE(weakModule, 1)
|
||||
XCTAssertNil(weakModule, @"AllocationTestModule should have been deallocated");
|
||||
}
|
||||
|
||||
- (void)testJavaScriptExecutorIsDeallocated
|
||||
{
|
||||
__weak id<RCTJavaScriptExecutor> weakExecutor;
|
||||
@autoreleasepool {
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil
|
||||
moduleProvider:nil
|
||||
launchOptions:nil];
|
||||
weakExecutor = [bridge.batchedBridge valueForKey:@"javaScriptExecutor"];
|
||||
XCTAssertNotNil(weakExecutor, @"JavaScriptExecutor should have been created");
|
||||
(void)bridge;
|
||||
}
|
||||
|
||||
RUN_RUNLOOP_WHILE(weakExecutor, 1);
|
||||
sleep(1);
|
||||
XCTAssertNil(weakExecutor, @"JavaScriptExecutor should have been released");
|
||||
}
|
||||
|
||||
- (void)testJavaScriptContextIsDeallocated
|
||||
{
|
||||
__weak id weakContext;
|
||||
@autoreleasepool {
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil
|
||||
moduleProvider:nil
|
||||
launchOptions:nil];
|
||||
id executor = [bridge.batchedBridge valueForKey:@"javaScriptExecutor"];
|
||||
RUN_RUNLOOP_WHILE(!(weakContext = [executor valueForKey:@"context"]), DEFAULT_TIMEOUT);
|
||||
XCTAssertNotNil(weakContext, @"RCTJavaScriptContext should have been created");
|
||||
(void)bridge;
|
||||
}
|
||||
|
||||
RUN_RUNLOOP_WHILE(weakContext, 1);
|
||||
sleep(1);
|
||||
XCTAssertNil(weakContext, @"RCTJavaScriptContext should have been deallocated");
|
||||
}
|
||||
|
||||
- (void)testContentViewIsInvalidated
|
||||
{
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil moduleProvider:nil launchOptions:nil];
|
||||
__weak id rootContentView;
|
||||
@autoreleasepool {
|
||||
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@""];
|
||||
RUN_RUNLOOP_WHILE(!(rootContentView = [rootView valueForKey:@"contentView"]), DEFAULT_TIMEOUT)
|
||||
XCTAssertTrue([rootContentView isValid], @"RCTContentView should be valid");
|
||||
(void)rootView;
|
||||
}
|
||||
|
||||
sleep(DEFAULT_TIMEOUT);
|
||||
XCTAssertFalse([rootContentView isValid], @"RCTContentView should have been invalidated");
|
||||
}
|
||||
|
||||
- (void)testUnderlyingBridgeIsDeallocated
|
||||
{
|
||||
RCTBridge *bridge;
|
||||
__weak id batchedBridge;
|
||||
@autoreleasepool {
|
||||
bridge = [[RCTBridge alloc] initWithBundleURL:nil moduleProvider:nil launchOptions:nil];
|
||||
batchedBridge = bridge.batchedBridge;
|
||||
XCTAssertTrue([batchedBridge isValid], @"RCTBatchedBridge should be valid");
|
||||
[bridge reload];
|
||||
}
|
||||
|
||||
// Use RUN_RUNLOOP_WHILE because `batchedBridge` deallocates on the main thread.
|
||||
RUN_RUNLOOP_WHILE(batchedBridge != nil, DEFAULT_TIMEOUT)
|
||||
|
||||
XCTAssertNotNil(bridge, @"RCTBridge should not have been deallocated");
|
||||
XCTAssertNil(batchedBridge, @"RCTBatchedBridge should have been deallocated");
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,187 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTBridgeModule.h"
|
||||
#import "RCTJavaScriptExecutor.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@interface RCTBridge (Testing)
|
||||
|
||||
@property (nonatomic, strong, readonly) RCTBridge *batchedBridge;
|
||||
|
||||
- (void)_handleBuffer:(id)buffer context:(NSNumber *)context;
|
||||
- (void)setUp;
|
||||
|
||||
@end
|
||||
|
||||
@interface TestExecutor : NSObject <RCTJavaScriptExecutor>
|
||||
|
||||
@property (nonatomic, readonly, copy) NSMutableDictionary *injectedStuff;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TestExecutor
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (void)setUp {}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_injectedStuff = [NSMutableDictionary dictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isValid
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)executeJSCall:(NSString *)name
|
||||
method:(NSString *)method
|
||||
arguments:(NSArray *)arguments
|
||||
context:(NSNumber *)executorID
|
||||
callback:(RCTJavaScriptCallback)onComplete
|
||||
{
|
||||
onComplete(nil, nil);
|
||||
}
|
||||
|
||||
- (void)executeApplicationScript:(NSString *)script
|
||||
sourceURL:(NSURL *)url
|
||||
onComplete:(RCTJavaScriptCompleteBlock)onComplete
|
||||
{
|
||||
onComplete(nil);
|
||||
}
|
||||
|
||||
- (void)executeBlockOnJavaScriptQueue:(dispatch_block_t)block
|
||||
{
|
||||
block();
|
||||
}
|
||||
|
||||
- (void)injectJSONText:(NSString *)script
|
||||
asGlobalObjectNamed:(NSString *)objectName
|
||||
callback:(RCTJavaScriptCompleteBlock)onComplete
|
||||
{
|
||||
_injectedStuff[objectName] = script;
|
||||
onComplete(nil);
|
||||
}
|
||||
|
||||
- (void)invalidate {}
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridgeTests : XCTestCase <RCTBridgeModule>
|
||||
{
|
||||
RCTBridge *_bridge;
|
||||
BOOL _testMethodCalled;
|
||||
dispatch_queue_t _queue;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeTests
|
||||
|
||||
RCT_EXPORT_MODULE(TestModule)
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return _queue;
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
|
||||
_queue = dispatch_queue_create("com.facebook.React.TestQueue", DISPATCH_QUEUE_SERIAL);
|
||||
|
||||
_bridge = [[RCTBridge alloc] initWithBundleURL:nil
|
||||
moduleProvider:^{ return @[self]; }
|
||||
launchOptions:nil];
|
||||
|
||||
_bridge.executorClass = [TestExecutor class];
|
||||
// Force to recreate the executor with the new class
|
||||
// - reload: doesn't work here since bridge hasn't loaded yet.
|
||||
[_bridge invalidate];
|
||||
[_bridge setUp];
|
||||
}
|
||||
|
||||
- (void)tearDown
|
||||
{
|
||||
[super tearDown];
|
||||
[_bridge invalidate];
|
||||
}
|
||||
|
||||
- (void)testHookRegistration
|
||||
{
|
||||
TestExecutor *executor = [_bridge.batchedBridge valueForKey:@"_javaScriptExecutor"];
|
||||
NSString *injectedStuff = executor.injectedStuff[@"__fbBatchedBridgeConfig"];
|
||||
NSDictionary *moduleConfig = RCTJSONParse(injectedStuff, NULL);
|
||||
NSDictionary *remoteModuleConfig = moduleConfig[@"remoteModuleConfig"];
|
||||
NSDictionary *testModuleConfig = remoteModuleConfig[@"TestModule"];
|
||||
NSDictionary *constants = testModuleConfig[@"constants"];
|
||||
NSDictionary *methods = testModuleConfig[@"methods"];
|
||||
|
||||
XCTAssertNotNil(moduleConfig);
|
||||
XCTAssertNotNil(remoteModuleConfig);
|
||||
XCTAssertNotNil(testModuleConfig);
|
||||
XCTAssertNotNil(constants);
|
||||
XCTAssertEqualObjects(constants[@"eleventyMillion"], @42);
|
||||
XCTAssertNotNil(methods);
|
||||
XCTAssertNotNil(methods[@"testMethod"]);
|
||||
}
|
||||
|
||||
- (void)testCallNativeMethod
|
||||
{
|
||||
TestExecutor *executor = [_bridge.batchedBridge valueForKey:@"_javaScriptExecutor"];
|
||||
NSString *injectedStuff = executor.injectedStuff[@"__fbBatchedBridgeConfig"];
|
||||
NSDictionary *moduleConfig = RCTJSONParse(injectedStuff, NULL);
|
||||
NSDictionary *remoteModuleConfig = moduleConfig[@"remoteModuleConfig"];
|
||||
NSDictionary *testModuleConfig = remoteModuleConfig[@"TestModule"];
|
||||
NSNumber *testModuleID = testModuleConfig[@"moduleID"];
|
||||
NSDictionary *methods = testModuleConfig[@"methods"];
|
||||
NSDictionary *testMethod = methods[@"testMethod"];
|
||||
NSNumber *testMethodID = testMethod[@"methodID"];
|
||||
|
||||
NSArray *args = @[@1234, @5678, @"stringy", @{@"a": @1}, @42];
|
||||
NSArray *buffer = @[@[testModuleID], @[testMethodID], @[args], @[], @1234567];
|
||||
|
||||
[_bridge.batchedBridge _handleBuffer:buffer context:RCTGetExecutorID(executor)];
|
||||
|
||||
dispatch_sync(_queue, ^{
|
||||
// clear the queue
|
||||
XCTAssertTrue(_testMethodCalled);
|
||||
});
|
||||
}
|
||||
|
||||
- (void)DISABLED_testBadArgumentsCount
|
||||
{
|
||||
//NSArray *bufferWithMissingArgument = @[@[@1], @[@0], @[@[@1234, @5678, @"stringy", @{@"a": @1}/*, @42*/]], @[], @1234567];
|
||||
//[_bridge _handleBuffer:bufferWithMissingArgument];
|
||||
NSLog(@"WARNING: testBadArgumentsCount is temporarily disabled until we have a better way to test cases that we expect to trigger redbox errors");
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(testMethod:(NSInteger)integer
|
||||
number:(NSNumber *)number
|
||||
string:(NSString *)string
|
||||
dictionary:(NSDictionary *)dict
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
_testMethodCalled = YES;
|
||||
|
||||
XCTAssertTrue(integer == 1234);
|
||||
XCTAssertEqualObjects(number, @5678);
|
||||
XCTAssertEqualObjects(string, @"stringy");
|
||||
XCTAssertEqualObjects(dict, @{@"a": @1});
|
||||
XCTAssertNotNil(callback);
|
||||
}
|
||||
|
||||
- (NSDictionary *)constantsToExport
|
||||
{
|
||||
return @{@"eleventyMillion": @42};
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,193 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <mach/mach_time.h>
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTContextExecutor.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
|
||||
@interface RCTContextExecutorTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTContextExecutorTests
|
||||
{
|
||||
RCTContextExecutor *_executor;
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
_executor = [[RCTContextExecutor alloc] init];
|
||||
RCTSetExecutorID(_executor);
|
||||
[_executor setUp];
|
||||
}
|
||||
|
||||
- (void)testNativeLoggingHookExceptionBehavior
|
||||
{
|
||||
dispatch_semaphore_t doneSem = dispatch_semaphore_create(0);
|
||||
[_executor executeApplicationScript:@"var x = {toString: function() { throw 1; }}; nativeLoggingHook(x);"
|
||||
sourceURL:[NSURL URLWithString:@"file://"]
|
||||
onComplete:^(id error){
|
||||
dispatch_semaphore_signal(doneSem);
|
||||
}];
|
||||
dispatch_semaphore_wait(doneSem, DISPATCH_TIME_FOREVER);
|
||||
[_executor invalidate];
|
||||
}
|
||||
|
||||
static uint64_t _get_time_nanoseconds(void)
|
||||
{
|
||||
static struct mach_timebase_info tb_info = {0};
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
int ret = mach_timebase_info(&tb_info);
|
||||
assert(0 == ret);
|
||||
});
|
||||
|
||||
return (mach_absolute_time() * tb_info.numer) / tb_info.denom;
|
||||
}
|
||||
|
||||
- (void)testDeserializationPerf
|
||||
{
|
||||
// This test case checks the assumption that deserializing objects from JavaScript
|
||||
// values one-by-one via ObjC JSC API is slower than using JSON string
|
||||
// You might want to switch your tests schema to "Release" build configuration
|
||||
|
||||
JSContextGroupRef group = JSContextGroupCreate();
|
||||
JSGlobalContextRef context = JSGlobalContextCreateInGroup(group, NULL);
|
||||
id message = @[@[@1, @2, @3, @4], @[@{@"a": @1}, @{@"b": @2}], [NSNull null]];
|
||||
NSString *code = RCTJSONStringify(message, NULL);
|
||||
JSStringRef script = JSStringCreateWithCFString((__bridge CFStringRef)code);
|
||||
JSValueRef error = NULL;
|
||||
JSValueRef value = JSEvaluateScript(context, script, NULL, NULL, 0, &error);
|
||||
XCTAssertTrue(error == NULL);
|
||||
|
||||
id obj;
|
||||
uint64_t start = _get_time_nanoseconds();
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
JSStringRef jsonJSString = JSValueCreateJSONString(context, value, 0, nil);
|
||||
NSString *jsonString = (__bridge NSString *)JSStringCopyCFString(kCFAllocatorDefault, jsonJSString);
|
||||
JSStringRelease(jsonJSString);
|
||||
|
||||
obj = RCTJSONParse(jsonString, NULL);
|
||||
}
|
||||
NSLog(@"JSON Parse time: %.2fms", (_get_time_nanoseconds() - start) / 1000000.0);
|
||||
|
||||
JSStringRelease(script);
|
||||
JSGlobalContextRelease(context);
|
||||
JSContextGroupRelease(group);
|
||||
}
|
||||
|
||||
- (void)MANUALLY_testJavaScriptCallSpeed
|
||||
{
|
||||
/**
|
||||
* Since we almost don't change the RCTContextExecutor logic, and this test is
|
||||
* very likely to become flaky (specially accross different devices) leave it
|
||||
* to be run manually
|
||||
*
|
||||
* Previous Values: If you change the executor code, you should update this values
|
||||
*/
|
||||
|
||||
int const runs = 4e5;
|
||||
int const frequency = 10;
|
||||
double const threshold = 0.1;
|
||||
static double const expectedTimes[] = {
|
||||
0x1.6199943826cf1p+13,
|
||||
0x1.a3bc0a81551c3p+13,
|
||||
0x1.d49fbb8602fe3p+13,
|
||||
0x1.d1f64085ecb7bp+13,
|
||||
};
|
||||
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
NSString *script = @" \
|
||||
var modules = { \
|
||||
module: { \
|
||||
method: function () { \
|
||||
return true; \
|
||||
} \
|
||||
} \
|
||||
}; \
|
||||
function require(module) { \
|
||||
return modules[module]; \
|
||||
} \
|
||||
";
|
||||
|
||||
[_executor executeApplicationScript:script sourceURL:[NSURL URLWithString:@"http://localhost:8081/"] onComplete:^(NSError *error) {
|
||||
NSMutableArray *params = [[NSMutableArray alloc] init];
|
||||
id data = @1;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
double samples[runs / frequency];
|
||||
int size = runs / frequency;
|
||||
double total = 0;
|
||||
for (int j = 0; j < runs; j++) {
|
||||
@autoreleasepool {
|
||||
double start = _get_time_nanoseconds();
|
||||
[_executor executeJSCall:@"module"
|
||||
method:@"method"
|
||||
arguments:params
|
||||
context:RCTGetExecutorID(_executor)
|
||||
callback:^(id json, NSError *__error) {
|
||||
RCTAssert([json isEqual:@YES], @"Invalid return");
|
||||
}];
|
||||
double run = _get_time_nanoseconds() - start;
|
||||
if ((j % frequency) == frequency - 1) { // Warmup
|
||||
total += run;
|
||||
samples[j/frequency] = run;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double mean = total / size;
|
||||
double variance = 0;
|
||||
|
||||
for (int j = 0; j < size; j++) {
|
||||
variance += pow(samples[j] - mean, 2);
|
||||
}
|
||||
variance /= size;
|
||||
|
||||
double standardDeviation = sqrt(variance);
|
||||
double marginOfError = standardDeviation * 1.645;
|
||||
|
||||
double lower = mean - marginOfError;
|
||||
double upper = mean + marginOfError;
|
||||
|
||||
int s = 0;
|
||||
total = 0;
|
||||
for (int j = 0; j < size; j++) {
|
||||
double v = samples[j];
|
||||
if (v >= lower && v <= upper) {
|
||||
samples[s++] = v;
|
||||
total += v;
|
||||
}
|
||||
}
|
||||
mean = total / s;
|
||||
|
||||
lower = mean * (1.0 - threshold);
|
||||
upper = mean * (1.0 + threshold);
|
||||
|
||||
double expected = expectedTimes[i];
|
||||
|
||||
NSLog(@"Previous: %lf, New: %f -> %a", expected, mean, mean);
|
||||
if (upper < expected) {
|
||||
NSLog(@"You made JS calls with %d argument(s) %.2lf%% faster :) - Remember to update the tests with the new value: %a",
|
||||
i, (1 - (double)mean / expected) * 100, mean);
|
||||
}
|
||||
|
||||
|
||||
XCTAssertTrue(lower < expected, @"You made JS calls with %d argument(s) %.2lf%% slower :( - If that's *really* necessary, update the tests with the new value: %a",
|
||||
i, ((double)mean / expected - 1) * 100, mean);
|
||||
|
||||
[params addObject:data];
|
||||
}
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
}];
|
||||
|
||||
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) {
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
|
||||
beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTConvert.h"
|
||||
|
||||
@interface RCTConvert_NSURLTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTConvert_NSURLTests
|
||||
|
||||
#define TEST_URL(name, _input, _expectedURL) \
|
||||
- (void)test_##name { \
|
||||
NSURL *result = [RCTConvert NSURL:_input]; \
|
||||
NSURL *expected = [NSURL URLWithString:_expectedURL]; \
|
||||
XCTAssertEqualObjects(result.absoluteURL, expected); \
|
||||
} \
|
||||
|
||||
#define TEST_PATH(name, _input, _expectedPath) \
|
||||
- (void)test_##name { \
|
||||
NSURL *result = [RCTConvert NSURL:_input]; \
|
||||
XCTAssertEqualObjects(result.path, _expectedPath); \
|
||||
} \
|
||||
|
||||
#define TEST_BUNDLE_PATH(name, _input, _expectedPath) \
|
||||
TEST_PATH(name, _input, [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:_expectedPath])
|
||||
|
||||
// Basic tests
|
||||
TEST_URL(basic, @"http://example.com", @"http://example.com")
|
||||
TEST_URL(null, [NSNull null], nil)
|
||||
|
||||
// Local files
|
||||
TEST_PATH(fileURL, @"file:///blah/hello.jsbundle", @"/blah/hello.jsbundle")
|
||||
TEST_BUNDLE_PATH(filePath, @"blah/hello.jsbundle", @"blah/hello.jsbundle")
|
||||
TEST_BUNDLE_PATH(filePathWithSpaces, @"blah blah/hello.jsbundle", @"blah blah/hello.jsbundle")
|
||||
TEST_BUNDLE_PATH(filePathWithEncodedSpaces, @"blah%20blah/hello.jsbundle", @"blah blah/hello.jsbundle")
|
||||
TEST_BUNDLE_PATH(imageAt2XPath, @"images/foo@2x.jpg", @"images/foo@2x.jpg")
|
||||
TEST_BUNDLE_PATH(imageFile, @"foo.jpg", @"foo.jpg")
|
||||
|
||||
// Remote files
|
||||
TEST_URL(fullURL, @"http://example.com/blah/hello.jsbundle", @"http://example.com/blah/hello.jsbundle")
|
||||
TEST_URL(urlWithSpaces, @"http://example.com/blah blah/foo", @"http://example.com/blah%20blah/foo")
|
||||
TEST_URL(urlWithEncodedSpaces, @"http://example.com/blah%20blah/foo", @"http://example.com/blah%20blah/foo")
|
||||
TEST_URL(imageURL, @"http://example.com/foo@2x.jpg", @"http://example.com/foo@2x.jpg")
|
||||
TEST_URL(imageURLWithSpaces, @"http://example.com/blah foo@2x.jpg", @"http://example.com/blah%20foo@2x.jpg")
|
||||
|
||||
@end
|
|
@ -0,0 +1,159 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTConvert.h"
|
||||
|
||||
@interface RCTConvert_UIFontTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTConvert_UIFontTests
|
||||
|
||||
#define RCTAssertEqualFonts(font1, font2) { \
|
||||
XCTAssertEqualObjects(font1, font2); \
|
||||
}
|
||||
|
||||
- (void)DISABLED_testWeight // task #7118691
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Bold" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontWeight": @"bold"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Medium" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontWeight": @"500"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-UltraLight" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontWeight": @"100"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontWeight": @"normal"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testSize
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:18.5];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontSize": @18.5}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testFamily
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"Cochin" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Cochin"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Helvetica Neue"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Italic" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"HelveticaNeue-Italic"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testStyle
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Italic" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontStyle": @"italic"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontStyle": @"normal"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)DISABLED_testStyleAndWeight // task #7118691
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-UltraLightItalic" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontStyle": @"italic", @"fontWeight": @"100"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-BoldItalic" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontStyle": @"italic", @"fontWeight": @"bold"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)DISABLED_testFamilyAndWeight // task #7118691
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Bold" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Helvetica Neue", @"fontWeight": @"bold"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"HelveticaNeue-Bold", @"fontWeight": @"normal"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"Cochin-Bold" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Cochin", @"fontWeight": @"700"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"Cochin" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Cochin", @"fontWeight": @"500"}]; // regular Cochin is actually medium bold
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"Cochin" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Cochin", @"fontWeight": @"100"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testFamilyAndStyle
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Italic" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Helvetica Neue", @"fontStyle": @"italic"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"HelveticaNeue-Italic", @"fontStyle": @"normal"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)DISABLED_testFamilyStyleAndWeight // task #7118691
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-UltraLightItalic" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Helvetica Neue", @"fontStyle": @"italic", @"fontWeight": @"100"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Bold" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"HelveticaNeue-Italic", @"fontStyle": @"normal", @"fontWeight": @"bold"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"HelveticaNeue-Italic", @"fontStyle": @"normal", @"fontWeight": @"normal"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,144 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import <OCMock/OCMock.h>
|
||||
#import "RCTEventDispatcher.h"
|
||||
|
||||
@interface RCTTestEvent : RCTBaseEvent
|
||||
|
||||
@property (nonatomic, assign) BOOL canCoalesce;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTTestEvent
|
||||
|
||||
- (instancetype)initWithViewTag:(NSNumber *)viewTag eventName:(NSString *)eventName body:(NSDictionary *)body
|
||||
{
|
||||
if (self = [super initWithViewTag:viewTag eventName:eventName body:body]) {
|
||||
self.canCoalesce = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (NSString *)moduleDotMethod
|
||||
{
|
||||
return @"RCTDeviceEventEmitter.emit";
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTEventDispatcherTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation RCTEventDispatcherTests
|
||||
{
|
||||
id _bridge;
|
||||
RCTEventDispatcher *_eventDispatcher;
|
||||
|
||||
NSString *_eventName;
|
||||
NSDictionary *_body;
|
||||
RCTTestEvent *_testEvent;
|
||||
NSString *_JSMethod;
|
||||
}
|
||||
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
|
||||
_bridge = [OCMockObject mockForClass:[RCTBridge class]];
|
||||
_eventDispatcher = [[RCTEventDispatcher alloc] init];
|
||||
((id<RCTBridgeModule>)_eventDispatcher).bridge = _bridge;
|
||||
|
||||
_eventName = @"sampleEvent";
|
||||
_body = @{ @"foo": @"bar" };
|
||||
_testEvent = [[RCTTestEvent alloc] initWithViewTag:nil
|
||||
eventName:_eventName
|
||||
body:_body];
|
||||
|
||||
_JSMethod = [[_testEvent class] moduleDotMethod];
|
||||
}
|
||||
|
||||
- (void)testLegacyEventsAreImmediatelyDispatched
|
||||
{
|
||||
[[_bridge expect] enqueueJSCall:_JSMethod
|
||||
args:@[_eventName, _body]];
|
||||
|
||||
[_eventDispatcher sendDeviceEventWithName:_eventName body:_body];
|
||||
|
||||
[_bridge verify];
|
||||
}
|
||||
|
||||
- (void)testNonCoalescingEventsAreImmediatelyDispatched
|
||||
{
|
||||
_testEvent.canCoalesce = NO;
|
||||
[[_bridge expect] enqueueJSCall:_JSMethod
|
||||
args:@[_eventName, _body]];
|
||||
|
||||
[_eventDispatcher sendEvent:_testEvent];
|
||||
|
||||
[_bridge verify];
|
||||
}
|
||||
|
||||
- (void)testCoalescedEventShouldBeDispatchedOnFrameUpdate
|
||||
{
|
||||
[_eventDispatcher sendEvent:_testEvent];
|
||||
|
||||
[[_bridge expect] enqueueJSCall:@"RCTDeviceEventEmitter.emit"
|
||||
args:@[_eventName, _body]];
|
||||
|
||||
[(id<RCTFrameUpdateObserver>)_eventDispatcher didUpdateFrame:nil];
|
||||
|
||||
[_bridge verify];
|
||||
}
|
||||
|
||||
- (void)testBasicCoalescingReturnsLastEvent
|
||||
{
|
||||
RCTTestEvent *ignoredEvent = [[RCTTestEvent alloc] initWithViewTag:nil
|
||||
eventName:_eventName
|
||||
body:@{ @"other": @"body" }];
|
||||
|
||||
[_eventDispatcher sendEvent:ignoredEvent];
|
||||
[_eventDispatcher sendEvent:_testEvent];
|
||||
|
||||
[[_bridge expect] enqueueJSCall:@"RCTDeviceEventEmitter.emit"
|
||||
args:@[_eventName, _body]];
|
||||
|
||||
[(id<RCTFrameUpdateObserver>)_eventDispatcher didUpdateFrame:nil];
|
||||
|
||||
[_bridge verify];
|
||||
}
|
||||
|
||||
- (void)testDifferentEventTypesDontCoalesce
|
||||
{
|
||||
NSString *firstEventName = @"firstEvent";
|
||||
RCTTestEvent *firstEvent = [[RCTTestEvent alloc] initWithViewTag:nil
|
||||
eventName:firstEventName
|
||||
body:_body];
|
||||
|
||||
[_eventDispatcher sendEvent:firstEvent];
|
||||
[_eventDispatcher sendEvent:_testEvent];
|
||||
|
||||
[[_bridge expect] enqueueJSCall:@"RCTDeviceEventEmitter.emit"
|
||||
args:@[firstEventName, _body]];
|
||||
|
||||
[[_bridge expect] enqueueJSCall:@"RCTDeviceEventEmitter.emit"
|
||||
args:@[_eventName, _body]];
|
||||
|
||||
[(id<RCTFrameUpdateObserver>)_eventDispatcher didUpdateFrame:nil];
|
||||
|
||||
[_bridge verify];
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTSparseArray.h"
|
||||
#import "UIView+React.h"
|
||||
|
||||
@interface RCTSparseArrayTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTSparseArrayTests
|
||||
|
||||
- (void)testDictionary
|
||||
{
|
||||
NSObject<RCTViewNodeProtocol> *myView = [[UIView alloc] init];
|
||||
myView.reactTag = @4;
|
||||
|
||||
NSObject<RCTViewNodeProtocol> *myOtherView = [[UIView alloc] init];
|
||||
myOtherView.reactTag = @5;
|
||||
|
||||
RCTSparseArray *registry = [[RCTSparseArray alloc] init];
|
||||
XCTAssertNil(registry[@4], @"how did you have a view when none are registered?");
|
||||
XCTAssertNil(registry[@5], @"how did you have a view when none are registered?");
|
||||
|
||||
registry[myView.reactTag] = myView;
|
||||
XCTAssertEqual(registry[@4], myView);
|
||||
XCTAssertNil(registry[@5], @"didn't register other view yet");
|
||||
|
||||
registry[myOtherView.reactTag] = myOtherView;
|
||||
XCTAssertEqual(registry[@4], myView);
|
||||
XCTAssertEqual(registry[@5], myOtherView);
|
||||
|
||||
registry[myView.reactTag] = nil;
|
||||
XCTAssertNil(registry[@4]);
|
||||
XCTAssertEqual(registry[@5], myOtherView);
|
||||
|
||||
registry[myOtherView.reactTag] = nil;
|
||||
XCTAssertNil(registry[@4], @"how did you have a view when none are registered?");
|
||||
XCTAssertNil(registry[@5], @"how did you have a view when none are registered?");
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,179 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTSparseArray.h"
|
||||
#import "RCTUIManager.h"
|
||||
#import "UIView+React.h"
|
||||
|
||||
@interface RCTUIManager (Testing)
|
||||
|
||||
- (void)_manageChildren:(NSNumber *)containerReactTag
|
||||
moveFromIndices:(NSArray *)moveFromIndices
|
||||
moveToIndices:(NSArray *)moveToIndices
|
||||
addChildReactTags:(NSArray *)addChildReactTags
|
||||
addAtIndices:(NSArray *)addAtIndices
|
||||
removeAtIndices:(NSArray *)removeAtIndices
|
||||
registry:(RCTSparseArray *)registry;
|
||||
|
||||
@property (nonatomic, readonly) RCTSparseArray *viewRegistry;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTUIManagerTests : XCTestCase
|
||||
|
||||
@property (nonatomic, readwrite, strong) RCTUIManager *uiManager;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTUIManagerTests
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
|
||||
_uiManager = [[RCTUIManager alloc] init];
|
||||
|
||||
// Register 20 views to use in the tests
|
||||
for (NSInteger i = 1; i <= 20; i++) {
|
||||
UIView *registeredView = [[UIView alloc] init];
|
||||
[registeredView setReactTag:@(i)];
|
||||
_uiManager.viewRegistry[i] = registeredView;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testManagingChildrenToAddViews
|
||||
{
|
||||
UIView *containerView = _uiManager.viewRegistry[20];
|
||||
NSMutableArray *addedViews = [NSMutableArray array];
|
||||
|
||||
NSArray *tagsToAdd = @[@1, @2, @3, @4, @5];
|
||||
NSArray *addAtIndices = @[@0, @1, @2, @3, @4];
|
||||
for (NSNumber *tag in tagsToAdd) {
|
||||
[addedViews addObject:_uiManager.viewRegistry[tag]];
|
||||
}
|
||||
|
||||
// Add views 1-5 to view 20
|
||||
[_uiManager _manageChildren:@20
|
||||
moveFromIndices:nil
|
||||
moveToIndices:nil
|
||||
addChildReactTags:tagsToAdd
|
||||
addAtIndices:addAtIndices
|
||||
removeAtIndices:nil
|
||||
registry:_uiManager.viewRegistry];
|
||||
|
||||
XCTAssertTrue([[containerView reactSubviews] count] == 5,
|
||||
@"Expect to have 5 react subviews after calling manage children \
|
||||
with 5 tags to add, instead have %lu", (unsigned long)[[containerView reactSubviews] count]);
|
||||
for (UIView *view in addedViews) {
|
||||
XCTAssertTrue([view superview] == containerView,
|
||||
@"Expected to have manage children successfully add children");
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testManagingChildrenToRemoveViews
|
||||
{
|
||||
UIView *containerView = _uiManager.viewRegistry[20];
|
||||
NSMutableArray *removedViews = [NSMutableArray array];
|
||||
|
||||
NSArray *removeAtIndices = @[@0, @4, @8, @12, @16];
|
||||
for (NSNumber *index in removeAtIndices) {
|
||||
NSNumber *reactTag = @([index integerValue] + 2);
|
||||
[removedViews addObject:_uiManager.viewRegistry[reactTag]];
|
||||
}
|
||||
for (NSInteger i = 2; i < 20; i++) {
|
||||
UIView *view = _uiManager.viewRegistry[i];
|
||||
[containerView addSubview:view];
|
||||
}
|
||||
|
||||
// Remove views 1-5 from view 20
|
||||
[_uiManager _manageChildren:@20
|
||||
moveFromIndices:nil
|
||||
moveToIndices:nil
|
||||
addChildReactTags:nil
|
||||
addAtIndices:nil
|
||||
removeAtIndices:removeAtIndices
|
||||
registry:_uiManager.viewRegistry];
|
||||
|
||||
XCTAssertEqual(containerView.reactSubviews.count, (NSUInteger)13,
|
||||
@"Expect to have 13 react subviews after calling manage children\
|
||||
with 5 tags to remove and 18 prior children, instead have %zd",
|
||||
containerView.reactSubviews.count);
|
||||
for (UIView *view in removedViews) {
|
||||
XCTAssertTrue([view superview] == nil,
|
||||
@"Expected to have manage children successfully remove children");
|
||||
// After removing views are unregistered - we need to reregister
|
||||
_uiManager.viewRegistry[view.reactTag] = view;
|
||||
}
|
||||
for (NSInteger i = 2; i < 20; i++) {
|
||||
UIView *view = _uiManager.viewRegistry[i];
|
||||
if (![removedViews containsObject:view]) {
|
||||
XCTAssertTrue([view superview] == containerView,
|
||||
@"Should not have removed view with react tag %ld during delete but did", (long)i);
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We want to start with views 1-10 added at indices 0-9
|
||||
// Then we'll remove indices 2, 3, 5 and 8
|
||||
// Add views 11 and 12 to indices 0 and 6
|
||||
// And move indices 4 and 9 to 1 and 7
|
||||
// So in total it goes from:
|
||||
// [1,2,3,4,5,6,7,8,9,10]
|
||||
// to
|
||||
// [11,5,1,2,7,8,12,10]
|
||||
- (void)testManagingChildrenToAddRemoveAndMove
|
||||
{
|
||||
UIView *containerView = _uiManager.viewRegistry[20];
|
||||
|
||||
NSArray *removeAtIndices = @[@2, @3, @5, @8];
|
||||
NSArray *addAtIndices = @[@0, @6];
|
||||
NSArray *tagsToAdd = @[@11, @12];
|
||||
NSArray *moveFromIndices = @[@4, @9];
|
||||
NSArray *moveToIndices = @[@1, @7];
|
||||
|
||||
// We need to keep these in array to keep them around
|
||||
NSMutableArray *viewsToRemove = [NSMutableArray array];
|
||||
for (NSInteger i = 0; i < removeAtIndices.count; i++) {
|
||||
NSNumber *reactTagToRemove = @([removeAtIndices[i] integerValue] + 1);
|
||||
UIView *viewToRemove = _uiManager.viewRegistry[reactTagToRemove];
|
||||
[viewsToRemove addObject:viewToRemove];
|
||||
}
|
||||
|
||||
for (NSInteger i = 1; i < 11; i++) {
|
||||
UIView *view = _uiManager.viewRegistry[i];
|
||||
[containerView addSubview:view];
|
||||
}
|
||||
|
||||
[_uiManager _manageChildren:@20
|
||||
moveFromIndices:moveFromIndices
|
||||
moveToIndices:moveToIndices
|
||||
addChildReactTags:tagsToAdd
|
||||
addAtIndices:addAtIndices
|
||||
removeAtIndices:removeAtIndices
|
||||
registry:_uiManager.viewRegistry];
|
||||
|
||||
XCTAssertTrue([[containerView reactSubviews] count] == 8,
|
||||
@"Expect to have 8 react subviews after calling manage children,\
|
||||
instead have the following subviews %@", [containerView reactSubviews]);
|
||||
|
||||
NSArray *expectedReactTags = @[@11, @5, @1, @2, @7, @8, @12, @10];
|
||||
for (NSInteger i = 0; i < [[containerView subviews] count]; i++) {
|
||||
XCTAssertEqualObjects([[containerView reactSubviews][i] reactTag], expectedReactTags[i],
|
||||
@"Expected subview at index %ld to have react tag #%@ but has tag #%@",
|
||||
(long)i, expectedReactTags[i], [[containerView reactSubviews][i] reactTag]);
|
||||
}
|
||||
|
||||
// Clean up after ourselves
|
||||
for (NSInteger i = 1; i < 13; i++) {
|
||||
UIView *view = _uiManager.viewRegistry[i];
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
for (UIView *view in viewsToRemove) {
|
||||
_uiManager.viewRegistry[view.reactTag] = view;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,131 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
ProgressViewIOS,
|
||||
StyleSheet,
|
||||
View,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
} = React;
|
||||
|
||||
class Downloader extends React.Component {
|
||||
|
||||
xhr: XMLHttpRequest;
|
||||
cancelled: boolean;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.cancelled = false;
|
||||
this.state = {
|
||||
downloading: false,
|
||||
contentSize: 1,
|
||||
downloaded: 0,
|
||||
};
|
||||
}
|
||||
|
||||
download() {
|
||||
this.xhr && this.xhr.abort();
|
||||
|
||||
var xhr = this.xhr || new XMLHttpRequest();
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === xhr.HEADERS_RECEIVED) {
|
||||
var contentSize = parseInt(xhr.getResponseHeader('Content-Length'), 10);
|
||||
this.setState({
|
||||
contentSize: contentSize,
|
||||
downloaded: 0,
|
||||
});
|
||||
} else if (xhr.readyState === xhr.LOADING) {
|
||||
this.setState({
|
||||
downloaded: xhr.responseText.length,
|
||||
});
|
||||
} else if (xhr.readyState === xhr.DONE) {
|
||||
this.setState({
|
||||
downloading: false,
|
||||
});
|
||||
if (this.cancelled) {
|
||||
this.cancelled = false;
|
||||
return;
|
||||
}
|
||||
if (xhr.status === 200) {
|
||||
alert('Download complete!');
|
||||
} else if (xhr.status !== 0) {
|
||||
alert('Error: Server returned HTTP status of ' + xhr.status + ' ' + xhr.responseText);
|
||||
} else {
|
||||
alert('Error: ' + xhr.responseText);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.open('GET', 'http://www.gutenberg.org/cache/epub/100/pg100.txt');
|
||||
xhr.send();
|
||||
this.xhr = xhr;
|
||||
|
||||
this.setState({downloading: true});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.cancelled = true;
|
||||
this.xhr && this.xhr.abort();
|
||||
}
|
||||
|
||||
render() {
|
||||
var button = this.state.downloading ? (
|
||||
<View style={styles.wrapper}>
|
||||
<View style={styles.button}>
|
||||
<Text>Downloading...</Text>
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<TouchableHighlight
|
||||
style={styles.wrapper}
|
||||
onPress={this.download.bind(this)}>
|
||||
<View style={styles.button}>
|
||||
<Text>Download 5MB Text File</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
|
||||
return (
|
||||
<View>
|
||||
{button}
|
||||
<ProgressViewIOS progress={(this.state.downloaded / this.state.contentSize)}/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
exports.framework = 'React';
|
||||
exports.title = 'XMLHttpRequest';
|
||||
exports.description = 'XMLHttpRequest';
|
||||
exports.examples = [{
|
||||
title: 'File Download',
|
||||
render() {
|
||||
return <Downloader/>;
|
||||
}
|
||||
}];
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
wrapper: {
|
||||
borderRadius: 5,
|
||||
marginBottom: 5,
|
||||
},
|
||||
button: {
|
||||
backgroundColor: '#eeeeee',
|
||||
padding: 10,
|
||||
},
|
||||
});
|
|
@ -1,51 +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.
|
||||
*/
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "RCTRootView.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
NSURL *jsCodeLocation;
|
||||
|
||||
// Loading JavaScript code - uncomment the one you want.
|
||||
|
||||
// OPTION 1
|
||||
// Load from development server. Start the server from the repository root:
|
||||
//
|
||||
// $ npm start
|
||||
//
|
||||
// To run on device, change `localhost` to the IP address of your computer, and make sure your computer and
|
||||
// iOS device are on the same Wi-Fi network.
|
||||
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/IntegrationTests/IntegrationTestsApp.includeRequire.runModule.bundle?dev=true"];
|
||||
|
||||
// OPTION 2
|
||||
// Load from pre-bundled file on disk. To re-generate the static bundle, run
|
||||
//
|
||||
// $ curl http://localhost:8081/IntegrationTests/IntegrationTestsApp.includeRequire.runModule.bundle -o main.jsbundle
|
||||
//
|
||||
// and uncomment the next following line
|
||||
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||
|
||||
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
|
||||
moduleName:@"IntegrationTestsApp"
|
||||
launchOptions:launchOptions];
|
||||
|
||||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
UIViewController *rootViewController = [[UIViewController alloc] init];
|
||||
rootViewController.view = rootView;
|
||||
self.window.rootViewController = rootViewController;
|
||||
[self.window makeKeyAndVisible];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,42 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="13F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 Facebook. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
|
||||
<rect key="frame" x="20" y="439" width="441" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="IntegrationTests" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
|
||||
<rect key="frame" x="20" y="140" width="441" height="43"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
|
||||
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
|
||||
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
|
||||
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
|
||||
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="548" y="455"/>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
|
@ -1,44 +0,0 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-1.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-2.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-3.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-5.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-4.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 31 KiB |
|
@ -1,42 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.facebook.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>You need to add NSLocationWhenInUseUsageDescription key in Info.plist to enable geolocation, otherwise it is going to *fail silently*!</string>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,664 +0,0 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
004D28A31AAF61C70097A701 /* IntegrationTestsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 004D28A21AAF61C70097A701 /* IntegrationTestsTests.m */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
1405E9C21AC3E65600F5BC37 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1405E9C11AC3E63C00F5BC37 /* libReact.a */; };
|
||||
580C37611AB0F61E0015E709 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 580C374B1AB0F54A0015E709 /* libRCTAdSupport.a */; };
|
||||
580C37621AB0F6260015E709 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 580C37501AB0F55C0015E709 /* libRCTGeolocation.a */; };
|
||||
580C37631AB0F62C0015E709 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 580C37551AB0F56E0015E709 /* libRCTImage.a */; };
|
||||
580C37641AB0F6350015E709 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 580C375A1AB0F5970015E709 /* libRCTNetwork.a */; };
|
||||
580C37651AB0F63E0015E709 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 580C375F1AB0F5D10015E709 /* libRCTText.a */; };
|
||||
58B80D5F1ABA4147004008FB /* libRCTTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 580C378F1AB104B00015E709 /* libRCTTest.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
1405E9C01AC3E63C00F5BC37 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 1405E9BC1AC3E63C00F5BC37 /* React.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
|
||||
remoteInfo = React;
|
||||
};
|
||||
58005BCB1ABA44F10062E044 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
||||
remoteInfo = IntegrationTests;
|
||||
};
|
||||
580C374A1AB0F54A0015E709 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
|
||||
remoteInfo = RCTAdSupport;
|
||||
};
|
||||
580C374F1AB0F55C0015E709 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RCTGeolocation;
|
||||
};
|
||||
580C37541AB0F56E0015E709 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 13417FE31AA91428003F314A /* RCTImage.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B5115D1A9E6B3D00147676;
|
||||
remoteInfo = RCTImage;
|
||||
};
|
||||
580C37591AB0F5970015E709 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 134180261AA91779003F314A /* RCTNetwork.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B511DB1A9E6C8500147676;
|
||||
remoteInfo = RCTNetwork;
|
||||
};
|
||||
580C375E1AB0F5D10015E709 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B5119B1A9E6C1200147676;
|
||||
remoteInfo = RCTText;
|
||||
};
|
||||
580C378E1AB104B00015E709 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 580C37891AB104AF0015E709 /* RCTTest.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 580C376F1AB104AF0015E709;
|
||||
remoteInfo = RCTTest;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
004D289E1AAF61C70097A701 /* IntegrationTestsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IntegrationTestsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
004D28A11AAF61C70097A701 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
004D28A21AAF61C70097A701 /* IntegrationTestsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IntegrationTestsTests.m; sourceTree = "<group>"; };
|
||||
13417FE31AA91428003F314A /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../Libraries/Image/RCTImage.xcodeproj; sourceTree = "<group>"; };
|
||||
13417FEA1AA914B8003F314A /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../Libraries/Text/RCTText.xcodeproj; sourceTree = "<group>"; };
|
||||
134180261AA91779003F314A /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = "<group>"; };
|
||||
134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = ../Libraries/AdSupport/RCTAdSupport.xcodeproj; sourceTree = "<group>"; };
|
||||
134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../Libraries/GeoLocation/RCTGeolocation.xcodeproj; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* IntegrationTests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IntegrationTests.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
1405E9BC1AC3E63C00F5BC37 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = ../React/React.xcodeproj; sourceTree = "<group>"; };
|
||||
580C37891AB104AF0015E709 /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = ../Libraries/RCTTest/RCTTest.xcodeproj; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
004D289B1AAF61C70097A701 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1405E9C21AC3E65600F5BC37 /* libReact.a in Frameworks */,
|
||||
580C37611AB0F61E0015E709 /* libRCTAdSupport.a in Frameworks */,
|
||||
580C37621AB0F6260015E709 /* libRCTGeolocation.a in Frameworks */,
|
||||
580C37631AB0F62C0015E709 /* libRCTImage.a in Frameworks */,
|
||||
580C37641AB0F6350015E709 /* libRCTNetwork.a in Frameworks */,
|
||||
58B80D5F1ABA4147004008FB /* libRCTTest.a in Frameworks */,
|
||||
580C37651AB0F63E0015E709 /* libRCTText.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
004D289F1AAF61C70097A701 /* IntegrationTestsTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
004D28A21AAF61C70097A701 /* IntegrationTestsTests.m */,
|
||||
004D28A01AAF61C70097A701 /* Supporting Files */,
|
||||
);
|
||||
path = IntegrationTestsTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
004D28A01AAF61C70097A701 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
004D28A11AAF61C70097A701 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1316A21D1AA397F400C0188E /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1405E9BC1AC3E63C00F5BC37 /* React.xcodeproj */,
|
||||
134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */,
|
||||
134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */,
|
||||
13417FE31AA91428003F314A /* RCTImage.xcodeproj */,
|
||||
134180261AA91779003F314A /* RCTNetwork.xcodeproj */,
|
||||
13417FEA1AA914B8003F314A /* RCTText.xcodeproj */,
|
||||
580C37891AB104AF0015E709 /* RCTTest.xcodeproj */,
|
||||
);
|
||||
name = Libraries;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13B07FAE1A68108700A75B9A /* IntegrationTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */,
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
|
||||
13B07FB71A68108700A75B9A /* main.m */,
|
||||
);
|
||||
name = IntegrationTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1405E9BD1AC3E63C00F5BC37 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1405E9C11AC3E63C00F5BC37 /* libReact.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
580C37471AB0F54A0015E709 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
580C374B1AB0F54A0015E709 /* libRCTAdSupport.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
580C374C1AB0F55C0015E709 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
580C37501AB0F55C0015E709 /* libRCTGeolocation.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
580C37511AB0F56E0015E709 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
580C37551AB0F56E0015E709 /* libRCTImage.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
580C37561AB0F5970015E709 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
580C375A1AB0F5970015E709 /* libRCTNetwork.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
580C375B1AB0F5D10015E709 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
580C375F1AB0F5D10015E709 /* libRCTText.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
580C378A1AB104AF0015E709 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
580C378F1AB104B00015E709 /* libRCTTest.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83CBB9F61A601CBA00E9B192 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAE1A68108700A75B9A /* IntegrationTests */,
|
||||
1316A21D1AA397F400C0188E /* Libraries */,
|
||||
004D289F1AAF61C70097A701 /* IntegrationTestsTests */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 2;
|
||||
};
|
||||
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* IntegrationTests.app */,
|
||||
004D289E1AAF61C70097A701 /* IntegrationTestsTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
004D289D1AAF61C70097A701 /* IntegrationTestsTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 004D28AD1AAF61C70097A701 /* Build configuration list for PBXNativeTarget "IntegrationTestsTests" */;
|
||||
buildPhases = (
|
||||
004D289A1AAF61C70097A701 /* Sources */,
|
||||
004D289B1AAF61C70097A701 /* Frameworks */,
|
||||
004D289C1AAF61C70097A701 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
58005BCC1ABA44F10062E044 /* PBXTargetDependency */,
|
||||
);
|
||||
name = IntegrationTestsTests;
|
||||
productName = IntegrationTestsTests;
|
||||
productReference = 004D289E1AAF61C70097A701 /* IntegrationTestsTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
13B07F861A680F5B00A75B9A /* IntegrationTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "IntegrationTests" */;
|
||||
buildPhases = (
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = IntegrationTests;
|
||||
productName = "Hello World";
|
||||
productReference = 13B07F961A680F5B00A75B9A /* IntegrationTests.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
83CBB9F71A601CBA00E9B192 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
TargetAttributes = {
|
||||
004D289D1AAF61C70097A701 = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
TestTargetID = 13B07F861A680F5B00A75B9A;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "IntegrationTests" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 83CBB9F61A601CBA00E9B192;
|
||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectReferences = (
|
||||
{
|
||||
ProductGroup = 580C37471AB0F54A0015E709 /* Products */;
|
||||
ProjectRef = 134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 580C374C1AB0F55C0015E709 /* Products */;
|
||||
ProjectRef = 134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 580C37511AB0F56E0015E709 /* Products */;
|
||||
ProjectRef = 13417FE31AA91428003F314A /* RCTImage.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 580C37561AB0F5970015E709 /* Products */;
|
||||
ProjectRef = 134180261AA91779003F314A /* RCTNetwork.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 580C378A1AB104AF0015E709 /* Products */;
|
||||
ProjectRef = 580C37891AB104AF0015E709 /* RCTTest.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 580C375B1AB0F5D10015E709 /* Products */;
|
||||
ProjectRef = 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 1405E9BD1AC3E63C00F5BC37 /* Products */;
|
||||
ProjectRef = 1405E9BC1AC3E63C00F5BC37 /* React.xcodeproj */;
|
||||
},
|
||||
);
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* IntegrationTests */,
|
||||
004D289D1AAF61C70097A701 /* IntegrationTestsTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
1405E9C11AC3E63C00F5BC37 /* libReact.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libReact.a;
|
||||
remoteRef = 1405E9C01AC3E63C00F5BC37 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
580C374B1AB0F54A0015E709 /* libRCTAdSupport.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTAdSupport.a;
|
||||
remoteRef = 580C374A1AB0F54A0015E709 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
580C37501AB0F55C0015E709 /* libRCTGeolocation.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTGeolocation.a;
|
||||
remoteRef = 580C374F1AB0F55C0015E709 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
580C37551AB0F56E0015E709 /* libRCTImage.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTImage.a;
|
||||
remoteRef = 580C37541AB0F56E0015E709 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
580C375A1AB0F5970015E709 /* libRCTNetwork.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTNetwork.a;
|
||||
remoteRef = 580C37591AB0F5970015E709 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
580C375F1AB0F5D10015E709 /* libRCTText.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTText.a;
|
||||
remoteRef = 580C375E1AB0F5D10015E709 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
580C378F1AB104B00015E709 /* libRCTTest.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTTest.a;
|
||||
remoteRef = 580C378E1AB104B00015E709 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
004D289C1AAF61C70097A701 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
004D289A1AAF61C70097A701 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
004D28A31AAF61C70097A701 /* IntegrationTestsTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
13B07F871A680F5B00A75B9A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
58005BCC1ABA44F10062E044 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 13B07F861A680F5B00A75B9A /* IntegrationTests */;
|
||||
targetProxy = 58005BCB1ABA44F10062E044 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
13B07FB21A68108700A75B9A /* Base */,
|
||||
);
|
||||
name = LaunchScreen.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
004D28A61AAF61C70097A701 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"FB_REFERENCE_IMAGE_DIR=\"\\\"$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages\\\"\"",
|
||||
"$(inherited)",
|
||||
);
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../React/**",
|
||||
);
|
||||
INFOPLIST_FILE = IntegrationTestsTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/IntegrationTests.app/IntegrationTests";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
004D28A71AAF61C70097A701 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
);
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../React/**",
|
||||
);
|
||||
INFOPLIST_FILE = IntegrationTestsTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/IntegrationTests.app/IntegrationTests";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../React/**",
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = IntegrationTests;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../React/**",
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = IntegrationTests;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../React/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
83CBBA211A601CBA00E9B192 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../React/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
004D28AD1AAF61C70097A701 /* Build configuration list for PBXNativeTarget "IntegrationTestsTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
004D28A61AAF61C70097A701 /* Debug */,
|
||||
004D28A71AAF61C70097A701 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "IntegrationTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
13B07F941A680F5B00A75B9A /* Debug */,
|
||||
13B07F951A680F5B00A75B9A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "IntegrationTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||
83CBBA211A601CBA00E9B192 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
}
|
|
@ -19,9 +19,17 @@ var slice = Array.prototype.slice;
|
|||
|
||||
var MethodTypes = keyMirror({
|
||||
remote: null,
|
||||
remoteAsync: null,
|
||||
local: null,
|
||||
});
|
||||
|
||||
type ErrorData = {
|
||||
message: string;
|
||||
domain: string;
|
||||
code: number;
|
||||
nativeStackIOS?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates remotely invokable modules.
|
||||
*/
|
||||
|
@ -36,21 +44,37 @@ var BatchedBridgeFactory = {
|
|||
*/
|
||||
_createBridgedModule: function(messageQueue, moduleConfig, moduleName) {
|
||||
var remoteModule = mapObject(moduleConfig.methods, function(methodConfig, memberName) {
|
||||
return methodConfig.type === MethodTypes.local ? null : function() {
|
||||
var lastArg = arguments.length > 0 ? arguments[arguments.length - 1] : null;
|
||||
var secondLastArg = arguments.length > 1 ? arguments[arguments.length - 2] : null;
|
||||
var hasSuccCB = typeof lastArg === 'function';
|
||||
var hasErrorCB = typeof secondLastArg === 'function';
|
||||
hasErrorCB && invariant(
|
||||
hasSuccCB,
|
||||
'Cannot have a non-function arg after a function arg.'
|
||||
);
|
||||
var numCBs = (hasSuccCB ? 1 : 0) + (hasErrorCB ? 1 : 0);
|
||||
var args = slice.call(arguments, 0, arguments.length - numCBs);
|
||||
var onSucc = hasSuccCB ? lastArg : null;
|
||||
var onFail = hasErrorCB ? secondLastArg : null;
|
||||
return messageQueue.call(moduleName, memberName, args, onFail, onSucc);
|
||||
};
|
||||
switch (methodConfig.type) {
|
||||
case MethodTypes.remoteAsync:
|
||||
return function(...args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
messageQueue.call(moduleName, memberName, args, resolve, (errorData) => {
|
||||
var error = _createErrorFromErrorData(errorData);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
case MethodTypes.local:
|
||||
return null;
|
||||
|
||||
default:
|
||||
return function() {
|
||||
var lastArg = arguments.length > 0 ? arguments[arguments.length - 1] : null;
|
||||
var secondLastArg = arguments.length > 1 ? arguments[arguments.length - 2] : null;
|
||||
var hasSuccCB = typeof lastArg === 'function';
|
||||
var hasErrorCB = typeof secondLastArg === 'function';
|
||||
hasErrorCB && invariant(
|
||||
hasSuccCB,
|
||||
'Cannot have a non-function arg after a function arg.'
|
||||
);
|
||||
var numCBs = (hasSuccCB ? 1 : 0) + (hasErrorCB ? 1 : 0);
|
||||
var args = slice.call(arguments, 0, arguments.length - numCBs);
|
||||
var onSucc = hasSuccCB ? lastArg : null;
|
||||
var onFail = hasErrorCB ? secondLastArg : null;
|
||||
return messageQueue.call(moduleName, memberName, args, onFail, onSucc);
|
||||
};
|
||||
}
|
||||
});
|
||||
for (var constName in moduleConfig.constants) {
|
||||
warning(!remoteModule[constName], 'saw constant and method named %s', constName);
|
||||
|
@ -59,7 +83,6 @@ var BatchedBridgeFactory = {
|
|||
return remoteModule;
|
||||
},
|
||||
|
||||
|
||||
create: function(MessageQueue, modulesConfig, localModulesConfig) {
|
||||
var messageQueue = new MessageQueue(modulesConfig, localModulesConfig);
|
||||
return {
|
||||
|
@ -80,4 +103,14 @@ var BatchedBridgeFactory = {
|
|||
}
|
||||
};
|
||||
|
||||
function _createErrorFromErrorData(errorData: ErrorData): Error {
|
||||
var {
|
||||
message,
|
||||
...extraErrorInfo,
|
||||
} = errorData;
|
||||
var error = new Error(message);
|
||||
error.framesToPop = 1;
|
||||
return Object.assign(error, extraErrorInfo);
|
||||
}
|
||||
|
||||
module.exports = BatchedBridgeFactory;
|
||||
|
|
|
@ -19,7 +19,6 @@ var Platform = require('Platform');
|
|||
var PropTypes = require('ReactPropTypes');
|
||||
var React = require('React');
|
||||
var ReactChildren = require('ReactChildren');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var Text = require('Text');
|
||||
var TextInputState = require('TextInputState');
|
||||
|
@ -29,36 +28,7 @@ var TouchableWithoutFeedback = require('TouchableWithoutFeedback');
|
|||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
var emptyFunction = require('emptyFunction');
|
||||
var invariant = require('invariant');
|
||||
var merge = require('merge');
|
||||
|
||||
var RCTTextViewAttributes = merge(ReactNativeViewAttributes.UIView, {
|
||||
autoCorrect: true,
|
||||
autoCapitalize: true,
|
||||
clearTextOnFocus: true,
|
||||
color: true,
|
||||
editable: true,
|
||||
fontFamily: true,
|
||||
fontSize: true,
|
||||
fontStyle: true,
|
||||
fontWeight: true,
|
||||
keyboardType: true,
|
||||
returnKeyType: true,
|
||||
enablesReturnKeyAutomatically: true,
|
||||
secureTextEntry: true,
|
||||
selectTextOnFocus: true,
|
||||
mostRecentEventCounter: true,
|
||||
placeholder: true,
|
||||
placeholderTextColor: true,
|
||||
text: true,
|
||||
});
|
||||
|
||||
var RCTTextFieldAttributes = merge(RCTTextViewAttributes, {
|
||||
caretHidden: true,
|
||||
enabled: true,
|
||||
clearButtonMode: true,
|
||||
clearTextOnFocus: true,
|
||||
selectTextOnFocus: true,
|
||||
});
|
||||
var requireNativeComponent = require('requireNativeComponent');
|
||||
|
||||
var onlyMultiline = {
|
||||
onSelectionChange: true,
|
||||
|
@ -82,16 +52,14 @@ var AndroidTextInputAttributes = {
|
|||
testID: true,
|
||||
};
|
||||
|
||||
var viewConfigIOS = {
|
||||
uiViewClassName: 'RCTTextField',
|
||||
validAttributes: RCTTextFieldAttributes,
|
||||
};
|
||||
|
||||
var viewConfigAndroid = {
|
||||
uiViewClassName: 'AndroidTextInput',
|
||||
validAttributes: AndroidTextInputAttributes,
|
||||
};
|
||||
|
||||
var RCTTextView = requireNativeComponent('RCTTextView', null);
|
||||
var RCTTextField = requireNativeComponent('RCTTextField', null);
|
||||
|
||||
type DefaultProps = {
|
||||
bufferDelay: number;
|
||||
};
|
||||
|
@ -164,7 +132,7 @@ var TextInput = React.createClass({
|
|||
*/
|
||||
keyboardType: PropTypes.oneOf([
|
||||
// Cross-platform
|
||||
'default',
|
||||
'default',
|
||||
'numeric',
|
||||
'email-address',
|
||||
// iOS-only
|
||||
|
@ -296,7 +264,7 @@ var TextInput = React.createClass({
|
|||
*/
|
||||
mixins: [NativeMethodsMixin, TimerMixin],
|
||||
|
||||
viewConfig: ((Platform.OS === 'ios' ? viewConfigIOS :
|
||||
viewConfig: ((Platform.OS === 'ios' ? RCTTextField.viewConfig :
|
||||
(Platform.OS === 'android' ? viewConfigAndroid : {})) : Object),
|
||||
|
||||
isFocused: function(): boolean {
|
||||
|
@ -510,6 +478,7 @@ var TextInput = React.createClass({
|
|||
onFocus={this._onFocus}
|
||||
onBlur={this._onBlur}
|
||||
onChange={this._onChange}
|
||||
onTextInput={this._onTextInput}
|
||||
onEndEditing={this.props.onEndEditing}
|
||||
onSubmitEditing={this.props.onSubmitEditing}
|
||||
onLayout={this.props.onLayout}
|
||||
|
@ -576,16 +545,6 @@ var styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
var RCTTextView = createReactNativeComponentClass({
|
||||
validAttributes: RCTTextViewAttributes,
|
||||
uiViewClassName: 'RCTTextView',
|
||||
});
|
||||
|
||||
var RCTTextField = createReactNativeComponentClass({
|
||||
validAttributes: RCTTextFieldAttributes,
|
||||
uiViewClassName: 'RCTTextField',
|
||||
});
|
||||
|
||||
var AndroidTextInput = createReactNativeComponentClass({
|
||||
validAttributes: AndroidTextInputAttributes,
|
||||
uiViewClassName: 'AndroidTextInput',
|
||||
|
|
|
@ -1290,7 +1290,7 @@ var Navigator = React.createClass({
|
|||
key={this.state.idStack[i]}
|
||||
ref={'scene_' + i}
|
||||
onStartShouldSetResponderCapture={() => {
|
||||
return !!this.state.transitionFromIndex || !!this.state.activeGesture;
|
||||
return (this.state.transitionFromIndex != null) || (this.state.transitionFromIndex != null);
|
||||
}}
|
||||
style={[styles.baseScene, this.props.sceneStyle, disabledSceneStyle]}>
|
||||
{React.cloneElement(child, {
|
||||
|
|
|
@ -164,7 +164,6 @@ var NavigatorBreadcrumbNavigationBar = React.createClass({
|
|||
renderToHardwareTextureAndroid: renderToHardwareTexture,
|
||||
};
|
||||
|
||||
this.refs['crumb_' + index].setNativeProps(props);
|
||||
this.refs['icon_' + index].setNativeProps(props);
|
||||
this.refs['separator_' + index].setNativeProps(props);
|
||||
this.refs['title_' + index].setNativeProps(props);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
1304D5AB1AA8C4A30002E2BE /* RCTStaticImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1304D5A81AA8C4A30002E2BE /* RCTStaticImage.m */; };
|
||||
1304D5AC1AA8C4A30002E2BE /* RCTStaticImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1304D5AA1AA8C4A30002E2BE /* RCTStaticImageManager.m */; };
|
||||
1304D5B21AA8C50D0002E2BE /* RCTGIFImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1304D5B11AA8C50D0002E2BE /* RCTGIFImage.m */; };
|
||||
1345A8391B26592900583190 /* RCTImageRequestHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 1345A8381B26592900583190 /* RCTImageRequestHandler.m */; };
|
||||
143879351AAD238D00F088A5 /* RCTCameraRollManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 143879341AAD238D00F088A5 /* RCTCameraRollManager.m */; };
|
||||
143879381AAD32A300F088A5 /* RCTImageLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 143879371AAD32A300F088A5 /* RCTImageLoader.m */; };
|
||||
58B5118F1A9E6BD600147676 /* RCTImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B5118A1A9E6BD600147676 /* RCTImageDownloader.m */; };
|
||||
|
@ -36,6 +37,8 @@
|
|||
1304D5AA1AA8C4A30002E2BE /* RCTStaticImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTStaticImageManager.m; sourceTree = "<group>"; };
|
||||
1304D5B01AA8C50D0002E2BE /* RCTGIFImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTGIFImage.h; sourceTree = "<group>"; };
|
||||
1304D5B11AA8C50D0002E2BE /* RCTGIFImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTGIFImage.m; sourceTree = "<group>"; };
|
||||
1345A8371B26592900583190 /* RCTImageRequestHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImageRequestHandler.h; sourceTree = "<group>"; };
|
||||
1345A8381B26592900583190 /* RCTImageRequestHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageRequestHandler.m; sourceTree = "<group>"; };
|
||||
143879331AAD238D00F088A5 /* RCTCameraRollManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTCameraRollManager.h; sourceTree = "<group>"; };
|
||||
143879341AAD238D00F088A5 /* RCTCameraRollManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTCameraRollManager.m; sourceTree = "<group>"; };
|
||||
143879361AAD32A300F088A5 /* RCTImageLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImageLoader.h; sourceTree = "<group>"; };
|
||||
|
@ -71,6 +74,8 @@
|
|||
1304D5B11AA8C50D0002E2BE /* RCTGIFImage.m */,
|
||||
58B511891A9E6BD600147676 /* RCTImageDownloader.h */,
|
||||
58B5118A1A9E6BD600147676 /* RCTImageDownloader.m */,
|
||||
1345A8371B26592900583190 /* RCTImageRequestHandler.h */,
|
||||
1345A8381B26592900583190 /* RCTImageRequestHandler.m */,
|
||||
58B5118B1A9E6BD600147676 /* RCTNetworkImageView.h */,
|
||||
58B5118C1A9E6BD600147676 /* RCTNetworkImageView.m */,
|
||||
58B5118D1A9E6BD600147676 /* RCTNetworkImageViewManager.h */,
|
||||
|
@ -152,6 +157,7 @@
|
|||
58B5118F1A9E6BD600147676 /* RCTImageDownloader.m in Sources */,
|
||||
58B511911A9E6BD600147676 /* RCTNetworkImageViewManager.m in Sources */,
|
||||
1304D5AC1AA8C4A30002E2BE /* RCTStaticImageManager.m in Sources */,
|
||||
1345A8391B26592900583190 /* RCTImageRequestHandler.m in Sources */,
|
||||
58B511901A9E6BD600147676 /* RCTNetworkImageView.m in Sources */,
|
||||
1304D5B21AA8C50D0002E2BE /* RCTGIFImage.m in Sources */,
|
||||
143879351AAD238D00F088A5 /* RCTCameraRollManager.m in Sources */,
|
||||
|
|
|
@ -82,8 +82,8 @@ static NSString *RCTCacheKeyForURL(NSURL *url)
|
|||
RCTImageDownloader *strongSelf = weakSelf;
|
||||
NSArray *blocks = strongSelf->_pendingBlocks[cacheKey];
|
||||
[strongSelf->_pendingBlocks removeObjectForKey:cacheKey];
|
||||
for (RCTCachedDataDownloadBlock cacheDownloadBlock in blocks) {
|
||||
cacheDownloadBlock(cached, data, error);
|
||||
for (RCTCachedDataDownloadBlock downloadBlock in blocks) {
|
||||
downloadBlock(cached, data, error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -16,9 +16,22 @@
|
|||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTDefines.h"
|
||||
#import "RCTGIFImage.h"
|
||||
#import "RCTImageDownloader.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
static void RCTDispatchCallbackOnMainQueue(void (^ __nonnull callback)(NSError *, id), NSError *error, UIImage *image)
|
||||
{
|
||||
if ([NSThread isMainThread]) {
|
||||
callback(error, image);
|
||||
} else {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
callback(error, image);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static dispatch_queue_t RCTImageLoaderQueue(void)
|
||||
{
|
||||
|
@ -31,24 +44,6 @@ static dispatch_queue_t RCTImageLoaderQueue(void)
|
|||
return queue;
|
||||
}
|
||||
|
||||
static NSError *RCTErrorWithMessage(NSString *message)
|
||||
{
|
||||
NSDictionary *errorInfo = @{NSLocalizedDescriptionKey: message};
|
||||
NSError *error = [[NSError alloc] initWithDomain:RCTErrorDomain code:0 userInfo:errorInfo];
|
||||
return error;
|
||||
}
|
||||
|
||||
static void RCTDispatchCallbackOnMainQueue(void (^callback)(NSError *, id), NSError *error, UIImage *image)
|
||||
{
|
||||
if ([NSThread isMainThread]) {
|
||||
callback(error, image);
|
||||
} else {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
callback(error, image);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@implementation RCTImageLoader
|
||||
|
||||
+ (ALAssetsLibrary *)assetsLibrary
|
||||
|
|
|
@ -7,11 +7,8 @@
|
|||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "RCTURLRequestHandler.h"
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (nonatomic, strong) UIWindow *window;
|
||||
@interface RCTImageRequestHandler : NSObject <RCTURLRequestHandler>
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// RCTImageRequestHandler.m
|
||||
// RCTImage
|
||||
//
|
||||
// Created by Nick Lockwood on 09/06/2015.
|
||||
// Copyright (c) 2015 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RCTImageRequestHandler.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTImageLoader.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@implementation RCTImageRequestHandler
|
||||
{
|
||||
NSInteger _currentToken;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (BOOL)canHandleRequest:(NSURLRequest *)request
|
||||
{
|
||||
return [@[@"assets-library", @"ph"] containsObject:[request.URL.scheme lowercaseString]];
|
||||
}
|
||||
|
||||
- (id)sendRequest:(NSURLRequest *)request
|
||||
withDelegate:(id<RCTURLRequestDelegate>)delegate
|
||||
{
|
||||
NSNumber *requestToken = @(++_currentToken);
|
||||
NSString *URLString = [request.URL absoluteString];
|
||||
[RCTImageLoader loadImageWithTag:URLString callback:^(NSError *error, UIImage *image) {
|
||||
if (error) {
|
||||
[delegate URLRequest:requestToken didCompleteWithError:error];
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *mimeType = nil;
|
||||
NSData *imageData = nil;
|
||||
if (RCTImageHasAlpha(image.CGImage)) {
|
||||
mimeType = @"image/png";
|
||||
imageData = UIImagePNGRepresentation(image);
|
||||
} else {
|
||||
mimeType = @"image/jpeg";
|
||||
imageData = UIImageJPEGRepresentation(image, 1.0);
|
||||
}
|
||||
|
||||
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:request.URL
|
||||
MIMEType:mimeType
|
||||
expectedContentLength:imageData.length
|
||||
textEncodingName:nil];
|
||||
|
||||
[delegate URLRequest:requestToken didReceiveResponse:response];
|
||||
[delegate URLRequest:requestToken didReceiveData:imageData];
|
||||
[delegate URLRequest:requestToken didCompleteWithError:nil];
|
||||
}];
|
||||
|
||||
return requestToken;
|
||||
}
|
||||
|
||||
@end
|
|
@ -85,7 +85,7 @@ function setUpAlert() {
|
|||
var alertOpts = {
|
||||
title: 'Alert',
|
||||
message: '' + text,
|
||||
buttons: [{'cancel': 'Okay'}],
|
||||
buttons: [{'cancel': 'OK'}],
|
||||
};
|
||||
RCTAlertManager.alertWithArgs(alertOpts, null);
|
||||
};
|
||||
|
@ -102,6 +102,7 @@ function setUpXHR() {
|
|||
// The native XMLHttpRequest in Chrome dev tools is CORS aware and won't
|
||||
// let you fetch anything from the internet
|
||||
GLOBAL.XMLHttpRequest = require('XMLHttpRequest');
|
||||
GLOBAL.FormData = require('FormData');
|
||||
|
||||
var fetchPolyfill = require('fetch');
|
||||
GLOBAL.fetch = fetchPolyfill.fetch;
|
||||
|
|
|
@ -13,9 +13,10 @@
|
|||
|
||||
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||
var RCTLinkingManager = require('NativeModules').LinkingManager;
|
||||
var Map = require('Map');
|
||||
var invariant = require('invariant');
|
||||
|
||||
var _notifHandlers = {};
|
||||
var _notifHandlers = new Map();
|
||||
var _initialURL = RCTLinkingManager &&
|
||||
RCTLinkingManager.initialURL;
|
||||
|
||||
|
@ -80,10 +81,6 @@ var DEVICE_NOTIF_EVENT = 'openURL';
|
|||
* }
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* _The iOS simulator does not support the `mailto:` and `tel:` schemas
|
||||
* because the Mail and Phone apps are not installed - you will need to test
|
||||
* them on a device._
|
||||
*/
|
||||
class LinkingIOS {
|
||||
/**
|
||||
|
@ -95,10 +92,11 @@ class LinkingIOS {
|
|||
type === 'url',
|
||||
'LinkingIOS only supports `url` events'
|
||||
);
|
||||
_notifHandlers[handler] = RCTDeviceEventEmitter.addListener(
|
||||
var listener = RCTDeviceEventEmitter.addListener(
|
||||
DEVICE_NOTIF_EVENT,
|
||||
handler
|
||||
);
|
||||
_notifHandlers.set(handler, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,11 +107,12 @@ class LinkingIOS {
|
|||
type === 'url',
|
||||
'LinkingIOS only supports `url` events'
|
||||
);
|
||||
if (!_notifHandlers[handler]) {
|
||||
var listener = _notifHandlers.get(handler);
|
||||
if (!listener) {
|
||||
return;
|
||||
}
|
||||
_notifHandlers[handler].remove();
|
||||
_notifHandlers[handler] = null;
|
||||
listener.remove();
|
||||
_notifHandlers.delete(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* 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 FormData
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
type FormDataValue = any;
|
||||
type FormDataPart = [string, FormDataValue];
|
||||
|
||||
/**
|
||||
* Polyfill for XMLHttpRequest2 FormData API, allowing multipart POST requests
|
||||
* with mixed data (string, native files) to be submitted via XMLHttpRequest.
|
||||
*/
|
||||
class FormData {
|
||||
_parts: Array<FormDataPart>;
|
||||
_partsByKey: {[key: string]: FormDataPart};
|
||||
|
||||
constructor() {
|
||||
this._parts = [];
|
||||
this._partsByKey = {};
|
||||
}
|
||||
|
||||
append(key: string, value: FormDataValue) {
|
||||
var parts = this._partsByKey[key];
|
||||
if (parts) {
|
||||
// It's a bit unclear what the behaviour should be in this case.
|
||||
// The XMLHttpRequest spec doesn't specify it, while MDN says that
|
||||
// the any new values should appended to existing values. We're not
|
||||
// doing that for now -- it's tedious and doesn't seem worth the effort.
|
||||
parts[1] = value;
|
||||
return;
|
||||
}
|
||||
parts = [key, value];
|
||||
this._parts.push(parts);
|
||||
this._partsByKey[key] = parts;
|
||||
}
|
||||
|
||||
getParts(): Array<FormDataValue> {
|
||||
return this._parts.map(([name, value]) => {
|
||||
if (typeof value === 'string') {
|
||||
return {
|
||||
string: value,
|
||||
headers: {
|
||||
'content-disposition': 'form-data; name="' + name + '"',
|
||||
},
|
||||
};
|
||||
}
|
||||
var contentDisposition = 'form-data; name="' + name + '"';
|
||||
if (typeof value.name === 'string') {
|
||||
contentDisposition += '; filename="' + value.name + '"';
|
||||
}
|
||||
return {
|
||||
...value,
|
||||
headers: {'content-disposition': contentDisposition},
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FormData;
|
|
@ -11,70 +11,451 @@
|
|||
|
||||
#import "RCTAssert.h"
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTURLRequestHandler.h"
|
||||
#import "RCTEventDispatcher.h"
|
||||
#import "RCTHTTPRequestHandler.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@implementation RCTDataManager
|
||||
typedef void (^RCTHTTPQueryResult)(NSError *error, NSDictionary *result);
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
@interface RCTDataManager ()<RCTURLRequestDelegate>
|
||||
|
||||
- (void)processDataForHTTPQuery:(NSDictionary *)data callback:(void (^)(NSError *error, NSDictionary *result))callback;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* Executes a network request.
|
||||
* The responseSender block won't be called on same thread as called.
|
||||
* Helper to convert FormData payloads into multipart/formdata requests.
|
||||
*/
|
||||
RCT_EXPORT_METHOD(queryData:(NSString *)queryType
|
||||
withQuery:(NSDictionary *)query
|
||||
responseSender:(RCTResponseSenderBlock)responseSender)
|
||||
@interface RCTHTTPFormDataHelper : NSObject
|
||||
|
||||
@property (nonatomic, weak) RCTDataManager *dataManager;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTHTTPFormDataHelper
|
||||
{
|
||||
if ([queryType isEqualToString:@"http"]) {
|
||||
NSMutableArray *parts;
|
||||
NSMutableData *multipartBody;
|
||||
RCTHTTPQueryResult _callback;
|
||||
NSString *boundary;
|
||||
}
|
||||
|
||||
// Build request
|
||||
NSURL *URL = [RCTConvert NSURL:query[@"url"]];
|
||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
|
||||
request.HTTPMethod = [RCTConvert NSString:query[@"method"]] ?: @"GET";
|
||||
request.allHTTPHeaderFields = [RCTConvert NSDictionary:query[@"headers"]];
|
||||
request.HTTPBody = [RCTConvert NSData:query[@"data"]];
|
||||
- (void)process:(NSArray *)formData callback:(nonnull void (^)(NSError *error, NSDictionary *result))callback
|
||||
{
|
||||
if (![formData count]) {
|
||||
callback(nil, nil);
|
||||
return;
|
||||
}
|
||||
parts = [formData mutableCopy];
|
||||
_callback = callback;
|
||||
multipartBody = [[NSMutableData alloc] init];
|
||||
boundary = [self generateBoundary];
|
||||
|
||||
// Build data task
|
||||
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *connectionError) {
|
||||
NSDictionary *currentPart = [parts objectAtIndex: 0];
|
||||
[_dataManager processDataForHTTPQuery:currentPart callback:^(NSError *e, NSDictionary *r) {
|
||||
[self handleResult:r error:e];
|
||||
}];
|
||||
}
|
||||
|
||||
NSHTTPURLResponse *httpResponse = nil;
|
||||
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
|
||||
// Might be a local file request
|
||||
httpResponse = (NSHTTPURLResponse *)response;
|
||||
}
|
||||
- (NSString *)generateBoundary
|
||||
{
|
||||
NSString *const boundaryChars = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_./";
|
||||
const NSUInteger boundaryLength = 70;
|
||||
|
||||
// Build response
|
||||
NSArray *responseJSON;
|
||||
if (connectionError == nil) {
|
||||
NSStringEncoding encoding = NSUTF8StringEncoding;
|
||||
if (response.textEncodingName) {
|
||||
CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);
|
||||
encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
|
||||
}
|
||||
responseJSON = @[
|
||||
@(httpResponse.statusCode ?: 200),
|
||||
httpResponse.allHeaderFields ?: @{},
|
||||
[[NSString alloc] initWithData:data encoding:encoding] ?: @"",
|
||||
];
|
||||
} else {
|
||||
responseJSON = @[
|
||||
@(httpResponse.statusCode),
|
||||
httpResponse.allHeaderFields ?: @{},
|
||||
connectionError.localizedDescription ?: [NSNull null],
|
||||
];
|
||||
}
|
||||
NSMutableString *output = [NSMutableString stringWithCapacity:boundaryLength];
|
||||
NSUInteger numchars = [boundaryChars length];
|
||||
for (NSUInteger i = 0; i < boundaryLength; i++) {
|
||||
[output appendFormat:@"%C", [boundaryChars characterAtIndex:arc4random_uniform((u_int32_t)numchars)]];
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// Send response (won't be sent on same thread as caller)
|
||||
responseSender(responseJSON);
|
||||
- (void)handleResult:(NSDictionary *)result error:(NSError *)error
|
||||
{
|
||||
if (error) {
|
||||
_callback(error, nil);
|
||||
return;
|
||||
}
|
||||
NSDictionary *currentPart = parts[0];
|
||||
[parts removeObjectAtIndex:0];
|
||||
|
||||
// Start with boundary.
|
||||
[multipartBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary]
|
||||
dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
// Print headers.
|
||||
NSMutableDictionary *headers = [(NSDictionary*)currentPart[@"headers"] mutableCopy];
|
||||
NSString *partContentType = result[@"contentType"];
|
||||
if (partContentType != nil) {
|
||||
[headers setObject:partContentType forKey:@"content-type"];
|
||||
}
|
||||
[headers enumerateKeysAndObjectsUsingBlock:^(NSString *parameterKey, NSString *parameterValue, BOOL *stop) {
|
||||
[multipartBody appendData:[[NSString stringWithFormat:@"%@: %@\r\n", parameterKey, parameterValue]
|
||||
dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
}];
|
||||
|
||||
// Add the body.
|
||||
[multipartBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[multipartBody appendData:result[@"body"]];
|
||||
[multipartBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
if ([parts count]) {
|
||||
NSDictionary *nextPart = [parts objectAtIndex: 0];
|
||||
[_dataManager processDataForHTTPQuery:nextPart callback:^(NSError *e, NSDictionary *r) {
|
||||
[self handleResult:r error:e];
|
||||
}];
|
||||
return;
|
||||
}
|
||||
|
||||
[task resume];
|
||||
// We've processed the last item. Finish and return.
|
||||
[multipartBody appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary]
|
||||
dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=\"%@\"", boundary];
|
||||
_callback(nil, @{@"body": multipartBody, @"contentType": contentType});
|
||||
}
|
||||
|
||||
} else {
|
||||
@end
|
||||
|
||||
RCTLogError(@"unsupported query type %@", queryType);
|
||||
/**
|
||||
* Helper to package in-flight requests together with their response data.
|
||||
*/
|
||||
@interface RCTActiveURLRequest : NSObject
|
||||
|
||||
@property (nonatomic, strong) NSNumber *requestID;
|
||||
@property (nonatomic, strong) NSURLRequest *request;
|
||||
@property (nonatomic, strong) id<RCTURLRequestHandler> handler;
|
||||
@property (nonatomic, assign) BOOL incrementalUpdates;
|
||||
@property (nonatomic, strong) NSURLResponse *response;
|
||||
@property (nonatomic, strong) NSMutableData *data;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTActiveURLRequest
|
||||
|
||||
- (void)setResponse:(NSURLResponse *)response;
|
||||
{
|
||||
_response = response;
|
||||
if (!_incrementalUpdates) {
|
||||
_data = [[NSMutableData alloc] initWithCapacity:(NSUInteger)MAX(0, response.expectedContentLength)];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* Helper to load request body data using a handler.
|
||||
*/
|
||||
@interface RCTDataLoader : NSObject <RCTURLRequestDelegate>
|
||||
|
||||
@end
|
||||
|
||||
typedef void (^RCTDataLoaderCallback)(NSData *data, NSString *MIMEType, NSError *error);
|
||||
|
||||
@implementation RCTDataLoader
|
||||
{
|
||||
RCTDataLoaderCallback _callback;
|
||||
RCTActiveURLRequest *_request;
|
||||
id _requestToken;
|
||||
}
|
||||
|
||||
- (instancetype)initWithRequest:(NSURLRequest *)request
|
||||
handler:(id<RCTURLRequestHandler>)handler
|
||||
callback:(RCTDataLoaderCallback)callback
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_callback = callback;
|
||||
_request = [[RCTActiveURLRequest alloc] init];
|
||||
_request.request = request;
|
||||
_request.handler = handler;
|
||||
_request.incrementalUpdates = NO;
|
||||
_requestToken = [handler sendRequest:request withDelegate:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)URLRequest:(id)requestToken didReceiveResponse:(NSURLResponse *)response
|
||||
{
|
||||
RCTAssert([requestToken isEqual:_requestToken], @"Shouldn't ever happen");
|
||||
_request.response = response;
|
||||
}
|
||||
|
||||
- (void)URLRequest:(id)requestToken didReceiveData:(NSData *)data
|
||||
{
|
||||
RCTAssert([requestToken isEqual:_requestToken], @"Shouldn't ever happen");
|
||||
[_request.data appendData:data];
|
||||
}
|
||||
|
||||
- (void)URLRequest:(id)requestToken didCompleteWithError:(NSError *)error
|
||||
{
|
||||
RCTAssert(_callback != nil, @"The callback property must be set");
|
||||
_callback(_request.data, _request.response.MIMEType, error);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* Bridge module that provides the JS interface to the network stack.
|
||||
*/
|
||||
@implementation RCTDataManager
|
||||
{
|
||||
NSInteger _currentRequestID;
|
||||
NSMapTable *_activeRequests;
|
||||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_currentRequestID = 0;
|
||||
_activeRequests = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory
|
||||
valueOptions:NSPointerFunctionsStrongMemory
|
||||
capacity:0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)buildRequest:(NSDictionary *)query
|
||||
responseSender:(RCTResponseSenderBlock)responseSender
|
||||
{
|
||||
NSURL *URL = [RCTConvert NSURL:query[@"url"]];
|
||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
|
||||
request.HTTPMethod = [[RCTConvert NSString:query[@"method"]] uppercaseString] ?: @"GET";
|
||||
request.allHTTPHeaderFields = [RCTConvert NSDictionary:query[@"headers"]];
|
||||
|
||||
BOOL incrementalUpdates = [RCTConvert BOOL:query[@"incrementalUpdates"]];
|
||||
|
||||
NSDictionary *data = [RCTConvert NSDictionary:query[@"data"]];
|
||||
[self processDataForHTTPQuery:data callback:^(NSError *error, NSDictionary *result) {
|
||||
if (error) {
|
||||
RCTLogError(@"Error processing request body: %@", error);
|
||||
// Ideally we'd circle back to JS here and notify an error/abort on the request.
|
||||
return;
|
||||
}
|
||||
request.HTTPBody = result[@"body"];
|
||||
NSString *contentType = result[@"contentType"];
|
||||
if (contentType) {
|
||||
[request setValue:contentType forHTTPHeaderField:@"content-type"];
|
||||
}
|
||||
[self sendRequest:request
|
||||
incrementalUpdates:incrementalUpdates
|
||||
responseSender:responseSender];
|
||||
}];
|
||||
}
|
||||
|
||||
- (id<RCTURLRequestHandler>)handlerForRequest:(NSURLRequest *)request
|
||||
{
|
||||
NSMutableArray *handlers = [NSMutableArray array];
|
||||
for (id<RCTBridgeModule> module in _bridge.modules.allValues) {
|
||||
if ([module conformsToProtocol:@protocol(RCTURLRequestHandler)]) {
|
||||
if ([(id<RCTURLRequestHandler>)module canHandleRequest:request]) {
|
||||
[handlers addObject:module];
|
||||
}
|
||||
}
|
||||
}
|
||||
[handlers sortUsingComparator:^NSComparisonResult(id<RCTURLRequestHandler> a, id<RCTURLRequestHandler> b) {
|
||||
float priorityA = [a respondsToSelector:@selector(handlerPriority)] ? [a handlerPriority] : 0;
|
||||
float priorityB = [b respondsToSelector:@selector(handlerPriority)] ? [b handlerPriority] : 0;
|
||||
if (priorityA < priorityB) {
|
||||
return NSOrderedAscending;
|
||||
} else if (priorityA > priorityB) {
|
||||
return NSOrderedDescending;
|
||||
} else {
|
||||
RCTLogError(@"The RCTURLRequestHandlers %@ and %@ both reported that"
|
||||
" they can handle the request %@, and have equal priority"
|
||||
" (%g). This could result in non-deterministic behavior.",
|
||||
a, b, request, priorityA);
|
||||
|
||||
return NSOrderedSame;
|
||||
}
|
||||
}];
|
||||
id<RCTURLRequestHandler> handler = [handlers lastObject];
|
||||
if (!handler) {
|
||||
RCTLogError(@"No suitable request handler found for %@", request);
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the 'data' part of an HTTP query.
|
||||
*
|
||||
* 'data' can be a JSON value of the following forms:
|
||||
*
|
||||
* - {"string": "..."}: a simple JS string that will be UTF-8 encoded and sent as the body
|
||||
*
|
||||
* - {"uri": "some-uri://..."}: reference to a system resource, e.g. an image in the asset library
|
||||
*
|
||||
* - {"formData": [...]}: list of data payloads that will be combined into a multipart/form-data request
|
||||
*
|
||||
* If successful, the callback be called with a result dictionary containing the following (optional) keys:
|
||||
*
|
||||
* - @"body" (NSData): the body of the request
|
||||
*
|
||||
* - @"contentType" (NSString): the content type header of the request
|
||||
*
|
||||
*/
|
||||
- (void)processDataForHTTPQuery:(NSDictionary *)query callback:(nonnull void (^)(NSError *error, NSDictionary *result))callback
|
||||
{
|
||||
if (!query) {
|
||||
callback(nil, nil);
|
||||
return;
|
||||
}
|
||||
NSData *body = [RCTConvert NSData:query[@"string"]];
|
||||
if (body) {
|
||||
callback(nil, @{@"body": body});
|
||||
return;
|
||||
}
|
||||
NSURLRequest *request = [RCTConvert NSURLRequest:query[@"uri"]];
|
||||
if (request) {
|
||||
id<RCTURLRequestHandler> handler = [self handlerForRequest:request];
|
||||
(void)[[RCTDataLoader alloc] initWithRequest:request handler:handler callback:^(NSData *data, NSString *MIMEType, NSError *error) {
|
||||
if (data) {
|
||||
callback(nil, @{@"body": data, @"contentType": MIMEType});
|
||||
} else {
|
||||
callback(error, nil);
|
||||
}
|
||||
}];
|
||||
return;
|
||||
}
|
||||
NSDictionaryArray *formData = [RCTConvert NSDictionaryArray:query[@"formData"]];
|
||||
if (formData != nil) {
|
||||
RCTHTTPFormDataHelper *formDataHelper = [[RCTHTTPFormDataHelper alloc] init];
|
||||
formDataHelper.dataManager = self;
|
||||
[formDataHelper process:formData callback:callback];
|
||||
return;
|
||||
}
|
||||
// Nothing in the data payload, at least nothing we could understand anyway.
|
||||
// Ignore and treat it as if it were null.
|
||||
callback(nil, nil);
|
||||
}
|
||||
|
||||
- (void)sendRequest:(NSURLRequest *)request
|
||||
incrementalUpdates:(BOOL)incrementalUpdates
|
||||
responseSender:(RCTResponseSenderBlock)responseSender
|
||||
{
|
||||
id<RCTURLRequestHandler> handler = [self handlerForRequest:request];
|
||||
id token = [handler sendRequest:request withDelegate:self];
|
||||
if (token) {
|
||||
RCTActiveURLRequest *activeRequest = [[RCTActiveURLRequest alloc] init];
|
||||
activeRequest.requestID = @(++_currentRequestID);
|
||||
activeRequest.request = request;
|
||||
activeRequest.handler = handler;
|
||||
activeRequest.incrementalUpdates = incrementalUpdates;
|
||||
[_activeRequests setObject:activeRequest forKey:token];
|
||||
responseSender(@[activeRequest.requestID]);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sendData:(NSData *)data forRequestToken:(id)requestToken
|
||||
{
|
||||
if (data.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
RCTActiveURLRequest *request = [_activeRequests objectForKey:requestToken];
|
||||
|
||||
// Get text encoding
|
||||
NSURLResponse *response = request.response;
|
||||
NSStringEncoding encoding = NSUTF8StringEncoding;
|
||||
if (response.textEncodingName) {
|
||||
CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);
|
||||
encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
|
||||
}
|
||||
|
||||
NSString *responseText = [[NSString alloc] initWithData:data encoding:encoding];
|
||||
if (!responseText && data.length) {
|
||||
RCTLogError(@"Received data was invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray *responseJSON = @[request.requestID, responseText ?: @""];
|
||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"didReceiveNetworkData"
|
||||
body:responseJSON];
|
||||
}
|
||||
|
||||
#pragma mark - RCTURLRequestDelegate
|
||||
|
||||
- (void)URLRequest:(id)requestToken didReceiveResponse:(NSURLResponse *)response
|
||||
{
|
||||
RCTActiveURLRequest *request = [_activeRequests objectForKey:requestToken];
|
||||
RCTAssert(request != nil, @"Unrecognized request token: %@", requestToken);
|
||||
|
||||
request.response = response;
|
||||
|
||||
NSHTTPURLResponse *httpResponse = nil;
|
||||
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
|
||||
// Might be a local file request
|
||||
httpResponse = (NSHTTPURLResponse *)response;
|
||||
}
|
||||
|
||||
NSArray *responseJSON = @[request.requestID,
|
||||
@(httpResponse.statusCode ?: 200),
|
||||
httpResponse.allHeaderFields ?: @{},
|
||||
];
|
||||
|
||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"didReceiveNetworkResponse"
|
||||
body:responseJSON];
|
||||
}
|
||||
|
||||
- (void)URLRequest:(id)requestToken didReceiveData:(NSData *)data
|
||||
{
|
||||
RCTActiveURLRequest *request = [_activeRequests objectForKey:requestToken];
|
||||
RCTAssert(request != nil, @"Unrecognized request token: %@", requestToken);
|
||||
|
||||
if (request.incrementalUpdates) {
|
||||
[self sendData:data forRequestToken:requestToken];
|
||||
} else {
|
||||
[request.data appendData:data];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)URLRequest:(id)requestToken didCompleteWithError:(NSError *)error
|
||||
{
|
||||
RCTActiveURLRequest *request = [_activeRequests objectForKey:requestToken];
|
||||
RCTAssert(request != nil, @"Unrecognized request token: %@", requestToken);
|
||||
|
||||
if (!request.incrementalUpdates) {
|
||||
[self sendData:request.data forRequestToken:requestToken];
|
||||
}
|
||||
|
||||
NSArray *responseJSON = @[request.requestID,
|
||||
error.localizedDescription ?: [NSNull null]
|
||||
];
|
||||
|
||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"didCompleteNetworkResponse"
|
||||
body:responseJSON];
|
||||
|
||||
[_activeRequests removeObjectForKey:requestToken];
|
||||
}
|
||||
|
||||
#pragma mark - JS API
|
||||
|
||||
RCT_EXPORT_METHOD(sendRequest:(NSDictionary *)query
|
||||
responseSender:(RCTResponseSenderBlock)responseSender)
|
||||
{
|
||||
[self buildRequest:query responseSender:responseSender];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(cancelRequest:(NSNumber *)requestID)
|
||||
{
|
||||
id requestToken = nil;
|
||||
RCTActiveURLRequest *activeRequest = nil;
|
||||
for (id token in _activeRequests) {
|
||||
RCTActiveURLRequest *request = [_activeRequests objectForKey:token];
|
||||
if ([request.requestID isEqualToNumber:requestID]) {
|
||||
activeRequest = request;
|
||||
requestToken = token;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
id<RCTURLRequestHandler> handler = activeRequest.handler;
|
||||
if ([handler respondsToSelector:@selector(cancelRequest:)]) {
|
||||
[activeRequest.handler cancelRequest:requestToken];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,9 @@
|
|||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
#import "RCTURLRequestHandler.h"
|
||||
#import "RCTInvalidating.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
@interface RCTHTTPRequestHandler : NSObject <RCTURLRequestHandler, RCTInvalidating>
|
||||
|
||||
@end
|
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import "RCTHTTPRequestHandler.h"
|
||||
|
||||
#import "RCTAssert.h"
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTEventDispatcher.h"
|
||||
#import "RCTImageLoader.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@interface RCTHTTPRequestHandler () <NSURLSessionDataDelegate>
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTHTTPRequestHandler
|
||||
{
|
||||
NSMapTable *_delegates;
|
||||
NSURLSession *_session;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_delegates = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory
|
||||
valueOptions:NSPointerFunctionsStrongMemory
|
||||
capacity:0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
[_session invalidateAndCancel];
|
||||
_session = nil;
|
||||
_delegates = nil;
|
||||
}
|
||||
|
||||
- (BOOL)isValid
|
||||
{
|
||||
return _delegates != nil;
|
||||
}
|
||||
|
||||
#pragma mark - NSURLRequestHandler
|
||||
|
||||
- (BOOL)canHandleRequest:(NSURLRequest *)request
|
||||
{
|
||||
return [@[@"http", @"https", @"file"] containsObject:[request.URL.scheme lowercaseString]];
|
||||
}
|
||||
|
||||
- (id)sendRequest:(NSURLRequest *)request
|
||||
withDelegate:(id<RCTURLRequestDelegate>)delegate
|
||||
{
|
||||
// Lazy setup
|
||||
if (!_session && [self isValid]) {
|
||||
NSOperationQueue *callbackQueue = [[NSOperationQueue alloc] init];
|
||||
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||
_session = [NSURLSession sessionWithConfiguration:configuration
|
||||
delegate:self
|
||||
delegateQueue:callbackQueue];
|
||||
}
|
||||
|
||||
NSURLSessionDataTask *task = [_session dataTaskWithRequest:request];
|
||||
[_delegates setObject:delegate forKey:task];
|
||||
[task resume];
|
||||
return task;
|
||||
}
|
||||
|
||||
- (void)cancelRequest:(NSURLSessionDataTask *)requestToken
|
||||
{
|
||||
[requestToken cancel];
|
||||
}
|
||||
|
||||
#pragma mark - NSURLSession delegate
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session
|
||||
dataTask:(NSURLSessionDataTask *)task
|
||||
didReceiveResponse:(NSURLResponse *)response
|
||||
completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
|
||||
{
|
||||
[[_delegates objectForKey:task] URLRequest:task didReceiveResponse:response];
|
||||
completionHandler(NSURLSessionResponseAllow);
|
||||
}
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session
|
||||
dataTask:(NSURLSessionDataTask *)task
|
||||
didReceiveData:(NSData *)data
|
||||
{
|
||||
[[_delegates objectForKey:task] URLRequest:task didReceiveData:data];
|
||||
}
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
|
||||
{
|
||||
[[_delegates objectForKey:task] URLRequest:task didCompleteWithError:error];
|
||||
[_delegates removeObjectForKey:task];
|
||||
}
|
||||
|
||||
@end
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
1372B7371AB03E7B00659ED6 /* RCTReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 1372B7361AB03E7B00659ED6 /* RCTReachability.m */; };
|
||||
352DA0BA1B17855800AA15A8 /* RCTHTTPRequestHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 352DA0B81B17855800AA15A8 /* RCTHTTPRequestHandler.m */; };
|
||||
58B512081A9E6CE300147676 /* RCTDataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B512071A9E6CE300147676 /* RCTDataManager.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
@ -26,6 +27,8 @@
|
|||
/* Begin PBXFileReference section */
|
||||
1372B7351AB03E7B00659ED6 /* RCTReachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTReachability.h; sourceTree = "<group>"; };
|
||||
1372B7361AB03E7B00659ED6 /* RCTReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTReachability.m; sourceTree = "<group>"; };
|
||||
352DA0B71B17855800AA15A8 /* RCTHTTPRequestHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTHTTPRequestHandler.h; sourceTree = "<group>"; };
|
||||
352DA0B81B17855800AA15A8 /* RCTHTTPRequestHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTHTTPRequestHandler.m; sourceTree = "<group>"; };
|
||||
58B511DB1A9E6C8500147676 /* libRCTNetwork.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTNetwork.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
58B512061A9E6CE300147676 /* RCTDataManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDataManager.h; sourceTree = "<group>"; };
|
||||
58B512071A9E6CE300147676 /* RCTDataManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDataManager.m; sourceTree = "<group>"; };
|
||||
|
@ -47,6 +50,8 @@
|
|||
children = (
|
||||
58B512061A9E6CE300147676 /* RCTDataManager.h */,
|
||||
58B512071A9E6CE300147676 /* RCTDataManager.m */,
|
||||
352DA0B71B17855800AA15A8 /* RCTHTTPRequestHandler.h */,
|
||||
352DA0B81B17855800AA15A8 /* RCTHTTPRequestHandler.m */,
|
||||
1372B7351AB03E7B00659ED6 /* RCTReachability.h */,
|
||||
1372B7361AB03E7B00659ED6 /* RCTReachability.m */,
|
||||
58B511DC1A9E6C8500147676 /* Products */,
|
||||
|
@ -121,6 +126,7 @@
|
|||
files = (
|
||||
1372B7371AB03E7B00659ED6 /* RCTReachability.m in Sources */,
|
||||
58B512081A9E6CE300147676 /* RCTDataManager.m in Sources */,
|
||||
352DA0BA1B17855800AA15A8 /* RCTHTTPRequestHandler.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -209,6 +215,7 @@
|
|||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../React/**",
|
||||
"$(SRCROOT)/../Image/**",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
|
@ -226,6 +233,7 @@
|
|||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../React/**",
|
||||
"$(SRCROOT)/../Image/**",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
|
|
|
@ -11,30 +11,102 @@
|
|||
*/
|
||||
'use strict';
|
||||
|
||||
var FormData = require('FormData');
|
||||
var RCTDataManager = require('NativeModules').DataManager;
|
||||
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||
|
||||
var XMLHttpRequestBase = require('XMLHttpRequestBase');
|
||||
|
||||
class XMLHttpRequest extends XMLHttpRequestBase {
|
||||
|
||||
_requestId: ?number;
|
||||
_subscriptions: [any];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._requestId = null;
|
||||
this._subscriptions = [];
|
||||
}
|
||||
|
||||
_didCreateRequest(requestId: number): void {
|
||||
this._requestId = requestId;
|
||||
this._subscriptions.push(RCTDeviceEventEmitter.addListener(
|
||||
'didReceiveNetworkResponse',
|
||||
(args) => this._didReceiveResponse.call(this, args[0], args[1], args[2])
|
||||
));
|
||||
this._subscriptions.push(RCTDeviceEventEmitter.addListener(
|
||||
'didReceiveNetworkData',
|
||||
(args) => this._didReceiveData.call(this, args[0], args[1])
|
||||
));
|
||||
this._subscriptions.push(RCTDeviceEventEmitter.addListener(
|
||||
'didCompleteNetworkResponse',
|
||||
(args) => this._didCompleteResponse.call(this, args[0], args[1])
|
||||
));
|
||||
}
|
||||
|
||||
_didReceiveResponse(requestId: number, status: number, responseHeaders: ?Object): void {
|
||||
if (requestId === this._requestId) {
|
||||
this.status = status;
|
||||
this.setResponseHeaders(responseHeaders);
|
||||
this.setReadyState(this.HEADERS_RECEIVED);
|
||||
}
|
||||
}
|
||||
|
||||
_didReceiveData(requestId: number, responseText: string): void {
|
||||
if (requestId === this._requestId) {
|
||||
if (!this.responseText) {
|
||||
this.responseText = responseText;
|
||||
} else {
|
||||
this.responseText += responseText;
|
||||
}
|
||||
this.setReadyState(this.LOADING);
|
||||
}
|
||||
}
|
||||
|
||||
_didCompleteResponse(requestId: number, error: string): void {
|
||||
if (requestId === this._requestId) {
|
||||
if (error) {
|
||||
this.responseText = error;
|
||||
}
|
||||
this._clearSubscriptions();
|
||||
this._requestId = null;
|
||||
this.setReadyState(this.DONE);
|
||||
}
|
||||
}
|
||||
|
||||
_clearSubscriptions(): void {
|
||||
for (var i = 0; i < this._subscriptions.length; i++) {
|
||||
var sub = this._subscriptions[i];
|
||||
sub.remove();
|
||||
}
|
||||
this._subscriptions = [];
|
||||
}
|
||||
|
||||
sendImpl(method: ?string, url: ?string, headers: Object, data: any): void {
|
||||
RCTDataManager.queryData(
|
||||
'http',
|
||||
if (typeof data === 'string') {
|
||||
data = {string: data};
|
||||
}
|
||||
if (data instanceof FormData) {
|
||||
data = {formData: data.getParts()};
|
||||
}
|
||||
RCTDataManager.sendRequest(
|
||||
{
|
||||
method: method,
|
||||
url: url,
|
||||
data: data,
|
||||
headers: headers,
|
||||
method,
|
||||
url,
|
||||
data,
|
||||
headers,
|
||||
incrementalUpdates: this.onreadystatechange ? true : false,
|
||||
},
|
||||
this.callback.bind(this)
|
||||
this._didCreateRequest.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
abortImpl(): void {
|
||||
console.warn(
|
||||
'XMLHttpRequest: abort() cancels JS callbacks ' +
|
||||
'but not native HTTP request.'
|
||||
);
|
||||
if (this._requestId) {
|
||||
RCTDataManager.cancelRequest(this._requestId);
|
||||
this._clearSubscriptions();
|
||||
this._requestId = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
* 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.
|
||||
*
|
||||
* @flow
|
||||
* @providesModule XMLHttpRequestBase
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
|
@ -30,6 +35,7 @@ class XMLHttpRequestBase {
|
|||
_headers: Object;
|
||||
_sent: boolean;
|
||||
_aborted: boolean;
|
||||
_lowerCaseResponseHeaders: Object;
|
||||
|
||||
constructor() {
|
||||
this.UNSENT = 0;
|
||||
|
@ -38,46 +44,52 @@ class XMLHttpRequestBase {
|
|||
this.LOADING = 3;
|
||||
this.DONE = 4;
|
||||
|
||||
this.onreadystatechange = undefined;
|
||||
this.upload = undefined; /* Upload not supported */
|
||||
this.readyState = this.UNSENT;
|
||||
this.responseHeaders = undefined;
|
||||
this.responseText = undefined;
|
||||
this.status = 0;
|
||||
this.onreadystatechange = null;
|
||||
this.onload = null;
|
||||
this.upload = undefined; /* Upload not supported yet */
|
||||
|
||||
this._reset();
|
||||
this._method = null;
|
||||
this._url = null;
|
||||
this._headers = {};
|
||||
this._sent = false;
|
||||
this._aborted = false;
|
||||
}
|
||||
|
||||
_reset() {
|
||||
this.readyState = this.UNSENT;
|
||||
this.responseHeaders = undefined;
|
||||
this.responseText = '';
|
||||
this.status = 0;
|
||||
|
||||
this._headers = {};
|
||||
this._sent = false;
|
||||
this._lowerCaseResponseHeaders = {};
|
||||
}
|
||||
|
||||
getAllResponseHeaders(): ?string {
|
||||
if (this.responseHeaders) {
|
||||
var headers = [];
|
||||
for (var headerName in this.responseHeaders) {
|
||||
headers.push(headerName + ': ' + this.responseHeaders[headerName]);
|
||||
}
|
||||
return headers.join('\n');
|
||||
if (!this.responseHeaders) {
|
||||
// according to the spec, return null if no response has been received
|
||||
return null;
|
||||
}
|
||||
// according to the spec, return null <==> no response has been received
|
||||
return null;
|
||||
var headers = this.responseHeaders || {};
|
||||
return Object.keys(headers).map((headerName) => {
|
||||
return headerName + ': ' + headers[headerName];
|
||||
}).join('\n');
|
||||
}
|
||||
|
||||
getResponseHeader(header: string): ?string {
|
||||
if (this.responseHeaders) {
|
||||
var value = this.responseHeaders[header.toLowerCase()];
|
||||
return value !== undefined ? value : null;
|
||||
}
|
||||
return null;
|
||||
var value = this._lowerCaseResponseHeaders[header.toLowerCase()];
|
||||
return value !== undefined ? value : null;
|
||||
}
|
||||
|
||||
setRequestHeader(header: string, value: any): void {
|
||||
if (this.readyState !== this.OPENED) {
|
||||
throw new Error('Request has not been opened');
|
||||
}
|
||||
this._headers[header.toLowerCase()] = value;
|
||||
}
|
||||
|
||||
open(method: string, url: string, async: ?boolean): void {
|
||||
/* Other optional arguments are not supported */
|
||||
/* Other optional arguments are not supported yet */
|
||||
if (this.readyState !== this.UNSENT) {
|
||||
throw new Error('Cannot open, already sending');
|
||||
}
|
||||
|
@ -85,10 +97,11 @@ class XMLHttpRequestBase {
|
|||
// async is default
|
||||
throw new Error('Synchronous http requests are not supported');
|
||||
}
|
||||
this._reset();
|
||||
this._method = method;
|
||||
this._url = url;
|
||||
this._aborted = false;
|
||||
this._setReadyState(this.OPENED);
|
||||
this.setReadyState(this.OPENED);
|
||||
}
|
||||
|
||||
sendImpl(method: ?string, url: ?string, headers: Object, data: any): void {
|
||||
|
@ -111,20 +124,18 @@ class XMLHttpRequestBase {
|
|||
}
|
||||
|
||||
abort(): void {
|
||||
this._aborted = true;
|
||||
this.abortImpl();
|
||||
// only call onreadystatechange if there is something to abort,
|
||||
// below logic is per spec
|
||||
if (!(this.readyState === this.UNSENT ||
|
||||
(this.readyState === this.OPENED && !this._sent) ||
|
||||
this.readyState === this.DONE)) {
|
||||
this._sent = false;
|
||||
this._setReadyState(this.DONE);
|
||||
this._reset();
|
||||
this.setReadyState(this.DONE);
|
||||
}
|
||||
if (this.readyState === this.DONE) {
|
||||
this._sendLoad();
|
||||
}
|
||||
this.readyState = this.UNSENT;
|
||||
this._aborted = true;
|
||||
// Reset again after, in case modified in handler
|
||||
this._reset();
|
||||
}
|
||||
|
||||
callback(status: number, responseHeaders: ?Object, responseText: string): void {
|
||||
|
@ -132,18 +143,22 @@ class XMLHttpRequestBase {
|
|||
return;
|
||||
}
|
||||
this.status = status;
|
||||
// Headers should be case-insensitive
|
||||
var lcResponseHeaders = {};
|
||||
for (var header in responseHeaders) {
|
||||
lcResponseHeaders[header.toLowerCase()] = responseHeaders[header];
|
||||
}
|
||||
this.responseHeaders = lcResponseHeaders;
|
||||
this.setResponseHeaders(responseHeaders);
|
||||
this.responseText = responseText;
|
||||
this._setReadyState(this.DONE);
|
||||
this._sendLoad();
|
||||
this.setReadyState(this.DONE);
|
||||
}
|
||||
|
||||
_setReadyState(newState: number): void {
|
||||
setResponseHeaders(responseHeaders: ?Object): void {
|
||||
this.responseHeaders = responseHeaders || null;
|
||||
var headers = responseHeaders || {};
|
||||
this._lowerCaseResponseHeaders =
|
||||
Object.keys(headers).reduce((lcaseHeaders, headerName) => {
|
||||
lcaseHeaders[headerName.toLowerCase()] = headers[headerName];
|
||||
return headers;
|
||||
}, {});
|
||||
}
|
||||
|
||||
setReadyState(newState: number): void {
|
||||
this.readyState = newState;
|
||||
// TODO: workaround flow bug with nullable function checks
|
||||
var onreadystatechange = this.onreadystatechange;
|
||||
|
@ -152,6 +167,9 @@ class XMLHttpRequestBase {
|
|||
// event anywhere, let's leave it empty
|
||||
onreadystatechange(null);
|
||||
}
|
||||
if (newState === this.DONE && !this._aborted) {
|
||||
this._sendLoad();
|
||||
}
|
||||
}
|
||||
|
||||
_sendLoad(): void {
|
||||
|
|
|
@ -121,7 +121,7 @@ RCT_EXPORT_METHOD(getApplicationIconBadgeNumber:(RCTResponseSenderBlock)callback
|
|||
|
||||
RCT_EXPORT_METHOD(requestPermissions:(NSDictionary *)permissions)
|
||||
{
|
||||
UIUserNotificationType types = UIRemoteNotificationTypeNone;
|
||||
UIUserNotificationType types = UIUserNotificationTypeNone;
|
||||
if (permissions) {
|
||||
if ([permissions[@"alert"] boolValue]) {
|
||||
types |= UIUserNotificationTypeAlert;
|
||||
|
|
|
@ -69,4 +69,21 @@ RCT_EXPORT_METHOD(sendAppEvent:(NSString *)name body:(id)body)
|
|||
[_bridge.eventDispatcher sendAppEventWithName:name body:body];
|
||||
}
|
||||
|
||||
RCT_REMAP_METHOD(shouldResolve, shouldResolve_resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
resolve(@1);
|
||||
}
|
||||
|
||||
RCT_REMAP_METHOD(shouldReject, shouldReject_resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
reject(nil);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(finish:(BOOL)success)
|
||||
{
|
||||
RCTAssert(success, @"RCTTestModule finished without success");
|
||||
[self markTestCompleted];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
|
|
@ -35,6 +35,7 @@ var createReactNativeComponentClass = function(
|
|||
this.previousFlattenedStyle = null;
|
||||
};
|
||||
Constructor.displayName = viewConfig.uiViewClassName;
|
||||
Constructor.viewConfig = viewConfig;
|
||||
Constructor.prototype = new ReactNativeBaseComponent(viewConfig);
|
||||
Constructor.prototype.constructor = Constructor;
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
var StyleSheetRegistry = require('StyleSheetRegistry');
|
||||
var invariant = require('invariant');
|
||||
var mergeIntoFast = require('mergeIntoFast');
|
||||
|
||||
type Atom = number | bool | Object | Array<?Atom>
|
||||
type StyleObj = Atom | Array<?StyleObj>
|
||||
|
@ -25,10 +24,7 @@ function getStyle(style) {
|
|||
return style;
|
||||
}
|
||||
|
||||
// TODO: Flow 0.7.0 doesn't refine bools properly so we have to use `any` to
|
||||
// tell it that this can't be a bool anymore. Should be fixed in 0.8.0,
|
||||
// after which this can take a ?StyleObj.
|
||||
function flattenStyle(style: any): ?Object {
|
||||
function flattenStyle(style: ?StyleObj): ?Object {
|
||||
if (!style) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -42,7 +38,13 @@ function flattenStyle(style: any): ?Object {
|
|||
for (var i = 0; i < style.length; ++i) {
|
||||
var computedStyle = flattenStyle(style[i]);
|
||||
if (computedStyle) {
|
||||
mergeIntoFast(result, computedStyle);
|
||||
for (var key in computedStyle) {
|
||||
result[key] = computedStyle[key];
|
||||
|
||||
if (__DEV__) {
|
||||
var value = computedStyle[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -127,7 +127,7 @@ function _convertToRadians(value: string): number {
|
|||
function _validateTransform(key, value, transformation) {
|
||||
invariant(
|
||||
!value.getValue,
|
||||
'You passed an animated value or spring to a normal component. ' +
|
||||
'You passed an Animated.Value to a normal component. ' +
|
||||
'You need to wrap that component in an Animated. For example, ' +
|
||||
'replace <View /> by <Animated.View />.'
|
||||
);
|
||||
|
|
|
@ -514,10 +514,10 @@ var MessageQueueMixin = {
|
|||
);
|
||||
// Store callback _before_ sending the request, just in case the MailBox
|
||||
// returns the response in a blocking manner.
|
||||
if (onSucc) {
|
||||
if (onFail || onSucc) {
|
||||
this._storeCallbacksInCurrentThread(onFail, onSucc, scope, this._POOLED_CBIDS);
|
||||
onFail && params.push(this._POOLED_CBIDS.errorCallbackID);
|
||||
params.push(this._POOLED_CBIDS.successCallbackID);
|
||||
onSucc && params.push(this._POOLED_CBIDS.successCallbackID);
|
||||
}
|
||||
var moduleID = this._remoteModuleNameToModuleID[moduleName];
|
||||
if (moduleID === undefined || moduleID === null) {
|
||||
|
|
|
@ -31,8 +31,11 @@ typedef void (^RCTWSMessageCallback)(NSError *error, NSDictionary *reply);
|
|||
RCTSparseArray *_callbacks;
|
||||
dispatch_semaphore_t _socketOpenSemaphore;
|
||||
NSMutableDictionary *_injectedObjects;
|
||||
NSURL *_url;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [self initWithURL:[NSURL URLWithString:@"http://localhost:8081/debugger-proxy"]];
|
||||
|
@ -41,41 +44,45 @@ typedef void (^RCTWSMessageCallback)(NSError *error, NSDictionary *reply);
|
|||
- (instancetype)initWithURL:(NSURL *)URL
|
||||
{
|
||||
if (self = [super init]) {
|
||||
|
||||
_jsQueue = dispatch_queue_create("com.facebook.React.WebSocketExecutor", DISPATCH_QUEUE_SERIAL);
|
||||
_socket = [[RCTSRWebSocket alloc] initWithURL:URL];
|
||||
_socket.delegate = self;
|
||||
_callbacks = [[RCTSparseArray alloc] init];
|
||||
_injectedObjects = [[NSMutableDictionary alloc] init];
|
||||
[_socket setDelegateDispatchQueue:_jsQueue];
|
||||
|
||||
NSURL *startDevToolsURL = [NSURL URLWithString:@"/launch-chrome-devtools" relativeToURL:URL];
|
||||
[NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:startDevToolsURL] delegate:nil];
|
||||
|
||||
if (![self connectToProxy]) {
|
||||
RCTLogError(@"Connection to %@ timed out. Are you running node proxy? If \
|
||||
you are running on the device, check if you have the right IP \
|
||||
address in `RCTWebSocketExecutor.m`.", URL);
|
||||
[self invalidate];
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSInteger retries = 3;
|
||||
BOOL runtimeIsReady = [self prepareJSRuntime];
|
||||
while (!runtimeIsReady && retries > 0) {
|
||||
runtimeIsReady = [self prepareJSRuntime];
|
||||
retries--;
|
||||
}
|
||||
if (!runtimeIsReady) {
|
||||
RCTLogError(@"Runtime is not ready. Make sure Chrome is running and not "
|
||||
"paused on a breakpoint or exception and try reloading again.");
|
||||
[self invalidate];
|
||||
return nil;
|
||||
}
|
||||
_url = URL;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
_jsQueue = dispatch_queue_create("com.facebook.React.WebSocketExecutor", DISPATCH_QUEUE_SERIAL);
|
||||
_socket = [[RCTSRWebSocket alloc] initWithURL:_url];
|
||||
_socket.delegate = self;
|
||||
_callbacks = [[RCTSparseArray alloc] init];
|
||||
_injectedObjects = [[NSMutableDictionary alloc] init];
|
||||
[_socket setDelegateDispatchQueue:_jsQueue];
|
||||
|
||||
NSURL *startDevToolsURL = [NSURL URLWithString:@"/launch-chrome-devtools" relativeToURL:_url];
|
||||
[NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:startDevToolsURL] delegate:nil];
|
||||
|
||||
if (![self connectToProxy]) {
|
||||
RCTLogError(@"Connection to %@ timed out. Are you running node proxy? If \
|
||||
you are running on the device, check if you have the right IP \
|
||||
address in `RCTWebSocketExecutor.m`.", _url);
|
||||
[self invalidate];
|
||||
return;
|
||||
}
|
||||
|
||||
NSInteger retries = 3;
|
||||
BOOL runtimeIsReady = [self prepareJSRuntime];
|
||||
while (!runtimeIsReady && retries > 0) {
|
||||
runtimeIsReady = [self prepareJSRuntime];
|
||||
retries--;
|
||||
}
|
||||
if (!runtimeIsReady) {
|
||||
RCTLogError(@"Runtime is not ready. Make sure Chrome is running and not "
|
||||
"paused on a breakpoint or exception and try reloading again.");
|
||||
[self invalidate];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)connectToProxy
|
||||
{
|
||||
_socketOpenSemaphore = dispatch_semaphore_create(0);
|
||||
|
|
|
@ -62,6 +62,7 @@ var ReactNative = Object.assign(Object.create(require('React')), {
|
|||
DeviceEventEmitter: require('RCTDeviceEventEmitter'),
|
||||
NativeAppEventEmitter: require('RCTNativeAppEventEmitter'),
|
||||
NativeModules: require('NativeModules'),
|
||||
Platform: require('Platform'),
|
||||
requireNativeComponent: require('requireNativeComponent'),
|
||||
|
||||
addons: {
|
||||
|
|
|
@ -47,12 +47,17 @@ typedef NS_ENUM(NSUInteger, RCTBridgeFields) {
|
|||
RCTBridgeFieldFlushDateMillis
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, RCTJavaScriptFunctionKind) {
|
||||
RCTJavaScriptFunctionKindNormal,
|
||||
RCTJavaScriptFunctionKindAsync,
|
||||
};
|
||||
|
||||
#ifdef __LP64__
|
||||
typedef uint64_t RCTHeaderValue;
|
||||
typedef struct mach_header_64 *RCTHeaderValue;
|
||||
typedef struct section_64 RCTHeaderSection;
|
||||
#define RCTGetSectByNameFromHeader getsectbynamefromheader_64
|
||||
#else
|
||||
typedef uint32_t RCTHeaderValue;
|
||||
typedef struct mach_header *RCTHeaderValue;
|
||||
typedef struct section RCTHeaderSection;
|
||||
#define RCTGetSectByNameFromHeader getsectbynamefromheader
|
||||
#endif
|
||||
|
@ -98,15 +103,15 @@ static NSArray *RCTJSMethods(void)
|
|||
dladdr(&RCTJSMethods, &info);
|
||||
|
||||
const RCTHeaderValue mach_header = (RCTHeaderValue)info.dli_fbase;
|
||||
const RCTHeaderSection *section = RCTGetSectByNameFromHeader((void *)mach_header, "__DATA", "RCTImport");
|
||||
|
||||
if (section) {
|
||||
for (RCTHeaderValue addr = section->offset;
|
||||
addr < section->offset + section->size;
|
||||
unsigned long size = 0;
|
||||
const uint8_t *sectionData = getsectiondata(mach_header, "__DATA", "RCTImport", &size);
|
||||
if (sectionData) {
|
||||
for (const uint8_t *addr = sectionData;
|
||||
addr < sectionData + size;
|
||||
addr += sizeof(const char **)) {
|
||||
|
||||
// Get data entry
|
||||
NSString *entry = @(*(const char **)(mach_header + addr));
|
||||
NSString *entry = @(*(const char **)addr);
|
||||
[uniqueMethods addObject:entry];
|
||||
}
|
||||
}
|
||||
|
@ -139,15 +144,15 @@ static NSArray *RCTBridgeModuleClassesByModuleID(void)
|
|||
dladdr(&RCTBridgeModuleClassesByModuleID, &info);
|
||||
|
||||
const RCTHeaderValue mach_header = (RCTHeaderValue)info.dli_fbase;
|
||||
const RCTHeaderSection *section = RCTGetSectByNameFromHeader((void *)mach_header, "__DATA", "RCTExportModule");
|
||||
|
||||
if (section) {
|
||||
for (RCTHeaderValue addr = section->offset;
|
||||
addr < section->offset + section->size;
|
||||
unsigned long size;
|
||||
const uint8_t *sectionData = getsectiondata(mach_header, "__DATA", "RCTExportModule", &size);
|
||||
if (sectionData) {
|
||||
for (const uint8_t *addr = sectionData;
|
||||
addr < sectionData + size;
|
||||
addr += sizeof(const char **)) {
|
||||
|
||||
// Get data entry
|
||||
NSString *entry = @(*(const char **)(mach_header + addr));
|
||||
NSString *entry = @(*(const char **)addr);
|
||||
NSArray *parts = [[entry substringWithRange:(NSRange){2, entry.length - 3}]
|
||||
componentsSeparatedByString:@" "];
|
||||
|
||||
|
@ -204,6 +209,27 @@ static NSArray *RCTBridgeModuleClassesByModuleID(void)
|
|||
return RCTModuleClassesByID;
|
||||
}
|
||||
|
||||
// TODO: Can we just replace RCTMakeError with this function instead?
|
||||
static NSDictionary *RCTJSErrorFromNSError(NSError *error)
|
||||
{
|
||||
NSString *errorMessage;
|
||||
NSArray *stackTrace = [NSThread callStackSymbols];
|
||||
NSMutableDictionary *errorInfo =
|
||||
[NSMutableDictionary dictionaryWithObject:stackTrace forKey:@"nativeStackIOS"];
|
||||
|
||||
if (error) {
|
||||
errorMessage = error.localizedDescription ?: @"Unknown error from a native module";
|
||||
errorInfo[@"domain"] = error.domain ?: RCTErrorDomain;
|
||||
errorInfo[@"code"] = @(error.code);
|
||||
} else {
|
||||
errorMessage = @"Unknown error from a native module";
|
||||
errorInfo[@"domain"] = RCTErrorDomain;
|
||||
errorInfo[@"code"] = @-1;
|
||||
}
|
||||
|
||||
return RCTMakeError(errorMessage, nil, errorInfo);
|
||||
}
|
||||
|
||||
@class RCTBatchedBridge;
|
||||
|
||||
@interface RCTBridge ()
|
||||
|
@ -239,6 +265,7 @@ static NSArray *RCTBridgeModuleClassesByModuleID(void)
|
|||
@property (nonatomic, copy, readonly) NSString *moduleClassName;
|
||||
@property (nonatomic, copy, readonly) NSString *JSMethodName;
|
||||
@property (nonatomic, assign, readonly) SEL selector;
|
||||
@property (nonatomic, assign, readonly) RCTJavaScriptFunctionKind functionKind;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -390,22 +417,64 @@ case _value: { \
|
|||
|
||||
[invocation setArgument:returnValue atIndex:index];
|
||||
|
||||
free(returnValue);
|
||||
}];
|
||||
break;
|
||||
free(returnValue);
|
||||
}];
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
defaultCase(argumentType);
|
||||
}
|
||||
} else if ([argumentName isEqualToString:@"RCTResponseSenderBlock"]) {
|
||||
addBlockArgument();
|
||||
} else if ([argumentName isEqualToString:@"RCTPromiseResolveBlock"]) {
|
||||
RCTAssert(i == numberOfArguments - 2,
|
||||
@"The RCTPromiseResolveBlock must be the second to last parameter in -[%@ %@]",
|
||||
_moduleClassName, objCMethodName);
|
||||
RCT_ARG_BLOCK(
|
||||
if (RCT_DEBUG && ![json isKindOfClass:[NSNumber class]]) {
|
||||
RCTLogError(@"Argument %tu (%@) of %@.%@ must be a promise resolver ID", index,
|
||||
json, RCTBridgeModuleNameForClass(_moduleClass), _JSMethodName);
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
defaultCase(argumentType);
|
||||
}
|
||||
} else if ([argumentName isEqualToString:@"RCTResponseSenderBlock"]) {
|
||||
addBlockArgument();
|
||||
} else {
|
||||
// Marked as autoreleasing, because NSInvocation doesn't retain arguments
|
||||
__autoreleasing RCTPromiseResolveBlock value = (^(id result) {
|
||||
NSArray *arguments = result ? @[result] : @[];
|
||||
[bridge _invokeAndProcessModule:@"BatchedBridge"
|
||||
method:@"invokeCallbackAndReturnFlushedQueue"
|
||||
arguments:@[json, arguments]
|
||||
context:context];
|
||||
});
|
||||
)
|
||||
_functionKind = RCTJavaScriptFunctionKindAsync;
|
||||
} else if ([argumentName isEqualToString:@"RCTPromiseRejectBlock"]) {
|
||||
RCTAssert(i == numberOfArguments - 1,
|
||||
@"The RCTPromiseRejectBlock must be the last parameter in -[%@ %@]",
|
||||
_moduleClassName, objCMethodName);
|
||||
RCT_ARG_BLOCK(
|
||||
if (RCT_DEBUG && ![json isKindOfClass:[NSNumber class]]) {
|
||||
RCTLogError(@"Argument %tu (%@) of %@.%@ must be a promise rejecter ID", index,
|
||||
json, RCTBridgeModuleNameForClass(_moduleClass), _JSMethodName);
|
||||
return;
|
||||
}
|
||||
|
||||
// Unknown argument type
|
||||
RCTLogError(@"Unknown argument type '%@' in method %@. Extend RCTConvert"
|
||||
" to support this type.", argumentName, [self methodName]);
|
||||
}
|
||||
// Marked as autoreleasing, because NSInvocation doesn't retain arguments
|
||||
__autoreleasing RCTPromiseRejectBlock value = (^(NSError *error) {
|
||||
NSDictionary *errorJSON = RCTJSErrorFromNSError(error);
|
||||
[bridge _invokeAndProcessModule:@"BatchedBridge"
|
||||
method:@"invokeCallbackAndReturnFlushedQueue"
|
||||
arguments:@[json, @[errorJSON]]
|
||||
context:context];
|
||||
});
|
||||
)
|
||||
_functionKind = RCTJavaScriptFunctionKindAsync;
|
||||
} else {
|
||||
|
||||
// Unknown argument type
|
||||
RCTLogError(@"Unknown argument type '%@' in method %@. Extend RCTConvert"
|
||||
" to support this type.", argumentName, [self methodName]);
|
||||
}
|
||||
}
|
||||
|
||||
_argumentBlocks = [argumentBlocks copy];
|
||||
|
@ -427,9 +496,18 @@ case _value: { \
|
|||
|
||||
// Safety check
|
||||
if (arguments.count != _argumentBlocks.count) {
|
||||
NSInteger actualCount = arguments.count;
|
||||
NSInteger expectedCount = _argumentBlocks.count;
|
||||
|
||||
// Subtract the implicit Promise resolver and rejecter functions for implementations of async functions
|
||||
if (_functionKind == RCTJavaScriptFunctionKindAsync) {
|
||||
actualCount -= 2;
|
||||
expectedCount -= 2;
|
||||
}
|
||||
|
||||
RCTLogError(@"%@.%@ was called with %zd arguments, but expects %zd",
|
||||
RCTBridgeModuleNameForClass(_moduleClass), _JSMethodName,
|
||||
arguments.count, _argumentBlocks.count);
|
||||
actualCount, expectedCount);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -481,21 +559,23 @@ static RCTSparseArray *RCTExportedMethodsByModuleID(void)
|
|||
dladdr(&RCTExportedMethodsByModuleID, &info);
|
||||
|
||||
const RCTHeaderValue mach_header = (RCTHeaderValue)info.dli_fbase;
|
||||
const RCTHeaderSection *section = RCTGetSectByNameFromHeader((void *)mach_header, "__DATA", "RCTExport");
|
||||
|
||||
if (section == NULL) {
|
||||
unsigned long size;
|
||||
const uint8_t *sectionData = getsectiondata(mach_header, "__DATA", "RCTExport", &size);
|
||||
|
||||
if (sectionData == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray *classes = RCTBridgeModuleClassesByModuleID();
|
||||
NSMutableDictionary *methodsByModuleClassName = [NSMutableDictionary dictionaryWithCapacity:[classes count]];
|
||||
|
||||
for (RCTHeaderValue addr = section->offset;
|
||||
addr < section->offset + section->size;
|
||||
for (const uint8_t *addr = sectionData;
|
||||
addr < sectionData + size;
|
||||
addr += sizeof(const char **) * 3) {
|
||||
|
||||
// Get data entry
|
||||
const char **entries = (const char **)(mach_header + addr);
|
||||
const char **entries = (const char **) addr;
|
||||
|
||||
// Create method
|
||||
RCTModuleMethod *moduleMethod =
|
||||
|
@ -533,7 +613,7 @@ static RCTSparseArray *RCTExportedMethodsByModuleID(void)
|
|||
* },
|
||||
* "methodName2": {
|
||||
* "methodID": 1,
|
||||
* "type": "remote"
|
||||
* "type": "remoteAsync"
|
||||
* },
|
||||
* etc...
|
||||
* },
|
||||
|
@ -557,7 +637,7 @@ static NSDictionary *RCTRemoteModulesConfig(NSDictionary *modulesByName)
|
|||
[methods enumerateObjectsUsingBlock:^(RCTModuleMethod *method, NSUInteger methodID, BOOL *_stop) {
|
||||
methodsByName[method.JSMethodName] = @{
|
||||
@"methodID": @(methodID),
|
||||
@"type": @"remote",
|
||||
@"type": method.functionKind == RCTJavaScriptFunctionKindAsync ? @"remoteAsync" : @"remote",
|
||||
};
|
||||
}];
|
||||
|
||||
|
@ -819,7 +899,7 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
|||
@implementation RCTBatchedBridge
|
||||
{
|
||||
BOOL _loading;
|
||||
id<RCTJavaScriptExecutor> _javaScriptExecutor;
|
||||
__weak id<RCTJavaScriptExecutor> _javaScriptExecutor;
|
||||
RCTSparseArray *_modulesByID;
|
||||
RCTSparseArray *_queuesByID;
|
||||
dispatch_queue_t _methodQueue;
|
||||
|
@ -856,13 +936,6 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
|||
[_mainDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize executor to allow enqueueing calls
|
||||
*/
|
||||
Class executorClass = self.executorClass ?: [RCTContextExecutor class];
|
||||
_javaScriptExecutor = RCTCreateExecutor(executorClass);
|
||||
_latestJSExecutor = _javaScriptExecutor;
|
||||
|
||||
/**
|
||||
* Initialize and register bridge modules *before* adding the display link
|
||||
* so we don't have threading issues
|
||||
|
@ -900,7 +973,7 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
|||
|
||||
- (Class)executorClass
|
||||
{
|
||||
return _parentBridge.executorClass;
|
||||
return _parentBridge.executorClass ?: [RCTContextExecutor class];
|
||||
}
|
||||
|
||||
- (void)setExecutorClass:(Class)executorClass
|
||||
|
@ -965,6 +1038,16 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
|||
// Store modules
|
||||
_modulesByName = [modulesByName copy];
|
||||
|
||||
/**
|
||||
* The executor is a bridge module, wait for it to be created and set it before
|
||||
* any other module has access to the bridge
|
||||
*/
|
||||
_javaScriptExecutor = _modulesByName[RCTBridgeModuleNameForClass(self.executorClass)];
|
||||
_latestJSExecutor = _javaScriptExecutor;
|
||||
RCTSetExecutorID(_javaScriptExecutor);
|
||||
|
||||
[_javaScriptExecutor setUp];
|
||||
|
||||
// Set bridge
|
||||
for (id<RCTBridgeModule> module in _modulesByName.allValues) {
|
||||
if ([module respondsToSelector:@selector(setBridge:)]) {
|
||||
|
@ -1081,6 +1164,10 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
|||
|
||||
- (NSDictionary *)modules
|
||||
{
|
||||
if (!self.isValid) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
RCTAssert(_modulesByName != nil, @"Bridge modules have not yet been initialized. "
|
||||
"You may be trying to access a module too early in the startup procedure.");
|
||||
|
||||
|
@ -1111,7 +1198,9 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
|||
// Invalidate modules
|
||||
for (id target in _modulesByID.allObjects) {
|
||||
if ([target respondsToSelector:@selector(invalidate)]) {
|
||||
[(id<RCTInvalidating>)target invalidate];
|
||||
[self dispatchBlock:^{
|
||||
[(id<RCTInvalidating>)target invalidate];
|
||||
} forModule:target];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1373,15 +1462,42 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: if we sort the requests by module, we could dispatch once per
|
||||
// module instead of per request, which would reduce the call overhead.
|
||||
NSMapTable *buckets = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsStrongMemory capacity:_queuesByID.count];
|
||||
for (NSUInteger i = 0; i < numRequests; i++) {
|
||||
@autoreleasepool {
|
||||
[self _handleRequestNumber:i
|
||||
moduleID:[moduleIDs[i] integerValue]
|
||||
methodID:[methodIDs[i] integerValue]
|
||||
params:paramsArrays[i]
|
||||
context:context];
|
||||
id queue = RCTNullIfNil(_queuesByID[moduleIDs[i]]);
|
||||
NSMutableOrderedSet *set = [buckets objectForKey:queue];
|
||||
if (!set) {
|
||||
set = [[NSMutableOrderedSet alloc] init];
|
||||
[buckets setObject:set forKey:queue];
|
||||
}
|
||||
[set addObject:@(i)];
|
||||
}
|
||||
|
||||
for (id queue in buckets) {
|
||||
RCTProfileBeginFlowEvent();
|
||||
dispatch_block_t block = ^{
|
||||
RCTProfileEndFlowEvent();
|
||||
RCTProfileBeginEvent();
|
||||
|
||||
NSOrderedSet *calls = [buckets objectForKey:queue];
|
||||
@autoreleasepool {
|
||||
for (NSNumber *indexObj in calls) {
|
||||
NSUInteger index = indexObj.unsignedIntegerValue;
|
||||
[self _handleRequestNumber:index
|
||||
moduleID:[moduleIDs[index] integerValue]
|
||||
methodID:[methodIDs[index] integerValue]
|
||||
params:paramsArrays[index]
|
||||
context:context];
|
||||
}
|
||||
}
|
||||
|
||||
RCTProfileEndEvent(RCTCurrentThreadName(), @"objc_call,dispatch_async", @{ @"calls": @(calls.count) });
|
||||
};
|
||||
|
||||
if (queue == (id)kCFNull) {
|
||||
[_javaScriptExecutor executeBlockOnJavaScriptQueue:block];
|
||||
} else {
|
||||
dispatch_async(queue, block);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1401,8 +1517,6 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
|||
params:(NSArray *)params
|
||||
context:(NSNumber *)context
|
||||
{
|
||||
RCTAssertJSThread();
|
||||
|
||||
if (!self.isValid) {
|
||||
return NO;
|
||||
}
|
||||
|
@ -1420,6 +1534,8 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
|||
return NO;
|
||||
}
|
||||
|
||||
RCTProfileBeginEvent();
|
||||
|
||||
RCTModuleMethod *method = methods[methodID];
|
||||
|
||||
// Look up module
|
||||
|
@ -1429,36 +1545,22 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
|||
return NO;
|
||||
}
|
||||
|
||||
RCTProfileBeginFlowEvent();
|
||||
__weak RCTBatchedBridge *weakSelf = self;
|
||||
[self dispatchBlock:^{
|
||||
RCTProfileEndFlowEvent();
|
||||
RCTProfileBeginEvent();
|
||||
RCTBatchedBridge *strongSelf = weakSelf;
|
||||
|
||||
if (!strongSelf.isValid) {
|
||||
// strongSelf has been invalidated since the dispatch_async call and this
|
||||
// invocation should not continue.
|
||||
return;
|
||||
@try {
|
||||
[method invokeWithBridge:self module:module arguments:params context:context];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
RCTLogError(@"Exception thrown while invoking %@ on target %@ with params %@: %@", method.JSMethodName, module, params, exception);
|
||||
if (!RCT_DEBUG && [exception.name rangeOfString:@"Unhandled JS Exception"].location != NSNotFound) {
|
||||
@throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
@try {
|
||||
[method invokeWithBridge:strongSelf module:module arguments:params context:context];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
RCTLogError(@"Exception thrown while invoking %@ on target %@ with params %@: %@", method.JSMethodName, module, params, exception);
|
||||
if (!RCT_DEBUG && [exception.name rangeOfString:@"Unhandled JS Exception"].location != NSNotFound) {
|
||||
@throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
RCTProfileEndEvent(@"Invoke callback", @"objc_call", @{
|
||||
@"module": method.moduleClassName,
|
||||
@"method": method.JSMethodName,
|
||||
@"selector": NSStringFromSelector(method.selector),
|
||||
@"args": RCTJSONStringify(params ?: [NSNull null], NULL),
|
||||
});
|
||||
} forModuleID:@(moduleID)];
|
||||
RCTProfileEndEvent(@"Invoke callback", @"objc_call", @{
|
||||
@"module": method.moduleClassName,
|
||||
@"method": method.JSMethodName,
|
||||
@"selector": NSStringFromSelector(method.selector),
|
||||
@"args": RCTJSONStringify(params ?: [NSNull null], NULL),
|
||||
});
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,20 @@
|
|||
*/
|
||||
typedef void (^RCTResponseSenderBlock)(NSArray *response);
|
||||
|
||||
/**
|
||||
* Block that bridge modules use to resolve the JS promise waiting for a result.
|
||||
* Nil results are supported and are converted to JS's undefined value.
|
||||
*/
|
||||
typedef void (^RCTPromiseResolveBlock)(id result);
|
||||
|
||||
/**
|
||||
* Block that bridge modules use to reject the JS promise waiting for a result.
|
||||
* The error may be nil but it is preferable to pass an NSError object for more
|
||||
* precise error messages.
|
||||
*/
|
||||
typedef void (^RCTPromiseRejectBlock)(NSError *error);
|
||||
|
||||
|
||||
/**
|
||||
* This constant can be returned from +methodQueue to force module
|
||||
* methods to be called on the JavaScript thread. This can have serious
|
||||
|
@ -37,7 +51,7 @@ extern const dispatch_queue_t RCTJSThread;
|
|||
* A reference to the RCTBridge. Useful for modules that require access
|
||||
* to bridge features, such as sending events or making JS calls. This
|
||||
* will be set automatically by the bridge when it initializes the module.
|
||||
* To implement this in your module, just add @synthesize bridge = _bridge;
|
||||
* To implement this in your module, just add @synthesize bridge = _bridge;
|
||||
*/
|
||||
@property (nonatomic, weak) RCTBridge *bridge;
|
||||
|
||||
|
@ -70,6 +84,26 @@ extern const dispatch_queue_t RCTJSThread;
|
|||
* { ... }
|
||||
*
|
||||
* and is exposed to JavaScript as `NativeModules.ModuleName.doSomething`.
|
||||
*
|
||||
* ## Promises
|
||||
*
|
||||
* Bridge modules can also define methods that are exported to JavaScript as
|
||||
* methods that return a Promise, and are compatible with JS async functions.
|
||||
*
|
||||
* Declare the last two parameters of your native method to be a resolver block
|
||||
* and a rejecter block. The resolver block must precede the rejecter block.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* RCT_EXPORT_METHOD(doSomethingAsync:(NSString *)aString
|
||||
* resolver:(RCTPromiseResolveBlock)resolve
|
||||
* rejecter:(RCTPromiseRejectBlock)reject
|
||||
* { ... }
|
||||
*
|
||||
* Calling `NativeModules.ModuleName.doSomethingAsync(aString)` from
|
||||
* JavaScript will return a promise that is resolved or rejected when your
|
||||
* native method implementation calls the respective block.
|
||||
*
|
||||
*/
|
||||
#define RCT_EXPORT_METHOD(method) \
|
||||
RCT_REMAP_METHOD(, method)
|
||||
|
@ -118,7 +152,7 @@ extern const dispatch_queue_t RCTJSThread;
|
|||
RCT_EXTERN_REMAP_MODULE(, objc_name, objc_supername)
|
||||
|
||||
/**
|
||||
* Similar to RCT_EXTERN_MODULE but allows setting a custom JavaScript name
|
||||
* Like RCT_EXTERN_MODULE, but allows setting a custom JavaScript name.
|
||||
*/
|
||||
#define RCT_EXTERN_REMAP_MODULE(js_name, objc_name, objc_supername) \
|
||||
objc_name : objc_supername \
|
||||
|
@ -136,7 +170,7 @@ extern const dispatch_queue_t RCTJSThread;
|
|||
RCT_EXTERN_REMAP_METHOD(, method)
|
||||
|
||||
/**
|
||||
* Similar to RCT_EXTERN_REMAP_METHOD but allows setting a custom JavaScript name
|
||||
* Like RCT_EXTERN_REMAP_METHOD, but allows setting a custom JavaScript name.
|
||||
*/
|
||||
#define RCT_EXTERN_REMAP_METHOD(js_name, method) \
|
||||
- (void)__rct_export__##method { \
|
||||
|
|
|
@ -118,7 +118,8 @@ RCT_CONVERTER(NSString *, NSString, description)
|
|||
|
||||
+ (NSURLRequest *)NSURLRequest:(id)json
|
||||
{
|
||||
return [NSURLRequest requestWithURL:[self NSURL:json]];
|
||||
NSURL *URL = [self NSURL:json];
|
||||
return URL ? [NSURLRequest requestWithURL:URL] : nil;
|
||||
}
|
||||
|
||||
+ (NSDate *)NSDate:(id)json
|
||||
|
|
|
@ -18,6 +18,21 @@
|
|||
#define RCT_EXTERN extern __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Nullability for Xcode 6.2
|
||||
*/
|
||||
#if !__has_feature(nullability)
|
||||
#define NS_ASSUME_NONNULL_BEGIN
|
||||
#define NS_ASSUME_NONNULL_END
|
||||
#define nullable
|
||||
#define nonnull
|
||||
#define null_unspecified
|
||||
#define null_resettable
|
||||
#define __nullable
|
||||
#define __nonnull
|
||||
#define __null_unspecified
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The RCT_DEBUG macro can be used to exclude error checking and logging code
|
||||
* from release builds to improve performance and reduce binary size.
|
||||
|
|
|
@ -72,6 +72,7 @@ static NSNumber *RCTGetEventID(id<RCTEvent> event)
|
|||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
@synthesize paused = _paused;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
|
@ -146,6 +147,7 @@ RCT_IMPORT_METHOD(RCTEventEmitter, receiveEvent);
|
|||
}
|
||||
|
||||
_eventQueue[eventID] = event;
|
||||
_paused = NO;
|
||||
|
||||
[_eventQueueLock unlock];
|
||||
}
|
||||
|
@ -180,6 +182,7 @@ RCT_IMPORT_METHOD(RCTEventEmitter, receiveEvent);
|
|||
[_eventQueueLock lock];
|
||||
eventQueue = _eventQueue;
|
||||
_eventQueue = [[NSMutableDictionary alloc] init];
|
||||
_paused = YES;
|
||||
[_eventQueueLock unlock];
|
||||
|
||||
for (id<RCTEvent> event in eventQueue.allValues) {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
|
||||
#import "RCTBridgeModule.h"
|
||||
#import "RCTInvalidating.h"
|
||||
|
||||
typedef void (^RCTJavaScriptCompleteBlock)(NSError *error);
|
||||
|
@ -20,7 +21,13 @@ typedef void (^RCTJavaScriptCallback)(id json, NSError *error);
|
|||
* Abstracts away a JavaScript execution context - we may be running code in a
|
||||
* web view (for debugging purposes), or may be running code in a `JSContext`.
|
||||
*/
|
||||
@protocol RCTJavaScriptExecutor <RCTInvalidating>
|
||||
@protocol RCTJavaScriptExecutor <RCTInvalidating, RCTBridgeModule>
|
||||
|
||||
/**
|
||||
* Used to set up the executor after the bridge has been fully initialized.
|
||||
* Do any expensive setup in this method instead of `-init`.
|
||||
*/
|
||||
- (void)setUp;
|
||||
|
||||
/**
|
||||
* Executes given method with arguments on JS thread and calls the given callback
|
||||
|
@ -61,14 +68,12 @@ typedef void (^RCTJavaScriptCallback)(id json, NSError *error);
|
|||
@end
|
||||
|
||||
static const char *RCTJavaScriptExecutorID = "RCTJavaScriptExecutorID";
|
||||
__used static id<RCTJavaScriptExecutor> RCTCreateExecutor(Class executorClass)
|
||||
__used static void RCTSetExecutorID(id<RCTJavaScriptExecutor> executor)
|
||||
{
|
||||
static NSUInteger executorID = 0;
|
||||
id<RCTJavaScriptExecutor> executor = [[executorClass alloc] init];
|
||||
if (executor) {
|
||||
objc_setAssociatedObject(executor, RCTJavaScriptExecutorID, @(++executorID), OBJC_ASSOCIATION_RETAIN);
|
||||
}
|
||||
return executor;
|
||||
}
|
||||
|
||||
__used static NSNumber *RCTGetExecutorID(id<RCTJavaScriptExecutor> executor)
|
||||
|
|
|
@ -171,6 +171,9 @@ void _RCTLogFormat(
|
|||
|
||||
// Log to red box
|
||||
if (level >= RCTLOG_REDBOX_LEVEL) {
|
||||
if (level < RCTLOG_FATAL_LEVEL) {
|
||||
[[RCTRedBox sharedInstance] setNextBackgroundColor:[UIColor colorWithRed:0.9 green:0.4 blue:0.2 alpha:1]];
|
||||
}
|
||||
[[RCTRedBox sharedInstance] showErrorMessage:message];
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
- (void)showErrorMessage:(NSString *)message withStack:(NSArray *)stack;
|
||||
- (void)updateErrorMessage:(NSString *)message withStack:(NSArray *)stack;
|
||||
|
||||
- (void)setNextBackgroundColor:(UIColor *)color;
|
||||
|
||||
- (NSString *)currentErrorMessage;
|
||||
|
||||
- (void)dismiss;
|
||||
|
|
|
@ -29,14 +29,15 @@
|
|||
NSArray *_lastStackTrace;
|
||||
|
||||
UITableViewCell *_cachedMessageCell;
|
||||
UIColor *_redColor;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
|
||||
_redColor = [UIColor colorWithRed:0.8 green:0 blue:0 alpha:1];
|
||||
self.windowLevel = UIWindowLevelStatusBar + 5;
|
||||
self.backgroundColor = [UIColor colorWithRed:0.8 green:0 blue:0 alpha:1];
|
||||
self.backgroundColor = _redColor;
|
||||
self.hidden = YES;
|
||||
|
||||
UIViewController *rootController = [[UIViewController alloc] init];
|
||||
|
@ -132,6 +133,7 @@
|
|||
- (void)dismiss
|
||||
{
|
||||
self.hidden = YES;
|
||||
self.backgroundColor = _redColor;
|
||||
[self resignFirstResponder];
|
||||
[[[[UIApplication sharedApplication] delegate] window] makeKeyWindow];
|
||||
}
|
||||
|
@ -261,6 +263,7 @@
|
|||
@implementation RCTRedBox
|
||||
{
|
||||
RCTRedBoxWindow *_window;
|
||||
UIColor *_nextBackgroundColor;
|
||||
}
|
||||
|
||||
+ (instancetype)sharedInstance
|
||||
|
@ -273,6 +276,11 @@
|
|||
return _sharedInstance;
|
||||
}
|
||||
|
||||
- (void)setNextBackgroundColor:(UIColor *)color
|
||||
{
|
||||
_nextBackgroundColor = color;
|
||||
}
|
||||
|
||||
- (void)showErrorMessage:(NSString *)message
|
||||
{
|
||||
[self showErrorMessage:message withStack:nil showIfHidden:YES];
|
||||
|
@ -304,6 +312,10 @@
|
|||
_window = [[RCTRedBoxWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
}
|
||||
[_window showErrorMessage:message withStack:stack showIfHidden:shouldShow];
|
||||
if (_nextBackgroundColor) {
|
||||
_window.backgroundColor = _nextBackgroundColor;
|
||||
_nextBackgroundColor = nil;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -334,6 +346,7 @@
|
|||
- (void)updateErrorMessage:(NSString *)message withStack:(NSArray *)stack {}
|
||||
- (void)showErrorMessage:(NSString *)message withStack:(NSArray *)stack showIfHidden:(BOOL)shouldShow {}
|
||||
- (NSString *)currentErrorMessage { return nil; }
|
||||
- (void)setNextBackgroundColor:(UIColor *)color {}
|
||||
- (void)dismiss {}
|
||||
|
||||
@end
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
* An abstract interface used by request handler modules to send
|
||||
* data back over the bridge back to JS.
|
||||
*/
|
||||
@protocol RCTURLRequestDelegate <NSObject>
|
||||
|
||||
/**
|
||||
* Call this when you first receives a response from the server. This should
|
||||
* include response headers, etc.
|
||||
*/
|
||||
- (void)URLRequest:(id)requestToken didReceiveResponse:(NSURLResponse *)response;
|
||||
|
||||
/**
|
||||
* Call this when you receive data from the server. This can be called multiple
|
||||
* times with partial data chunks, or just once with the full data packet.
|
||||
*/
|
||||
- (void)URLRequest:(id)requestToken didReceiveData:(NSData *)data;
|
||||
|
||||
/**
|
||||
* Call this when the request is complete and/or if an error is encountered.
|
||||
* For a successful request, the error parameter should be nil.
|
||||
*/
|
||||
- (void)URLRequest:(id)requestToken didCompleteWithError:(NSError *)error;
|
||||
|
||||
@end
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import "RCTBridgeModule.h"
|
||||
#import "RCTURLRequestDelegate.h"
|
||||
|
||||
/**
|
||||
* Provides the interface needed to register a request handler. Request handlers
|
||||
* are also bridge modules, so should be registered using RCT_EXPORT_MODULE().
|
||||
*/
|
||||
@protocol RCTURLRequestHandler <RCTBridgeModule>
|
||||
|
||||
/**
|
||||
* Indicates whether this handler is capable of processing the specified
|
||||
* request. Typically the handler would examine the scheme/protocol of the
|
||||
* request URL (and possibly the HTTP method and/or headers) to determine this.
|
||||
*/
|
||||
- (BOOL)canHandleRequest:(NSURLRequest *)request;
|
||||
|
||||
/**
|
||||
* Send a network request and call the delegate with the response data. The
|
||||
* method should return a token, which can be anything, including the request
|
||||
* itself. This will be used later to refer to the request in callbacks. The
|
||||
* `sendRequest:withDelegate:` method *must* return before calling any of the
|
||||
* delegate methods, or the delegate won't recognize the token.
|
||||
*/
|
||||
- (id)sendRequest:(NSURLRequest *)request
|
||||
withDelegate:(id<RCTURLRequestDelegate>)delegate;
|
||||
|
||||
@optional
|
||||
|
||||
/**
|
||||
* Not all request types can be cancelled, but this method can be implemented
|
||||
* for ones that can. It should be used to free up any resources on ongoing
|
||||
* processes associated with the request.
|
||||
*/
|
||||
- (void)cancelRequest:(id)requestToken;
|
||||
|
||||
/**
|
||||
* If more than one RCTURLRequestHandler responds YES to `canHandleRequest:`
|
||||
* then `handlerPriority` is used to determine which one to use. The handler
|
||||
* with the highest priority will be selected. Default priority is zero. If
|
||||
* two or more valid handlers have the same priority, the selection order is
|
||||
* undefined.
|
||||
*/
|
||||
- (float)handlerPriority;
|
||||
|
||||
@end
|
|
@ -57,3 +57,10 @@ RCT_EXTERN BOOL RCTRunningInTestEnvironment(void);
|
|||
|
||||
// Return YES if image has an alpha component
|
||||
RCT_EXTERN BOOL RCTImageHasAlpha(CGImageRef image);
|
||||
|
||||
// Create an NSError in the NCTErrorDomain
|
||||
RCT_EXTERN NSError *RCTErrorWithMessage(NSString *message);
|
||||
|
||||
// Convert nil values to NSNull, and vice-versa
|
||||
RCT_EXTERN id RCTNullIfNil(id value);
|
||||
RCT_EXTERN id RCTNilIfNull(id value);
|
||||
|
|
|
@ -281,3 +281,20 @@ BOOL RCTImageHasAlpha(CGImageRef image)
|
|||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
NSError *RCTErrorWithMessage(NSString *message)
|
||||
{
|
||||
NSDictionary *errorInfo = @{NSLocalizedDescriptionKey: message};
|
||||
NSError *error = [[NSError alloc] initWithDomain:RCTErrorDomain code:0 userInfo:errorInfo];
|
||||
return error;
|
||||
}
|
||||
|
||||
id RCTNullIfNil(id value)
|
||||
{
|
||||
return value ?: (id)kCFNull;
|
||||
}
|
||||
|
||||
id RCTNilIfNull(id value)
|
||||
{
|
||||
return value == (id)kCFNull ? nil : value;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,8 @@
|
|||
NSThread *_javaScriptThread;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
/**
|
||||
* The one tiny pure native hook that we implement is a native logging hook.
|
||||
* You could even argue that this is not necessary - we could plumb logging
|
||||
|
@ -233,37 +235,43 @@ static NSError *RCTNSErrorFromJSError(JSContextRef context, JSValueRef jsError)
|
|||
JSGlobalContextRef ctx;
|
||||
if (context) {
|
||||
ctx = JSGlobalContextRetain(context);
|
||||
} else {
|
||||
JSContextGroupRef group = JSContextGroupCreate();
|
||||
ctx = JSGlobalContextCreateInGroup(group, NULL);
|
||||
#if FB_JSC_HACK
|
||||
JSContextGroupBindToCurrentThread(group);
|
||||
#endif
|
||||
JSContextGroupRelease(group);
|
||||
strongSelf->_context = [[RCTJavaScriptContext alloc] initWithJSContext:ctx];
|
||||
}
|
||||
|
||||
strongSelf->_context = [[RCTJavaScriptContext alloc] initWithJSContext:ctx];
|
||||
[strongSelf _addNativeHook:RCTNativeLoggingHook withName:"nativeLoggingHook"];
|
||||
[strongSelf _addNativeHook:RCTNoop withName:"noop"];
|
||||
|
||||
#if RCT_DEV
|
||||
[strongSelf _addNativeHook:RCTConsoleProfile withName:"consoleProfile"];
|
||||
[strongSelf _addNativeHook:RCTConsoleProfileEnd withName:"consoleProfileEnd"];
|
||||
|
||||
for (NSString *event in @[RCTProfileDidStartProfiling, RCTProfileDidEndProfiling]) {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(toggleProfilingFlag:)
|
||||
name:event
|
||||
object:nil];
|
||||
}
|
||||
#endif
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
__weak RCTContextExecutor *weakSelf = self;
|
||||
[self executeBlockOnJavaScriptQueue:^{
|
||||
RCTContextExecutor *strongSelf = weakSelf;
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
if (!strongSelf->_context) {
|
||||
JSGlobalContextRef ctx = JSGlobalContextCreate(NULL);
|
||||
JSGlobalContextRetain(ctx);
|
||||
strongSelf->_context = [[RCTJavaScriptContext alloc] initWithJSContext:ctx];
|
||||
}
|
||||
[strongSelf _addNativeHook:RCTNativeLoggingHook withName:"nativeLoggingHook"];
|
||||
[strongSelf _addNativeHook:RCTNoop withName:"noop"];
|
||||
#if RCT_DEV
|
||||
[strongSelf _addNativeHook:RCTConsoleProfile withName:"consoleProfile"];
|
||||
[strongSelf _addNativeHook:RCTConsoleProfileEnd withName:"consoleProfileEnd"];
|
||||
|
||||
for (NSString *event in @[RCTProfileDidStartProfiling, RCTProfileDidEndProfiling]) {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(toggleProfilingFlag:)
|
||||
name:event
|
||||
object:nil];
|
||||
}
|
||||
#endif
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)toggleProfilingFlag:(NSNotification *)notification
|
||||
{
|
||||
JSObjectRef globalObject = JSContextGetGlobalObject(_context.ctx);
|
||||
|
|
|
@ -46,16 +46,14 @@ static void RCTReportError(RCTJavaScriptCallback callback, NSString *fmt, ...)
|
|||
NSRegularExpression *_scriptTagsRegex;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
@synthesize valid = _valid;
|
||||
|
||||
- (instancetype)initWithWebView:(UIWebView *)webView
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_objectsToInject = [[NSMutableDictionary alloc] init];
|
||||
_webView = webView ?: [[UIWebView alloc] init];
|
||||
_commentsRegex = [NSRegularExpression regularExpressionWithPattern:@"(^ *?\\/\\/.*?$|\\/\\*\\*[\\s\\S]*?\\*\\/)" options:NSRegularExpressionAnchorsMatchLines error:NULL],
|
||||
_scriptTagsRegex = [NSRegularExpression regularExpressionWithPattern:@"<(\\/?script[^>]*?)>" options:0 error:NULL],
|
||||
_webView.delegate = self;
|
||||
_webView = webView;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -65,6 +63,18 @@ static void RCTReportError(RCTJavaScriptCallback callback, NSString *fmt, ...)
|
|||
return [self initWithWebView:nil];
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
if (!_webView) {
|
||||
_webView = [[UIWebView alloc] init];
|
||||
}
|
||||
|
||||
_objectsToInject = [[NSMutableDictionary alloc] init];
|
||||
_commentsRegex = [NSRegularExpression regularExpressionWithPattern:@"(^ *?\\/\\/.*?$|\\/\\*\\*[\\s\\S]*?\\*\\/)" options:NSRegularExpressionAnchorsMatchLines error:NULL],
|
||||
_scriptTagsRegex = [NSRegularExpression regularExpressionWithPattern:@"<(\\/?script[^>]*?)>" options:0 error:NULL],
|
||||
_webView.delegate = self;
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
_valid = NO;
|
||||
|
|
|
@ -44,7 +44,9 @@ RCT_EXPORT_METHOD(reportSoftException:(NSString *)message
|
|||
[_delegate handleSoftJSExceptionWithMessage:message stack:stack];
|
||||
return;
|
||||
}
|
||||
// JS already logs the error via console.
|
||||
RCTRedBox *box = [RCTRedBox sharedInstance];
|
||||
[box setNextBackgroundColor:[UIColor colorWithRed:0.9 green:0.4 blue:0.2 alpha:1]];
|
||||
[box showErrorMessage:message withStack:stack];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(reportFatalException:(NSString *)message
|
||||
|
|