Updates_for_Mon_July_13th
This commit is contained in:
commit
31b63ade13
|
@ -194,23 +194,46 @@ exports.examples = [
|
|||
'pixels to the tint color.',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<Image
|
||||
source={require('image!uie_thumb_normal')}
|
||||
style={[styles.icon, {tintColor: 'blue' }]}
|
||||
/>
|
||||
<Image
|
||||
source={require('image!uie_thumb_normal')}
|
||||
style={[styles.icon, styles.leftMargin, {tintColor: 'green' }]}
|
||||
/>
|
||||
<Image
|
||||
source={require('image!uie_thumb_normal')}
|
||||
style={[styles.icon, styles.leftMargin, {tintColor: 'red' }]}
|
||||
/>
|
||||
<Image
|
||||
source={require('image!uie_thumb_normal')}
|
||||
style={[styles.icon, styles.leftMargin, {tintColor: 'black' }]}
|
||||
/>
|
||||
<View>
|
||||
<View style={styles.horizontal}>
|
||||
<Image
|
||||
source={require('image!uie_thumb_normal')}
|
||||
style={[styles.icon, {tintColor: '#5ac8fa' }]}
|
||||
/>
|
||||
<Image
|
||||
source={require('image!uie_thumb_normal')}
|
||||
style={[styles.icon, styles.leftMargin, {tintColor: '#4cd964' }]}
|
||||
/>
|
||||
<Image
|
||||
source={require('image!uie_thumb_normal')}
|
||||
style={[styles.icon, styles.leftMargin, {tintColor: '#ff2d55' }]}
|
||||
/>
|
||||
<Image
|
||||
source={require('image!uie_thumb_normal')}
|
||||
style={[styles.icon, styles.leftMargin, {tintColor: '#8e8e93' }]}
|
||||
/>
|
||||
</View>
|
||||
<Text style={styles.sectionText}>
|
||||
It also works with downloaded images:
|
||||
</Text>
|
||||
<View style={styles.horizontal}>
|
||||
<Image
|
||||
source={smallImage}
|
||||
style={[styles.base, {tintColor: '#5ac8fa' }]}
|
||||
/>
|
||||
<Image
|
||||
source={smallImage}
|
||||
style={[styles.base, styles.leftMargin, {tintColor: '#4cd964' }]}
|
||||
/>
|
||||
<Image
|
||||
source={smallImage}
|
||||
style={[styles.base, styles.leftMargin, {tintColor: '#ff2d55' }]}
|
||||
/>
|
||||
<Image
|
||||
source={smallImage}
|
||||
style={[styles.base, styles.leftMargin, {tintColor: '#8e8e93' }]}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
@ -283,6 +306,9 @@ var styles = StyleSheet.create({
|
|||
background: {
|
||||
backgroundColor: '#222222'
|
||||
},
|
||||
sectionText: {
|
||||
marginVertical: 6,
|
||||
},
|
||||
nestedText: {
|
||||
marginLeft: 12,
|
||||
marginTop: 20,
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
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 */; };
|
||||
138D6A171B53CD440074A87E /* RCTCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 138D6A151B53CD440074A87E /* RCTCacheTests.m */; };
|
||||
138D6A181B53CD440074A87E /* RCTShadowViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 138D6A161B53CD440074A87E /* RCTShadowViewTests.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 */; };
|
||||
|
@ -47,6 +49,7 @@
|
|||
14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14DC67F11AB71876001358AB /* libRCTPushNotification.a */; };
|
||||
3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; };
|
||||
834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 834C36D21AF8DA610019C93C /* libRCTSettings.a */; };
|
||||
83636F8F1B53F22C009F943E /* RCTUIManagerScenarioTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */; };
|
||||
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
@ -158,6 +161,8 @@
|
|||
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>"; };
|
||||
138D6A151B53CD440074A87E /* RCTCacheTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTCacheTests.m; sourceTree = "<group>"; };
|
||||
138D6A161B53CD440074A87E /* RCTShadowViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTShadowViewTests.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>"; };
|
||||
|
@ -202,6 +207,7 @@
|
|||
14E0EEC81AB118F7000DECC3 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../../Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = "<group>"; };
|
||||
357858F81B28D2C400341EDB /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = "<group>"; };
|
||||
58005BE41ABA80530062E044 /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = ../../Libraries/RCTTest/RCTTest.xcodeproj; sourceTree = "<group>"; };
|
||||
83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIManagerScenarioTests.m; sourceTree = "<group>"; };
|
||||
D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = ../../Libraries/Vibration/RCTVibration.xcodeproj; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
@ -347,8 +353,10 @@
|
|||
1497CFA71B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m */,
|
||||
1497CFA81B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m */,
|
||||
1497CFA91B21F5E400C1F8F2 /* RCTEventDispatcherTests.m */,
|
||||
138D6A161B53CD440074A87E /* RCTShadowViewTests.m */,
|
||||
1497CFAA1B21F5E400C1F8F2 /* RCTSparseArrayTests.m */,
|
||||
1497CFAB1B21F5E400C1F8F2 /* RCTUIManagerTests.m */,
|
||||
138D6A151B53CD440074A87E /* RCTCacheTests.m */,
|
||||
143BC57E1B21E18100462512 /* Info.plist */,
|
||||
14D6D7101B220EB3001FB087 /* libOCMock.a */,
|
||||
14D6D7011B220AE3001FB087 /* OCMock */,
|
||||
|
@ -383,6 +391,7 @@
|
|||
children = (
|
||||
141FC1201B222EBB004D5FFB /* IntegrationTests.m */,
|
||||
143BC5A01B21E45C00462512 /* UIExplorerSnapshotTests.m */,
|
||||
83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */,
|
||||
143BC5971B21E3E100462512 /* Supporting Files */,
|
||||
);
|
||||
path = UIExplorerIntegrationTests;
|
||||
|
@ -779,7 +788,9 @@
|
|||
1497CFAD1B21F5E400C1F8F2 /* RCTBridgeTests.m in Sources */,
|
||||
1497CFB11B21F5E400C1F8F2 /* RCTEventDispatcherTests.m in Sources */,
|
||||
1497CFB31B21F5E400C1F8F2 /* RCTUIManagerTests.m in Sources */,
|
||||
138D6A171B53CD440074A87E /* RCTCacheTests.m in Sources */,
|
||||
1497CFAC1B21F5E400C1F8F2 /* RCTAllocationTests.m in Sources */,
|
||||
138D6A181B53CD440074A87E /* RCTShadowViewTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -797,6 +808,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
141FC1211B222EBB004D5FFB /* IntegrationTests.m in Sources */,
|
||||
83636F8F1B53F22C009F943E /* RCTUIManagerScenarioTests.m in Sources */,
|
||||
143BC5A11B21E45C00462512 /* UIExplorerSnapshotTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
|
@ -0,0 +1,437 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTShadowView.h"
|
||||
#import "RCTUIManager.h"
|
||||
#import "RCTRootView.h"
|
||||
#import "RCTSparseArray.h"
|
||||
#import "UIView+React.h"
|
||||
|
||||
@interface RCTUIManager (Testing)
|
||||
|
||||
- (void)_manageChildren:(NSNumber *)containerReactTag
|
||||
addChildReactTags:(NSArray *)addChildReactTags
|
||||
addAtIndices:(NSArray *)addAtIndices
|
||||
removeAtIndices:(NSArray *)removeAtIndices
|
||||
registry:(RCTSparseArray *)registry;
|
||||
|
||||
- (void)modifyManageChildren:(NSNumber *)containerReactTag
|
||||
addChildReactTags:(NSMutableArray *)mutableAddChildReactTags
|
||||
addAtIndices:(NSMutableArray *)mutableAddAtIndices
|
||||
removeAtIndices:(NSMutableArray *)mutableRemoveAtIndices;
|
||||
|
||||
- (void)createView:(NSNumber *)reactTag
|
||||
viewName:(NSString *)viewName
|
||||
rootTag:(NSNumber *)rootTag
|
||||
props:(NSDictionary *)props;
|
||||
|
||||
- (void)updateView:(NSNumber *)reactTag
|
||||
viewName:(NSString *)viewName
|
||||
props:(NSDictionary *)props;
|
||||
|
||||
- (void)manageChildren:(NSNumber *)containerReactTag
|
||||
moveFromIndices:(NSArray *)moveFromIndices
|
||||
moveToIndices:(NSArray *)moveToIndices
|
||||
addChildReactTags:(NSArray *)addChildReactTags
|
||||
addAtIndices:(NSArray *)addAtIndices
|
||||
removeAtIndices:(NSArray *)removeAtIndices;
|
||||
|
||||
- (void)flushUIBlocks;
|
||||
|
||||
@property (nonatomic, readonly) RCTSparseArray *viewRegistry;
|
||||
@property (nonatomic, readonly) RCTSparseArray *shadowViewRegistry; // RCT thread only
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTUIManagerScenarioTests : XCTestCase
|
||||
|
||||
@property (nonatomic, readwrite, strong) RCTUIManager *uiManager;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTUIManagerScenarioTests
|
||||
|
||||
- (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;
|
||||
|
||||
RCTShadowView *registeredShadowView = [[RCTShadowView alloc] init];
|
||||
registeredShadowView.viewName = @"RCTView";
|
||||
[registeredShadowView setReactTag:@(i)];
|
||||
_uiManager.shadowViewRegistry[i] = registeredShadowView;
|
||||
}
|
||||
}
|
||||
|
||||
/* +-----------------------------------------------------------+ +----------------------+
|
||||
* | Shadow Hierarchy | | Legend |
|
||||
* +-----------------------------------------------------------+ +----------------------+
|
||||
* | | | |
|
||||
* | +---+ ****** | | ******************** |
|
||||
* | | 1 | * 11 * | | * Layout-only View * |
|
||||
* | +---+ ****** | | ******************** |
|
||||
* | | | | | |
|
||||
* | +-------+---+---+----------+ +---+---+ | | +----+ |
|
||||
* | | | | | | | | | |View| Subview |
|
||||
* | v v v v v v | | +----+ -----------> |
|
||||
* | ***** +---+ ***** +---+ +----+ +----+ | | |
|
||||
* | * 2 * | 3 | * 4 * | 5 | | 12 | | 13 | | +----------------------+
|
||||
* | ***** +---+ ***** +---+ +----+ +----+ |
|
||||
* | | | | |
|
||||
* | +---+--+ | +---+---+ |
|
||||
* | | | | | | |
|
||||
* | v v v v v |
|
||||
* | +---+ +---+ +---+ +---+ ****** |
|
||||
* | | 6 | | 7 | | 8 | | 9 | * 10 * |
|
||||
* | +---+ +---+ +---+ +---+ ****** |
|
||||
* | |
|
||||
* +-----------------------------------------------------------+
|
||||
*
|
||||
* +-----------------------------------------------------------+
|
||||
* | View Hierarchy |
|
||||
* +-----------------------------------------------------------+
|
||||
* | |
|
||||
* | +---+ ****** |
|
||||
* | | 1 | * 11 * |
|
||||
* | +---+ ****** |
|
||||
* | | | |
|
||||
* | +------+------+------+------+ +---+---+ |
|
||||
* | | | | | | | | |
|
||||
* | v v v v v v v |
|
||||
* | +---+ +---+ +---+ +---+ +---+ +----+ +----+ |
|
||||
* | | 6 | | 7 | | 3 | | 8 | | 5 | | 12 | | 13 | |
|
||||
* | +---+ +---+ +---+ +---+ +---+ +----+ +----+ |
|
||||
* | | |
|
||||
* | v |
|
||||
* | +---+ |
|
||||
* | | 9 | |
|
||||
* | +---+ |
|
||||
* | |
|
||||
* +-----------------------------------------------------------+
|
||||
*/
|
||||
|
||||
- (void)updateShadowViewWithReactTag:(NSNumber *)reactTag layoutOnly:(BOOL)isLayoutOnly childTags:(NSArray *)childTags
|
||||
{
|
||||
RCTShadowView *shadowView = _uiManager.shadowViewRegistry[reactTag];
|
||||
shadowView.allProps = isLayoutOnly ? @{} : @{@"collapsible": @NO};
|
||||
[childTags enumerateObjectsUsingBlock:^(NSNumber *childTag, NSUInteger idx, __unused BOOL *stop) {
|
||||
[shadowView insertReactSubview:_uiManager.shadowViewRegistry[childTag] atIndex:idx];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setUpShadowViewHierarchy
|
||||
{
|
||||
[self updateShadowViewWithReactTag:@1 layoutOnly:NO childTags:@[@2, @3, @4, @5]];
|
||||
[self updateShadowViewWithReactTag:@2 layoutOnly:YES childTags:@[@6, @7]];
|
||||
[self updateShadowViewWithReactTag:@3 layoutOnly:NO childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@4 layoutOnly:YES childTags:@[@8]];
|
||||
[self updateShadowViewWithReactTag:@5 layoutOnly:NO childTags:@[@9, @10]];
|
||||
[self updateShadowViewWithReactTag:@6 layoutOnly:NO childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@7 layoutOnly:NO childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@8 layoutOnly:NO childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@9 layoutOnly:NO childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@10 layoutOnly:YES childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@11 layoutOnly:YES childTags:@[@12, @13]];
|
||||
[self updateShadowViewWithReactTag:@12 layoutOnly:NO childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@13 layoutOnly:NO childTags:nil];
|
||||
}
|
||||
|
||||
- (void)testModifyIndices1
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[@2] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[@3] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[@0] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[@6, @7]));
|
||||
XCTAssertEqualObjects(addIndices, (@[@3, @4]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[@0, @1]));
|
||||
}
|
||||
|
||||
- (void)testModifyIndices2
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[@11] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[@4] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[@12, @13]));
|
||||
XCTAssertEqualObjects(addIndices, (@[@5, @6]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[]));
|
||||
}
|
||||
|
||||
- (void)testModifyIndices3
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[@2] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[]));
|
||||
XCTAssertEqualObjects(addIndices, (@[]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[@3]));
|
||||
}
|
||||
|
||||
- (void)testModifyIndices4
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[@11] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[@3] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[@2] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[@12, @13]));
|
||||
XCTAssertEqualObjects(addIndices, (@[@4, @5]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[@3]));
|
||||
}
|
||||
|
||||
- (void)testModifyIndices5
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[@0, @1, @2, @3] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[]));
|
||||
XCTAssertEqualObjects(addIndices, (@[]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[@0, @1, @2, @3, @4]));
|
||||
}
|
||||
|
||||
- (void)testModifyIndices6
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[@11] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[@0] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[@0, @1, @2, @3] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[@12, @13]));
|
||||
XCTAssertEqualObjects(addIndices, (@[@0, @1]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[@0, @1, @2, @3, @4]));
|
||||
}
|
||||
|
||||
- (void)testModifyIndices7
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[@11] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[@1] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[@0, @2, @3] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[@12, @13]));
|
||||
XCTAssertEqualObjects(addIndices, (@[@1, @2]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[@0, @1, @3, @4]));
|
||||
}
|
||||
|
||||
- (void)DISABLED_testScenario1
|
||||
{
|
||||
RCTUIManager *uiManager = [[RCTUIManager alloc] init];
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil moduleProvider:^{ return @[uiManager]; } launchOptions:nil];
|
||||
NS_VALID_UNTIL_END_OF_SCOPE RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"Test"];
|
||||
|
||||
__block BOOL done = NO;
|
||||
|
||||
dispatch_queue_t shadowQueue = [uiManager valueForKey:@"shadowQueue"];
|
||||
dispatch_async(shadowQueue, ^{
|
||||
// Make sure root view finishes loading.
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{});
|
||||
|
||||
/* */[uiManager createView:@2 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}];
|
||||
/* */[uiManager createView:@3 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}];
|
||||
/* V */[uiManager createView:@4 viewName:@"RCTView" rootTag:@1 props:@{@"alignItems":@"center",@"backgroundColor":@"#F5FCFF",@"flex":@1,@"justifyContent":@"center"}];
|
||||
/* V */[uiManager createView:@5 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"blue",@"height":@50,@"width":@50}];
|
||||
/* */[uiManager createView:@6 viewName:@"RCTView" rootTag:@1 props:@{@"width":@250}];
|
||||
/* V */[uiManager createView:@7 viewName:@"RCTView" rootTag:@1 props:@{@"borderWidth":@10,@"margin":@50}];
|
||||
/* V */[uiManager createView:@8 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"yellow",@"height":@50}];
|
||||
/* V */[uiManager createView:@9 viewName:@"RCTText" rootTag:@1 props:@{@"accessible":@1,@"fontSize":@20,@"isHighlighted":@0,@"margin":@10,@"textAlign":@"center"}];
|
||||
/* */[uiManager createView:@10 viewName:@"RCTRawText" rootTag:@1 props:@{@"text":@"This tests removal of layout-only views."}];
|
||||
/* */[uiManager manageChildren:@9 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@10] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* V */[uiManager createView:@12 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"green",@"height":@50}];
|
||||
/* */[uiManager manageChildren:@7 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@8,@9,@12] addAtIndices:@[@0,@1,@2] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@6 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@7] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* V */[uiManager createView:@13 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"red",@"height":@50,@"width":@50}];
|
||||
/* */[uiManager manageChildren:@4 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@5,@6,@13] addAtIndices:@[@0,@1,@2] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@3 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@4] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@2 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@3] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@1 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@2] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
|
||||
[uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) {
|
||||
XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)12);
|
||||
XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)8);
|
||||
done = YES;
|
||||
}];
|
||||
|
||||
[uiManager flushUIBlocks];
|
||||
});
|
||||
|
||||
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:1.0];
|
||||
while ([date timeIntervalSinceNow] > 0 && !done) {
|
||||
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
}
|
||||
|
||||
done = NO;
|
||||
dispatch_async(shadowQueue, ^{
|
||||
[uiManager updateView:@7 viewName:@"RCTView" props:@{@"borderWidth":[NSNull null]}];
|
||||
[uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) {
|
||||
XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)12);
|
||||
XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)7);
|
||||
done = YES;
|
||||
}];
|
||||
|
||||
[uiManager flushUIBlocks];
|
||||
});
|
||||
|
||||
date = [NSDate dateWithTimeIntervalSinceNow:1.0];
|
||||
while ([date timeIntervalSinceNow] > 0 && !done) {
|
||||
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
}
|
||||
|
||||
done = NO;
|
||||
dispatch_async(shadowQueue, ^{
|
||||
[uiManager updateView:@7 viewName:@"RCTView" props:@{@"borderWidth":@10}];
|
||||
[uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) {
|
||||
XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)12);
|
||||
XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)8);
|
||||
done = YES;
|
||||
}];
|
||||
|
||||
[uiManager flushUIBlocks];
|
||||
});
|
||||
|
||||
date = [NSDate dateWithTimeIntervalSinceNow:1.0];
|
||||
while ([date timeIntervalSinceNow] > 0 && !done) {
|
||||
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)DISABLED_testScenario2
|
||||
{
|
||||
RCTUIManager *uiManager = [[RCTUIManager alloc] init];
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil moduleProvider:^{ return @[uiManager]; } launchOptions:nil];
|
||||
NS_VALID_UNTIL_END_OF_SCOPE RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"Test"];
|
||||
|
||||
__block BOOL done = NO;
|
||||
|
||||
dispatch_queue_t shadowQueue = [uiManager valueForKey:@"shadowQueue"];
|
||||
dispatch_async(shadowQueue, ^{
|
||||
// Make sure root view finishes loading.
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{});
|
||||
|
||||
/* */[uiManager createView:@2 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}];
|
||||
/* */[uiManager createView:@3 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}];
|
||||
/* V */[uiManager createView:@4 viewName:@"RCTView" rootTag:@1 props:@{@"alignItems":@"center",@"backgroundColor":@"#F5FCFF",@"flex":@1,@"justifyContent":@"center"}];
|
||||
/* */[uiManager createView:@5 viewName:@"RCTView" rootTag:@1 props:@{@"width":@250}];
|
||||
/* V */[uiManager createView:@6 viewName:@"RCTView" rootTag:@1 props:@{@"borderWidth":@1}];
|
||||
/* V */[uiManager createView:@7 viewName:@"RCTText" rootTag:@1 props:@{@"accessible":@1,@"fontSize":@20,@"isHighlighted":@0,@"margin":@10,@"textAlign":@"center"}];
|
||||
/* */[uiManager createView:@8 viewName:@"RCTRawText" rootTag:@1 props:@{@"text":@"This tests removal of layout-only views."}];
|
||||
/* */[uiManager manageChildren:@7 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@8] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@6 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@7] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@5 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@6] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@4 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@5] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@3 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@4] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@2 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@3] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@1 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@2] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
|
||||
[uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) {
|
||||
XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)8);
|
||||
XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)4);
|
||||
done = YES;
|
||||
}];
|
||||
|
||||
[uiManager flushUIBlocks];
|
||||
});
|
||||
|
||||
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:1.0];
|
||||
while ([date timeIntervalSinceNow] > 0 && !done) {
|
||||
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
}
|
||||
|
||||
done = NO;
|
||||
dispatch_async(shadowQueue, ^{
|
||||
[uiManager updateView:@6 viewName:@"RCTView" props:@{@"borderWidth":[NSNull null]}];
|
||||
[uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) {
|
||||
XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)8);
|
||||
XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)3);
|
||||
done = YES;
|
||||
}];
|
||||
|
||||
[uiManager flushUIBlocks];
|
||||
});
|
||||
|
||||
date = [NSDate dateWithTimeIntervalSinceNow:1.0];
|
||||
while ([date timeIntervalSinceNow] > 0 && !done) {
|
||||
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
}
|
||||
|
||||
done = NO;
|
||||
dispatch_async(shadowQueue, ^{
|
||||
[uiManager updateView:@6 viewName:@"RCTView" props:@{@"borderWidth":@1}];
|
||||
[uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) {
|
||||
XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)8);
|
||||
XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)4);
|
||||
done = YES;
|
||||
}];
|
||||
|
||||
[uiManager flushUIBlocks];
|
||||
});
|
||||
|
||||
date = [NSDate dateWithTimeIntervalSinceNow:1.0];
|
||||
while ([date timeIntervalSinceNow] > 0 && !done) {
|
||||
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,4 +1,16 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import "RCTCache.h"
|
||||
|
||||
// Silence silly sign warnings when using int literals
|
||||
#pragma clang diagnostic ignored "-Wsign-compare"
|
||||
|
||||
@interface RCTCache (Private)
|
||||
|
||||
- (void)cleanUpAllObjects;
|
||||
- (void)resequence;
|
||||
- (NSDictionary *)cache;
|
||||
- (void)setSequenceNumber:(NSInteger)number;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTCacheTests : XCTestCase
|
||||
|
||||
@property (nonatomic, strong) RCTCache *cache;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTCacheTests
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
self.cache = [[RCTCache alloc] init];
|
||||
self.cache.countLimit = 3;
|
||||
self.cache.totalCostLimit = 100;
|
||||
}
|
||||
|
||||
- (void)tearDown
|
||||
{
|
||||
self.cache = nil;
|
||||
}
|
||||
|
||||
- (void)testInsertion
|
||||
{
|
||||
[self.cache setObject:@1 forKey:@"foo" cost:1];
|
||||
[self.cache setObject:@2 forKey:@"bar" cost:2];
|
||||
[self.cache setObject:@3 forKey:@"baz" cost:3];
|
||||
|
||||
XCTAssertEqual([self.cache count], 3);
|
||||
XCTAssertEqual([self.cache totalCost], 6);
|
||||
}
|
||||
|
||||
- (void)testRemoval
|
||||
{
|
||||
[self.cache setObject:@1 forKey:@"foo" cost:1];
|
||||
[self.cache setObject:@2 forKey:@"bar" cost:2];
|
||||
[self.cache setObject:@3 forKey:@"baz" cost:3];
|
||||
|
||||
[self.cache removeObjectForKey:@"bar"];
|
||||
|
||||
XCTAssertEqual([self.cache count], 2);
|
||||
XCTAssertNil([self.cache objectForKey:@"bar"]);
|
||||
}
|
||||
|
||||
- (void)testCountEviction
|
||||
{
|
||||
[self.cache setObject:@1 forKey:@"foo"];
|
||||
[self.cache setObject:@2 forKey:@"bar"];
|
||||
[self.cache setObject:@3 forKey:@"baz"];
|
||||
[self.cache setObject:@4 forKey:@"bam"];
|
||||
|
||||
XCTAssertEqual([self.cache count], 3);
|
||||
XCTAssertNil([self.cache objectForKey:@"foo"]);
|
||||
|
||||
[self.cache setObject:@5 forKey:@"boo"];
|
||||
|
||||
XCTAssertEqual([self.cache count], 3);
|
||||
XCTAssertNil([self.cache objectForKey:@"bar"]);
|
||||
}
|
||||
|
||||
- (void)testCostEviction
|
||||
{
|
||||
[self.cache setObject:@1 forKey:@"foo" cost:99];
|
||||
[self.cache setObject:@2 forKey:@"bar" cost:2];
|
||||
|
||||
XCTAssertEqual([self.cache count], 1);
|
||||
XCTAssertEqual([self.cache totalCost], 2);
|
||||
XCTAssertNil([self.cache objectForKey:@"foo"]);
|
||||
|
||||
[self.cache setObject:@3 forKey:@"baz" cost:999];
|
||||
|
||||
XCTAssertEqual([self.cache count], 0);
|
||||
XCTAssertEqual([self.cache totalCost], 0);
|
||||
}
|
||||
|
||||
- (void)testCleanup
|
||||
{
|
||||
[self.cache setObject:@1 forKey:@"foo"];
|
||||
[self.cache setObject:@2 forKey:@"bar"];
|
||||
[self.cache setObject:@3 forKey:@"baz"];
|
||||
|
||||
//simulate memory warning
|
||||
[self.cache cleanUpAllObjects];
|
||||
|
||||
XCTAssertEqual([self.cache count], 0);
|
||||
XCTAssertEqual([self.cache totalCost], 0);
|
||||
}
|
||||
|
||||
- (void)testResequence
|
||||
{
|
||||
[self.cache setObject:@1 forKey:@"foo"];
|
||||
[self.cache setObject:@2 forKey:@"bar"];
|
||||
[self.cache setObject:@3 forKey:@"baz"];
|
||||
|
||||
[self.cache resequence];
|
||||
|
||||
NSDictionary *innerCache = [self.cache cache];
|
||||
XCTAssertEqualObjects([innerCache[@"foo"] valueForKey:@"sequenceNumber"], @0);
|
||||
XCTAssertEqualObjects([innerCache[@"bar"] valueForKey:@"sequenceNumber"], @1);
|
||||
XCTAssertEqualObjects([innerCache[@"baz"] valueForKey:@"sequenceNumber"], @2);
|
||||
|
||||
[self.cache removeObjectForKey:@"foo"];
|
||||
[self.cache resequence];
|
||||
|
||||
XCTAssertEqualObjects([innerCache[@"bar"] valueForKey:@"sequenceNumber"], @0);
|
||||
XCTAssertEqualObjects([innerCache[@"baz"] valueForKey:@"sequenceNumber"], @1);
|
||||
}
|
||||
|
||||
- (void)testResequenceTrigger
|
||||
{
|
||||
[self.cache setObject:@1 forKey:@"foo"];
|
||||
[self.cache setObject:@2 forKey:@"bar"];
|
||||
|
||||
//first object should now be bar with sequence number of 1
|
||||
[self.cache removeObjectForKey:@"foo"];
|
||||
|
||||
//should trigger resequence
|
||||
[self.cache setSequenceNumber:NSIntegerMax];
|
||||
[self.cache setObject:@3 forKey:@"baz"];
|
||||
|
||||
NSDictionary *innerCache = [self.cache cache];
|
||||
XCTAssertEqualObjects([innerCache[@"bar"] valueForKey:@"sequenceNumber"], @0);
|
||||
XCTAssertEqualObjects([innerCache[@"baz"] valueForKey:@"sequenceNumber"], @1);
|
||||
|
||||
//first object should now be baz with sequence number of 1
|
||||
[self.cache removeObjectForKey:@"bar"];
|
||||
|
||||
//should also trigger resequence
|
||||
[self.cache setSequenceNumber:NSIntegerMax];
|
||||
[self.cache objectForKey:@"baz"];
|
||||
|
||||
XCTAssertEqualObjects([innerCache[@"baz"] valueForKey:@"sequenceNumber"], @0);
|
||||
}
|
||||
|
||||
- (void)testName
|
||||
{
|
||||
self.cache.name = @"Hello";
|
||||
XCTAssertEqualObjects(self.cache.name, @"Hello");
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,4 +1,16 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <mach/mach_time.h>
|
||||
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@interface RCTConvert_NSURLTests : XCTestCase
|
||||
|
||||
|
@ -30,7 +43,7 @@ TEST_PATH(name, _input, [[[NSBundle mainBundle] bundlePath] stringByAppendingPat
|
|||
TEST_URL(basic, @"http://example.com", @"http://example.com")
|
||||
TEST_URL(null, (id)kCFNull, nil)
|
||||
|
||||
// Local files
|
||||
// Resource 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")
|
||||
|
@ -38,6 +51,9 @@ TEST_BUNDLE_PATH(filePathWithEncodedSpaces, @"blah%20blah/hello.jsbundle", @"bla
|
|||
TEST_BUNDLE_PATH(imageAt2XPath, @"images/foo@2x.jpg", @"images/foo@2x.jpg")
|
||||
TEST_BUNDLE_PATH(imageFile, @"foo.jpg", @"foo.jpg")
|
||||
|
||||
// User documents
|
||||
TEST_PATH(documentsFolder, @"~/Documents", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject])
|
||||
|
||||
// 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")
|
||||
|
@ -45,4 +61,12 @@ TEST_URL(urlWithEncodedSpaces, @"http://example.com/blah%20blah/foo", @"http://e
|
|||
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")
|
||||
|
||||
// Data URLs
|
||||
- (void)testDataURL
|
||||
{
|
||||
NSURL *expectedURL = RCTDataURL(@"text/plain", [@"abcde" dataUsingEncoding:NSUTF8StringEncoding]);
|
||||
NSURL *testURL = [NSURL URLWithString:@"data:text/plain;base64,YWJjZGU="];
|
||||
XCTAssertEqualObjects([testURL absoluteString], [expectedURL absoluteString]);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
|
@ -174,7 +186,7 @@
|
|||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont boldSystemFontOfSize:14];
|
||||
UIFont *expected = [UIFont systemFontOfSize:14 weight:UIFontWeightBold];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"foobar", @"fontWeight": @"bold"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
|
@ -16,29 +28,6 @@
|
|||
removeAtIndices:(NSArray *)removeAtIndices
|
||||
registry:(RCTSparseArray *)registry;
|
||||
|
||||
- (void)modifyManageChildren:(NSNumber *)containerReactTag
|
||||
addChildReactTags:(NSMutableArray *)mutableAddChildReactTags
|
||||
addAtIndices:(NSMutableArray *)mutableAddAtIndices
|
||||
removeAtIndices:(NSMutableArray *)mutableRemoveAtIndices;
|
||||
|
||||
- (void)createView:(NSNumber *)reactTag
|
||||
viewName:(NSString *)viewName
|
||||
rootTag:(NSNumber *)rootTag
|
||||
props:(NSDictionary *)props;
|
||||
|
||||
- (void)updateView:(NSNumber *)reactTag
|
||||
viewName:(NSString *)viewName
|
||||
props:(NSDictionary *)props;
|
||||
|
||||
- (void)manageChildren:(NSNumber *)containerReactTag
|
||||
moveFromIndices:(NSArray *)moveFromIndices
|
||||
moveToIndices:(NSArray *)moveToIndices
|
||||
addChildReactTags:(NSArray *)addChildReactTags
|
||||
addAtIndices:(NSArray *)addAtIndices
|
||||
removeAtIndices:(NSArray *)removeAtIndices;
|
||||
|
||||
- (void)flushUIBlocks;
|
||||
|
||||
@property (nonatomic, readonly) RCTSparseArray *viewRegistry;
|
||||
@property (nonatomic, readonly) RCTSparseArray *shadowViewRegistry; // RCT thread only
|
||||
|
||||
|
@ -197,329 +186,4 @@
|
|||
}
|
||||
}
|
||||
|
||||
/* +-----------------------------------------------------------+ +----------------------+
|
||||
* | Shadow Hierarchy | | Legend |
|
||||
* +-----------------------------------------------------------+ +----------------------+
|
||||
* | | | |
|
||||
* | +---+ ****** | | ******************** |
|
||||
* | | 1 | * 11 * | | * Layout-only View * |
|
||||
* | +---+ ****** | | ******************** |
|
||||
* | | | | | |
|
||||
* | +-------+---+---+----------+ +---+---+ | | +----+ |
|
||||
* | | | | | | | | | |View| Subview |
|
||||
* | v v v v v v | | +----+ -----------> |
|
||||
* | ***** +---+ ***** +---+ +----+ +----+ | | |
|
||||
* | * 2 * | 3 | * 4 * | 5 | | 12 | | 13 | | +----------------------+
|
||||
* | ***** +---+ ***** +---+ +----+ +----+ |
|
||||
* | | | | |
|
||||
* | +---+--+ | +---+---+ |
|
||||
* | | | | | | |
|
||||
* | v v v v v |
|
||||
* | +---+ +---+ +---+ +---+ ****** |
|
||||
* | | 6 | | 7 | | 8 | | 9 | * 10 * |
|
||||
* | +---+ +---+ +---+ +---+ ****** |
|
||||
* | |
|
||||
* +-----------------------------------------------------------+
|
||||
*
|
||||
* +-----------------------------------------------------------+
|
||||
* | View Hierarchy |
|
||||
* +-----------------------------------------------------------+
|
||||
* | |
|
||||
* | +---+ ****** |
|
||||
* | | 1 | * 11 * |
|
||||
* | +---+ ****** |
|
||||
* | | | |
|
||||
* | +------+------+------+------+ +---+---+ |
|
||||
* | | | | | | | | |
|
||||
* | v v v v v v v |
|
||||
* | +---+ +---+ +---+ +---+ +---+ +----+ +----+ |
|
||||
* | | 6 | | 7 | | 3 | | 8 | | 5 | | 12 | | 13 | |
|
||||
* | +---+ +---+ +---+ +---+ +---+ +----+ +----+ |
|
||||
* | | |
|
||||
* | v |
|
||||
* | +---+ |
|
||||
* | | 9 | |
|
||||
* | +---+ |
|
||||
* | |
|
||||
* +-----------------------------------------------------------+
|
||||
*/
|
||||
|
||||
- (void)updateShadowViewWithReactTag:(NSNumber *)reactTag layoutOnly:(BOOL)isLayoutOnly childTags:(NSArray *)childTags
|
||||
{
|
||||
RCTShadowView *shadowView = _uiManager.shadowViewRegistry[reactTag];
|
||||
shadowView.allProps = isLayoutOnly ? @{} : @{@"collapsible": @NO};
|
||||
[childTags enumerateObjectsUsingBlock:^(NSNumber *childTag, NSUInteger idx, __unused BOOL *stop) {
|
||||
[shadowView insertReactSubview:_uiManager.shadowViewRegistry[childTag] atIndex:idx];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setUpShadowViewHierarchy
|
||||
{
|
||||
[self updateShadowViewWithReactTag:@1 layoutOnly:NO childTags:@[@2, @3, @4, @5]];
|
||||
[self updateShadowViewWithReactTag:@2 layoutOnly:YES childTags:@[@6, @7]];
|
||||
[self updateShadowViewWithReactTag:@3 layoutOnly:NO childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@4 layoutOnly:YES childTags:@[@8]];
|
||||
[self updateShadowViewWithReactTag:@5 layoutOnly:NO childTags:@[@9, @10]];
|
||||
[self updateShadowViewWithReactTag:@6 layoutOnly:NO childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@7 layoutOnly:NO childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@8 layoutOnly:NO childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@9 layoutOnly:NO childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@10 layoutOnly:YES childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@11 layoutOnly:YES childTags:@[@12, @13]];
|
||||
[self updateShadowViewWithReactTag:@12 layoutOnly:NO childTags:nil];
|
||||
[self updateShadowViewWithReactTag:@13 layoutOnly:NO childTags:nil];
|
||||
}
|
||||
|
||||
- (void)testModifyIndices1
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[@2] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[@3] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[@0] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[@6, @7]));
|
||||
XCTAssertEqualObjects(addIndices, (@[@3, @4]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[@0, @1]));
|
||||
}
|
||||
|
||||
- (void)testModifyIndices2
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[@11] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[@4] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[@12, @13]));
|
||||
XCTAssertEqualObjects(addIndices, (@[@5, @6]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[]));
|
||||
}
|
||||
|
||||
- (void)testModifyIndices3
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[@2] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[]));
|
||||
XCTAssertEqualObjects(addIndices, (@[]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[@3]));
|
||||
}
|
||||
|
||||
- (void)testModifyIndices4
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[@11] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[@3] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[@2] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[@12, @13]));
|
||||
XCTAssertEqualObjects(addIndices, (@[@4, @5]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[@3]));
|
||||
}
|
||||
|
||||
- (void)testModifyIndices5
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[@0, @1, @2, @3] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[]));
|
||||
XCTAssertEqualObjects(addIndices, (@[]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[@0, @1, @2, @3, @4]));
|
||||
}
|
||||
|
||||
- (void)testModifyIndices6
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[@11] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[@0] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[@0, @1, @2, @3] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[@12, @13]));
|
||||
XCTAssertEqualObjects(addIndices, (@[@0, @1]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[@0, @1, @2, @3, @4]));
|
||||
}
|
||||
|
||||
- (void)testModifyIndices7
|
||||
{
|
||||
[self setUpShadowViewHierarchy];
|
||||
|
||||
NSMutableArray *addTags = [@[@11] mutableCopy];
|
||||
NSMutableArray *addIndices = [@[@1] mutableCopy];
|
||||
NSMutableArray *removeIndices = [@[@0, @2, @3] mutableCopy];
|
||||
[self.uiManager modifyManageChildren:@1
|
||||
addChildReactTags:addTags
|
||||
addAtIndices:addIndices
|
||||
removeAtIndices:removeIndices];
|
||||
XCTAssertEqualObjects(addTags, (@[@12, @13]));
|
||||
XCTAssertEqualObjects(addIndices, (@[@1, @2]));
|
||||
XCTAssertEqualObjects(removeIndices, (@[@0, @1, @3, @4]));
|
||||
}
|
||||
|
||||
- (void)DISABLED_testScenario1 // t7660646
|
||||
{
|
||||
RCTUIManager *uiManager = [[RCTUIManager alloc] init];
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil moduleProvider:^{ return @[uiManager]; } launchOptions:nil];
|
||||
NS_VALID_UNTIL_END_OF_SCOPE RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"Test"];
|
||||
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@""];
|
||||
|
||||
dispatch_queue_t shadowQueue = [uiManager valueForKey:@"shadowQueue"];
|
||||
dispatch_async(shadowQueue, ^{
|
||||
// Make sure root view finishes loading.
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{});
|
||||
|
||||
/* */[uiManager createView:@2 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}];
|
||||
/* */[uiManager createView:@3 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}];
|
||||
/* V */[uiManager createView:@4 viewName:@"RCTView" rootTag:@1 props:@{@"alignItems":@"center",@"backgroundColor":@"#F5FCFF",@"flex":@1,@"justifyContent":@"center"}];
|
||||
/* V */[uiManager createView:@5 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"blue",@"height":@50,@"width":@50}];
|
||||
/* */[uiManager createView:@6 viewName:@"RCTView" rootTag:@1 props:@{@"width":@250}];
|
||||
/* V */[uiManager createView:@7 viewName:@"RCTView" rootTag:@1 props:@{@"borderWidth":@10,@"margin":@50}];
|
||||
/* V */[uiManager createView:@8 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"yellow",@"height":@50}];
|
||||
/* V */[uiManager createView:@9 viewName:@"RCTText" rootTag:@1 props:@{@"accessible":@1,@"fontSize":@20,@"isHighlighted":@0,@"margin":@10,@"textAlign":@"center"}];
|
||||
/* */[uiManager createView:@10 viewName:@"RCTRawText" rootTag:@1 props:@{@"text":@"This tests removal of layout-only views."}];
|
||||
/* */[uiManager manageChildren:@9 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@10] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* V */[uiManager createView:@12 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"green",@"height":@50}];
|
||||
/* */[uiManager manageChildren:@7 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@8,@9,@12] addAtIndices:@[@0,@1,@2] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@6 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@7] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* V */[uiManager createView:@13 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"red",@"height":@50,@"width":@50}];
|
||||
/* */[uiManager manageChildren:@4 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@5,@6,@13] addAtIndices:@[@0,@1,@2] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@3 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@4] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@2 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@3] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@1 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@2] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
|
||||
[uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) {
|
||||
XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)12);
|
||||
XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)8);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[uiManager flushUIBlocks];
|
||||
});
|
||||
|
||||
[self waitForExpectationsWithTimeout:1 handler:nil];
|
||||
|
||||
expectation = [self expectationWithDescription:@""];
|
||||
dispatch_async(shadowQueue, ^{
|
||||
[uiManager updateView:@7 viewName:@"RCTView" props:@{@"borderWidth":[NSNull null]}];
|
||||
[uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) {
|
||||
XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)12);
|
||||
XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)7);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[uiManager flushUIBlocks];
|
||||
});
|
||||
|
||||
[self waitForExpectationsWithTimeout:1 handler:nil];
|
||||
|
||||
expectation = [self expectationWithDescription:@""];
|
||||
dispatch_async(shadowQueue, ^{
|
||||
[uiManager updateView:@7 viewName:@"RCTView" props:@{@"borderWidth":@10}];
|
||||
[uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) {
|
||||
XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)12);
|
||||
XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)8);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[uiManager flushUIBlocks];
|
||||
});
|
||||
|
||||
[self waitForExpectationsWithTimeout:1 handler:nil];
|
||||
}
|
||||
|
||||
- (void)DISABLED_testScenario2 // t7660646
|
||||
{
|
||||
RCTUIManager *uiManager = [[RCTUIManager alloc] init];
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil moduleProvider:^{ return @[uiManager]; } launchOptions:nil];
|
||||
NS_VALID_UNTIL_END_OF_SCOPE RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"Test"];
|
||||
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@""];
|
||||
|
||||
dispatch_queue_t shadowQueue = [uiManager valueForKey:@"shadowQueue"];
|
||||
dispatch_async(shadowQueue, ^{
|
||||
// Make sure root view finishes loading.
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{});
|
||||
|
||||
/* */[uiManager createView:@2 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}];
|
||||
/* */[uiManager createView:@3 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}];
|
||||
/* V */[uiManager createView:@4 viewName:@"RCTView" rootTag:@1 props:@{@"alignItems":@"center",@"backgroundColor":@"#F5FCFF",@"flex":@1,@"justifyContent":@"center"}];
|
||||
/* */[uiManager createView:@5 viewName:@"RCTView" rootTag:@1 props:@{@"width":@250}];
|
||||
/* V */[uiManager createView:@6 viewName:@"RCTView" rootTag:@1 props:@{@"borderWidth":@1}];
|
||||
/* V */[uiManager createView:@7 viewName:@"RCTText" rootTag:@1 props:@{@"accessible":@1,@"fontSize":@20,@"isHighlighted":@0,@"margin":@10,@"textAlign":@"center"}];
|
||||
/* */[uiManager createView:@8 viewName:@"RCTRawText" rootTag:@1 props:@{@"text":@"This tests removal of layout-only views."}];
|
||||
/* */[uiManager manageChildren:@7 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@8] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@6 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@7] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@5 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@6] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@4 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@5] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@3 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@4] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@2 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@3] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
/* */[uiManager manageChildren:@1 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@2] addAtIndices:@[@0] removeAtIndices:nil];
|
||||
|
||||
[uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) {
|
||||
XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)8);
|
||||
XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)4);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[uiManager flushUIBlocks];
|
||||
});
|
||||
|
||||
[self waitForExpectationsWithTimeout:1 handler:nil];
|
||||
|
||||
expectation = [self expectationWithDescription:@""];
|
||||
dispatch_async(shadowQueue, ^{
|
||||
[uiManager updateView:@6 viewName:@"RCTView" props:@{@"borderWidth":[NSNull null]}];
|
||||
[uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) {
|
||||
XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)8);
|
||||
XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)3);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[uiManager flushUIBlocks];
|
||||
});
|
||||
|
||||
[self waitForExpectationsWithTimeout:1 handler:nil];
|
||||
|
||||
expectation = [self expectationWithDescription:@""];
|
||||
dispatch_async(shadowQueue, ^{
|
||||
[uiManager updateView:@6 viewName:@"RCTView" props:@{@"borderWidth":@1}];
|
||||
[uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) {
|
||||
XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)8);
|
||||
XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)4);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[uiManager flushUIBlocks];
|
||||
});
|
||||
|
||||
[self waitForExpectationsWithTimeout:1 handler:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -36,7 +36,8 @@ var WebView = React.createClass({
|
|||
propTypes: {
|
||||
renderError: PropTypes.func, // view to show if there's an error
|
||||
renderLoading: PropTypes.func, // loading indicator to show
|
||||
url: PropTypes.string.isRequired,
|
||||
url: PropTypes.string,
|
||||
html: PropTypes.string,
|
||||
automaticallyAdjustContentInsets: PropTypes.bool,
|
||||
contentInset: EdgeInsetsPropType,
|
||||
onNavigationStateChange: PropTypes.func,
|
||||
|
@ -102,6 +103,7 @@ var WebView = React.createClass({
|
|||
key="webViewKey"
|
||||
style={webViewStyles}
|
||||
url={this.props.url}
|
||||
html={this.props.html}
|
||||
injectedJavaScript={this.props.injectedJavaScript}
|
||||
userAgent={this.props.userAgent}
|
||||
javaScriptEnabledAndroid={this.props.javaScriptEnabledAndroid}
|
||||
|
@ -183,6 +185,7 @@ var WebView = React.createClass({
|
|||
|
||||
var RCTWebView = createReactNativeComponentClass({
|
||||
validAttributes: merge(ReactNativeViewAttributes.UIView, {
|
||||
html: true,
|
||||
injectedJavaScript: true,
|
||||
javaScriptEnabledAndroid: true,
|
||||
url: true,
|
||||
|
|
|
@ -221,7 +221,9 @@ var ListView = React.createClass({
|
|||
* such as scrollTo.
|
||||
*/
|
||||
getScrollResponder: function() {
|
||||
return this.refs[SCROLLVIEW_REF];
|
||||
return this.refs[SCROLLVIEW_REF] &&
|
||||
this.refs[SCROLLVIEW_REF].getScrollResponder &&
|
||||
this.refs[SCROLLVIEW_REF].getScrollResponder();
|
||||
},
|
||||
|
||||
setNativeProps: function(props) {
|
||||
|
@ -399,14 +401,18 @@ var ListView = React.createClass({
|
|||
*/
|
||||
|
||||
_measureAndUpdateScrollProps: function() {
|
||||
var scrollComponent = this.getScrollResponder();
|
||||
if (!scrollComponent || !scrollComponent.getInnerViewNode) {
|
||||
return;
|
||||
}
|
||||
RCTUIManager.measureLayout(
|
||||
this.refs[SCROLLVIEW_REF].getInnerViewNode(),
|
||||
React.findNodeHandle(this.refs[SCROLLVIEW_REF]),
|
||||
scrollComponent.getInnerViewNode(),
|
||||
React.findNodeHandle(scrollComponent),
|
||||
logError,
|
||||
this._setScrollContentHeight
|
||||
);
|
||||
RCTUIManager.measureLayoutRelativeToParent(
|
||||
React.findNodeHandle(this.refs[SCROLLVIEW_REF]),
|
||||
React.findNodeHandle(scrollComponent),
|
||||
logError,
|
||||
this._setScrollVisibleHeight
|
||||
);
|
||||
|
@ -414,7 +420,7 @@ var ListView = React.createClass({
|
|||
// RKScrollViewManager.calculateChildFrames not available on every platform
|
||||
RKScrollViewManager && RKScrollViewManager.calculateChildFrames &&
|
||||
RKScrollViewManager.calculateChildFrames(
|
||||
React.findNodeHandle(this.refs[SCROLLVIEW_REF]),
|
||||
React.findNodeHandle(scrollComponent),
|
||||
this._updateChildFrames,
|
||||
);
|
||||
},
|
||||
|
|
|
@ -62,7 +62,7 @@ static void *const RCTDownloadTaskWrapperProgressBlockKey = (void *)&RCTDownload
|
|||
|
||||
- (NSURLSessionDownloadTask *)downloadData:(NSURL *)url progressBlock:(RCTDataProgressBlock)progressBlock completionBlock:(RCTDataCompletionBlock)completionBlock
|
||||
{
|
||||
NSURLSessionDownloadTask *task = [_URLSession downloadTaskWithURL:url completionHandler:nil];
|
||||
NSURLSessionDownloadTask *task = [_URLSession downloadTaskWithURL:url];
|
||||
task.rct_completionBlock = completionBlock;
|
||||
task.rct_progressBlock = progressBlock;
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ typedef void (^RCTImageDownloadCancellationBlock)(void);
|
|||
size:(CGSize)size
|
||||
scale:(CGFloat)scale
|
||||
resizeMode:(UIViewContentMode)resizeMode
|
||||
tintColor:(UIColor *)tintColor
|
||||
backgroundColor:(UIColor *)backgroundColor
|
||||
progressBlock:(RCTDataProgressBlock)progressBlock
|
||||
block:(RCTImageDownloadBlock)block;
|
||||
|
|
|
@ -105,16 +105,15 @@ CGRect RCTClipRect(CGSize, CGFloat, CGSize, CGFloat, UIViewContentMode);
|
|||
}];
|
||||
|
||||
NSCachedURLResponse *cachedResponse = [_cache cachedResponseForRequest:request];
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cachedResponse) {
|
||||
runBlocks(YES, cachedResponse.data, nil);
|
||||
} else {
|
||||
[task resume];
|
||||
}
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cachedResponse) {
|
||||
runBlocks(YES, cachedResponse.data, nil);
|
||||
} else {
|
||||
[task resume];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -132,6 +131,7 @@ CGRect RCTClipRect(CGSize, CGFloat, CGSize, CGFloat, UIViewContentMode);
|
|||
size:(CGSize)size
|
||||
scale:(CGFloat)scale
|
||||
resizeMode:(UIViewContentMode)resizeMode
|
||||
tintColor:(UIColor *)tintColor
|
||||
backgroundColor:(UIColor *)backgroundColor
|
||||
progressBlock:(RCTDataProgressBlock)progressBlock
|
||||
block:(RCTImageDownloadBlock)block
|
||||
|
@ -174,6 +174,10 @@ CGRect RCTClipRect(CGSize, CGFloat, CGSize, CGFloat, UIViewContentMode);
|
|||
[blendColor setFill];
|
||||
UIRectFill((CGRect){CGPointZero, destSize});
|
||||
}
|
||||
if (tintColor) {
|
||||
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
||||
[tintColor setFill];
|
||||
}
|
||||
[image drawInRect:imageRect];
|
||||
image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
|
|
@ -28,6 +28,11 @@
|
|||
*/
|
||||
@property (nonatomic, strong) NSURL *imageURL;
|
||||
|
||||
/**
|
||||
* Whether the image should be masked with this view's tint color.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL tinted;
|
||||
|
||||
/**
|
||||
* By default, changing imageURL will reset whatever existing image was present
|
||||
* and revert to defaultImage while the new image loads. In certain obscure cases you
|
||||
|
|
|
@ -60,6 +60,12 @@ RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder)
|
|||
[self _updateImage];
|
||||
}
|
||||
|
||||
- (void)setTintColor:(UIColor *)tintColor
|
||||
{
|
||||
super.tintColor = tintColor;
|
||||
[self _updateImage];
|
||||
}
|
||||
|
||||
- (void)setProgressHandlerRegistered:(BOOL)progressHandlerRegistered
|
||||
{
|
||||
_progressHandlerRegistered = progressHandlerRegistered;
|
||||
|
@ -144,9 +150,14 @@ RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder)
|
|||
}
|
||||
}];
|
||||
} else {
|
||||
_downloadToken = [_imageDownloader downloadImageForURL:imageURL size:self.bounds.size scale:RCTScreenScale()
|
||||
resizeMode:self.contentMode backgroundColor:self.backgroundColor
|
||||
progressBlock:progressHandler block:^(UIImage *image, NSError *error) {
|
||||
_downloadToken = [_imageDownloader downloadImageForURL:imageURL
|
||||
size:self.bounds.size
|
||||
scale:RCTScreenScale()
|
||||
resizeMode:self.contentMode
|
||||
tintColor:_tinted ? self.tintColor : nil
|
||||
backgroundColor:self.backgroundColor
|
||||
progressBlock:progressHandler
|
||||
block:^(UIImage *image, NSError *error) {
|
||||
if (image) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (imageURL != self.imageURL) {
|
||||
|
|
|
@ -31,6 +31,16 @@ RCT_REMAP_VIEW_PROPERTY(defaultImageSrc, defaultImage, UIImage)
|
|||
RCT_REMAP_VIEW_PROPERTY(src, imageURL, NSURL)
|
||||
RCT_REMAP_VIEW_PROPERTY(resizeMode, contentMode, UIViewContentMode)
|
||||
RCT_EXPORT_VIEW_PROPERTY(progressHandlerRegistered, BOOL)
|
||||
RCT_CUSTOM_VIEW_PROPERTY(tintColor, UIColor, RCTNetworkImageView)
|
||||
{
|
||||
if (json) {
|
||||
view.tinted = YES;
|
||||
view.tintColor = [RCTConvert UIColor:json];
|
||||
} else {
|
||||
view.tinted = defaultView.tinted;
|
||||
view.tintColor = defaultView.tintColor;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary *)customDirectEventTypes
|
||||
{
|
||||
|
|
|
@ -122,10 +122,6 @@ class MessageQueue {
|
|||
(this._debugInfo[this._callbackID >> 5] = null);
|
||||
|
||||
this._debugInfo[this._callbackID >> 1] = [module, method];
|
||||
if (SPY_MODE && isFinite(module)) {
|
||||
console.log('JS->N : ' + this._remoteModuleTable[module] + '.' +
|
||||
this._remoteMethodTable[module][method] + '(' + JSON.stringify(params) + ')');
|
||||
}
|
||||
}
|
||||
onFail && params.push(this._callbackID);
|
||||
this._callbacks[this._callbackID++] = onFail;
|
||||
|
@ -135,6 +131,10 @@ class MessageQueue {
|
|||
this._queue[MODULE_IDS].push(module);
|
||||
this._queue[METHOD_IDS].push(method);
|
||||
this._queue[PARAMS].push(params);
|
||||
if (__DEV__ && SPY_MODE && isFinite(module)) {
|
||||
console.log('JS->N : ' + this._remoteModuleTable[module] + '.' +
|
||||
this._remoteMethodTable[module][method] + '(' + JSON.stringify(params) + ')');
|
||||
}
|
||||
}
|
||||
|
||||
__callFunction(module, method, args) {
|
||||
|
@ -157,8 +157,8 @@ class MessageQueue {
|
|||
let callback = this._callbacks[cbID];
|
||||
if (__DEV__) {
|
||||
let debug = this._debugInfo[cbID >> 1];
|
||||
let module = this._remoteModuleTable[debug[0]];
|
||||
let method = this._remoteMethodTable[debug[0]][debug[1]];
|
||||
let module = debug && this._remoteModuleTable[debug[0]];
|
||||
let method = debug && this._remoteMethodTable[debug[0]][debug[1]];
|
||||
if (!callback) {
|
||||
console.error(`Callback with id ${cbID}: ${module}.${method}() not found`);
|
||||
} else if (SPY_MODE) {
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* 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>
|
||||
|
||||
/**
|
||||
* RCTCache is a simple LRU cache implementation, based on the API of NSCache,
|
||||
* but with known, deterministic behavior. The cache will always remove items
|
||||
* outside of the specified cost/count limits, and will be automatically
|
||||
* cleared in the event of a memory warning.
|
||||
*/
|
||||
@interface RCTCache : NSCache
|
||||
|
||||
/**
|
||||
* The total number of objects currently resident in the cache.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger count;
|
||||
|
||||
/**
|
||||
* The total cost of the objects currently resident in the cache.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger totalCost;
|
||||
|
||||
/**
|
||||
* Subscripting support
|
||||
*/
|
||||
- (id)objectForKeyedSubscript:(id<NSCopying>)key;
|
||||
- (void)setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key;
|
||||
|
||||
@end
|
||||
|
||||
@protocol RCTCacheDelegate <NSCacheDelegate>
|
||||
@optional
|
||||
|
||||
/**
|
||||
* Should the specified object be evicted from the cache?
|
||||
*/
|
||||
- (BOOL)cache:(RCTCache *)cache shouldEvictObject:(id)entry;
|
||||
|
||||
/**
|
||||
* The specified object is about to be evicted from the cache.
|
||||
*/
|
||||
- (void)cache:(RCTCache *)cache willEvictObject:(id)entry;
|
||||
|
||||
@end
|
|
@ -0,0 +1,326 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Adapted from https://github.com/nicklockwood/OSCache
|
||||
|
||||
#import "RCTCache.h"
|
||||
|
||||
#import "RCTAssert.h"
|
||||
|
||||
#import <TargetConditionals.h>
|
||||
#if TARGET_OS_IPHONE
|
||||
#import <UIKit/UIKit.h>
|
||||
#endif
|
||||
|
||||
@interface RCTCacheEntry : NSObject
|
||||
|
||||
@property (nonatomic, strong) NSObject *object;
|
||||
@property (nonatomic, assign) NSUInteger cost;
|
||||
@property (nonatomic, assign) NSInteger sequenceNumber;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTCacheEntry
|
||||
|
||||
+ (instancetype)entryWithObject:(id)object cost:(NSUInteger)cost sequenceNumber:(NSInteger)sequenceNumber
|
||||
{
|
||||
RCTCacheEntry *entry = [[self alloc] init];
|
||||
entry.object = object;
|
||||
entry.cost = cost;
|
||||
entry.sequenceNumber = sequenceNumber;
|
||||
return entry;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTCache_Private : NSObject
|
||||
|
||||
@property (nonatomic, unsafe_unretained) id<RCTCacheDelegate> delegate;
|
||||
@property (nonatomic, assign) NSUInteger countLimit;
|
||||
@property (nonatomic, assign) NSUInteger totalCostLimit;
|
||||
@property (nonatomic, copy) NSString *name;
|
||||
|
||||
@property (nonatomic, assign) NSUInteger totalCost;
|
||||
@property (nonatomic, strong) NSMutableDictionary *cache;
|
||||
@property (nonatomic, assign) BOOL delegateRespondsToWillEvictObject;
|
||||
@property (nonatomic, assign) BOOL delegateRespondsToShouldEvictObject;
|
||||
@property (nonatomic, assign) BOOL currentlyCleaning;
|
||||
@property (nonatomic, assign) NSInteger sequenceNumber;
|
||||
@property (nonatomic, strong) NSLock *lock;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTCache_Private
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
//create storage
|
||||
_cache = [[NSMutableDictionary alloc] init];
|
||||
_lock = [[NSLock alloc] init];
|
||||
_totalCost = 0;
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
//clean up in the event of a memory warning
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cleanUpAllObjects) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)setDelegate:(id<RCTCacheDelegate>)delegate
|
||||
{
|
||||
_delegate = delegate;
|
||||
_delegateRespondsToShouldEvictObject = [delegate respondsToSelector:@selector(cache:shouldEvictObject:)];
|
||||
_delegateRespondsToWillEvictObject = [delegate respondsToSelector:@selector(cache:willEvictObject:)];
|
||||
}
|
||||
|
||||
- (void)setCountLimit:(NSUInteger)countLimit
|
||||
{
|
||||
[_lock lock];
|
||||
_countLimit = countLimit;
|
||||
[_lock unlock];
|
||||
[self cleanUp];
|
||||
}
|
||||
|
||||
- (void)setTotalCostLimit:(NSUInteger)totalCostLimit
|
||||
{
|
||||
[_lock lock];
|
||||
_totalCostLimit = totalCostLimit;
|
||||
[_lock unlock];
|
||||
[self cleanUp];
|
||||
}
|
||||
|
||||
- (NSUInteger)count
|
||||
{
|
||||
return [_cache count];
|
||||
}
|
||||
|
||||
- (void)cleanUp
|
||||
{
|
||||
[_lock lock];
|
||||
NSUInteger maxCount = [self countLimit] ?: INT_MAX;
|
||||
NSUInteger maxCost = [self totalCostLimit] ?: INT_MAX;
|
||||
NSUInteger totalCount = [_cache count];
|
||||
if (totalCount > maxCount || _totalCost > maxCost)
|
||||
{
|
||||
//sort, oldest first
|
||||
NSArray *keys = [[_cache allKeys] sortedArrayUsingComparator:^NSComparisonResult(id key1, id key2) {
|
||||
RCTCacheEntry *entry1 = self.cache[key1];
|
||||
RCTCacheEntry *entry2 = self.cache[key2];
|
||||
return (NSComparisonResult)MIN(1, MAX(-1, entry1.sequenceNumber - entry2.sequenceNumber));
|
||||
}];
|
||||
|
||||
//remove oldest items until within limit
|
||||
for (id key in keys)
|
||||
{
|
||||
if (totalCount <= maxCount && _totalCost <= maxCost)
|
||||
{
|
||||
break;
|
||||
}
|
||||
RCTCacheEntry *entry = _cache[key];
|
||||
if (!_delegateRespondsToShouldEvictObject || [self.delegate cache:(RCTCache *)self shouldEvictObject:entry])
|
||||
{
|
||||
if (_delegateRespondsToWillEvictObject)
|
||||
{
|
||||
_currentlyCleaning = YES;
|
||||
[self.delegate cache:(RCTCache *)self willEvictObject:entry];
|
||||
_currentlyCleaning = NO;
|
||||
}
|
||||
[_cache removeObjectForKey:key];
|
||||
_totalCost -= entry.cost;
|
||||
totalCount --;
|
||||
}
|
||||
}
|
||||
}
|
||||
[_lock unlock];
|
||||
}
|
||||
|
||||
- (void)cleanUpAllObjects
|
||||
{
|
||||
[_lock lock];
|
||||
if (_delegateRespondsToShouldEvictObject || _delegateRespondsToWillEvictObject)
|
||||
{
|
||||
NSArray *keys = [_cache allKeys];
|
||||
if (_delegateRespondsToShouldEvictObject)
|
||||
{
|
||||
//sort, oldest first (in case we want to use that information in our eviction test)
|
||||
keys = [keys sortedArrayUsingComparator:^NSComparisonResult(id key1, id key2) {
|
||||
RCTCacheEntry *entry1 = self.cache[key1];
|
||||
RCTCacheEntry *entry2 = self.cache[key2];
|
||||
return (NSComparisonResult)MIN(1, MAX(-1, entry1.sequenceNumber - entry2.sequenceNumber));
|
||||
}];
|
||||
}
|
||||
|
||||
//remove all items individually
|
||||
for (id key in keys)
|
||||
{
|
||||
RCTCacheEntry *entry = _cache[key];
|
||||
if (!_delegateRespondsToShouldEvictObject || [self.delegate cache:(RCTCache *)self shouldEvictObject:entry])
|
||||
{
|
||||
if (_delegateRespondsToWillEvictObject)
|
||||
{
|
||||
_currentlyCleaning = YES;
|
||||
[self.delegate cache:(RCTCache *)self willEvictObject:entry];
|
||||
_currentlyCleaning = NO;
|
||||
}
|
||||
[_cache removeObjectForKey:key];
|
||||
_totalCost -= entry.cost;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_totalCost = 0;
|
||||
[_cache removeAllObjects];
|
||||
_sequenceNumber = 0;
|
||||
}
|
||||
[_lock unlock];
|
||||
}
|
||||
|
||||
- (void)resequence
|
||||
{
|
||||
//sort, oldest first
|
||||
NSArray *entries = [[_cache allValues] sortedArrayUsingComparator:^NSComparisonResult(RCTCacheEntry *entry1, RCTCacheEntry *entry2) {
|
||||
return (NSComparisonResult)MIN(1, MAX(-1, entry1.sequenceNumber - entry2.sequenceNumber));
|
||||
}];
|
||||
|
||||
//renumber items
|
||||
NSInteger index = 0;
|
||||
for (RCTCacheEntry *entry in entries)
|
||||
{
|
||||
entry.sequenceNumber = index++;
|
||||
}
|
||||
}
|
||||
|
||||
- (id)objectForKey:(id<NSCopying>)key
|
||||
{
|
||||
[_lock lock];
|
||||
RCTCacheEntry *entry = _cache[key];
|
||||
entry.sequenceNumber = _sequenceNumber++;
|
||||
if (_sequenceNumber < 0)
|
||||
{
|
||||
[self resequence];
|
||||
}
|
||||
id object = entry.object;
|
||||
[_lock unlock];
|
||||
return object;
|
||||
}
|
||||
|
||||
- (id)objectForKeyedSubscript:(id<NSCopying>)key
|
||||
{
|
||||
return [self objectForKey:key];
|
||||
}
|
||||
|
||||
- (void)setObject:(id)obj forKey:(id<NSCopying>)key
|
||||
{
|
||||
[self setObject:obj forKey:key cost:0];
|
||||
}
|
||||
|
||||
- (void)setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key
|
||||
{
|
||||
[self setObject:obj forKey:key cost:0];
|
||||
}
|
||||
|
||||
- (void)setObject:(id)obj forKey:(id<NSCopying>)key cost:(NSUInteger)g
|
||||
{
|
||||
RCTAssert(!_currentlyCleaning, @"It is not possible to modify cache from within the implementation of this delegate method.");
|
||||
[_lock lock];
|
||||
_totalCost -= [_cache[key] cost];
|
||||
_totalCost += g;
|
||||
_cache[key] = [RCTCacheEntry entryWithObject:obj cost:g sequenceNumber:_sequenceNumber++];
|
||||
if (_sequenceNumber < 0)
|
||||
{
|
||||
[self resequence];
|
||||
}
|
||||
[_lock unlock];
|
||||
[self cleanUp];
|
||||
}
|
||||
|
||||
- (void)removeObjectForKey:(id<NSCopying>)key
|
||||
{
|
||||
RCTAssert(!_currentlyCleaning, @"It is not possible to modify cache from within the implementation of this delegate method.");
|
||||
[_lock lock];
|
||||
_totalCost -= [_cache[key] cost];
|
||||
[_cache removeObjectForKey:key];
|
||||
[_lock unlock];
|
||||
}
|
||||
|
||||
- (void)removeAllObjects
|
||||
{
|
||||
RCTAssert(!_currentlyCleaning, @"It is not possible to modify cache from within the implementation of this delegate method.");
|
||||
[_lock lock];
|
||||
_totalCost = 0;
|
||||
_sequenceNumber = 0;
|
||||
[_cache removeAllObjects];
|
||||
[_lock unlock];
|
||||
}
|
||||
|
||||
//handle unimplemented methods
|
||||
|
||||
- (BOOL)isKindOfClass:(Class)cls
|
||||
{
|
||||
//pretend that we're an RCTCache if anyone asks
|
||||
if (cls == [RCTCache class] || cls == [NSCache class])
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
return [super isKindOfClass:cls];
|
||||
}
|
||||
|
||||
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
|
||||
{
|
||||
//protect against calls to unimplemented NSCache methods
|
||||
NSMethodSignature *signature = [super methodSignatureForSelector:selector];
|
||||
if (!signature)
|
||||
{
|
||||
signature = [NSCache instanceMethodSignatureForSelector:selector];
|
||||
}
|
||||
return signature;
|
||||
}
|
||||
|
||||
- (void)forwardInvocation:(NSInvocation *)invocation
|
||||
{
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wnonnull"
|
||||
|
||||
[invocation invokeWithTarget:nil];
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTCache
|
||||
|
||||
@dynamic count;
|
||||
@dynamic totalCost;
|
||||
|
||||
+ (instancetype)alloc
|
||||
{
|
||||
return (RCTCache *)[RCTCache_Private alloc];
|
||||
}
|
||||
|
||||
- (id)objectForKeyedSubscript:(__unused NSNumber *)key
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setObject:(__unused id)obj forKeyedSubscript:(__unused id<NSCopying>)key {}
|
||||
|
||||
@end
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#import <objc/message.h>
|
||||
|
||||
#import "RCTCache.h"
|
||||
#import "RCTDefines.h"
|
||||
|
||||
@implementation RCTConvert
|
||||
|
@ -106,7 +107,11 @@ RCT_CONVERTER(NSString *, NSString, description)
|
|||
|
||||
// Assume that it's a local path
|
||||
path = [path stringByRemovingPercentEncoding];
|
||||
if (![path isAbsolutePath]) {
|
||||
if ([path hasPrefix:@"~"]) {
|
||||
// Path is inside user directory
|
||||
path = [path stringByExpandingTildeInPath];
|
||||
} else if (![path isAbsolutePath]) {
|
||||
// Assume it's a resource path
|
||||
path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:path];
|
||||
}
|
||||
return [NSURL fileURLWithPath:path];
|
||||
|
@ -387,10 +392,11 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[
|
|||
+ (UIColor *)UIColor:(id)json
|
||||
{
|
||||
// Check color cache
|
||||
static NSMutableDictionary *colorCache = nil;
|
||||
static RCTCache *colorCache = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
colorCache = [[NSMutableDictionary alloc] init];
|
||||
colorCache = [[RCTCache alloc] init];
|
||||
colorCache.countLimit = 1024;
|
||||
});
|
||||
UIColor *color = colorCache[json];
|
||||
if (color) {
|
||||
|
@ -650,43 +656,54 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[
|
|||
return nil;
|
||||
}
|
||||
|
||||
if (RCT_DEBUG && ![json isKindOfClass:[NSString class]] && ![json isKindOfClass:[NSDictionary class]]) {
|
||||
RCTLogConvertError(json, "an image");
|
||||
return nil;
|
||||
}
|
||||
|
||||
UIImage *image;
|
||||
NSString *path;
|
||||
CGFloat scale = 0.0;
|
||||
if ([json isKindOfClass:[NSString class]]) {
|
||||
if ([json length] == 0) {
|
||||
return nil;
|
||||
}
|
||||
path = json;
|
||||
} else {
|
||||
} else if ([json isKindOfClass:[NSDictionary class]]) {
|
||||
path = [self NSString:json[@"uri"]];
|
||||
scale = [self CGFloat:json[@"scale"]];
|
||||
} else {
|
||||
RCTLogConvertError(json, "an image");
|
||||
}
|
||||
|
||||
if ([path hasPrefix:@"data:"]) {
|
||||
NSURL *url = [NSURL URLWithString:path];
|
||||
NSData *imageData = [NSData dataWithContentsOfURL:url];
|
||||
image = [UIImage imageWithData:imageData];
|
||||
} else if ([path isAbsolutePath] || [path hasPrefix:@"~"]) {
|
||||
image = [UIImage imageWithContentsOfFile:path.stringByExpandingTildeInPath];
|
||||
} else {
|
||||
image = [UIImage imageNamed:path];
|
||||
if (!image) {
|
||||
image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:path ofType:nil]];
|
||||
NSURL *URL = [self NSURL:path];
|
||||
NSString *scheme = [URL.scheme lowercaseString];
|
||||
if ([scheme isEqualToString:@"file"]) {
|
||||
|
||||
if ([NSThread currentThread] == [NSThread mainThread]) {
|
||||
// Image may reside inside a .car file, in which case we have no choice
|
||||
// but to use +[UIImage imageNamed] - but this method isn't thread safe
|
||||
image = [UIImage imageNamed:path];
|
||||
}
|
||||
|
||||
if (!image) {
|
||||
// Attempt to load from the file system
|
||||
if ([path pathExtension].length == 0) {
|
||||
path = [path stringByAppendingPathExtension:@"png"];
|
||||
}
|
||||
image = [UIImage imageWithContentsOfFile:path];
|
||||
}
|
||||
|
||||
// We won't warn about nil images because there are legitimate cases
|
||||
// where we find out if a string is an image by using this method, but
|
||||
// we do enforce thread-safe API usage with the following check
|
||||
if (RCT_DEBUG && !image && [UIImage imageNamed:path]) {
|
||||
RCTAssertMainThread();
|
||||
}
|
||||
|
||||
} else if ([scheme isEqualToString:@"data"]) {
|
||||
image = [UIImage imageWithData:[NSData dataWithContentsOfURL:URL]];
|
||||
} else {
|
||||
RCTLogConvertError(json, "an image. Only local files or data URIs are supported");
|
||||
}
|
||||
|
||||
|
||||
if (scale > 0) {
|
||||
image = [UIImage imageWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
|
||||
image = [UIImage imageWithCGImage:image.CGImage
|
||||
scale:scale
|
||||
orientation:image.imageOrientation];
|
||||
}
|
||||
|
||||
// NOTE: we don't warn about nil images because there are legitimate
|
||||
// case where we find out if a string is an image by using this method
|
||||
return image;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#import "RCTLog.h"
|
||||
|
||||
#include <asl.h>
|
||||
|
||||
#import "RCTAssert.h"
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTDefines.h"
|
||||
|
@ -57,6 +59,25 @@ RCTLogFunction RCTDefaultLogFunction = ^(
|
|||
);
|
||||
fprintf(stderr, "%s\n", log.UTF8String);
|
||||
fflush(stderr);
|
||||
|
||||
int aslLevel = ASL_LEVEL_ERR;
|
||||
switch(level) {
|
||||
case RCTLogLevelInfo:
|
||||
aslLevel = ASL_LEVEL_NOTICE;
|
||||
break;
|
||||
case RCTLogLevelWarning:
|
||||
aslLevel = ASL_LEVEL_WARNING;
|
||||
break;
|
||||
case RCTLogLevelError:
|
||||
aslLevel = ASL_LEVEL_ERR;
|
||||
break;
|
||||
case RCTLogLevelMustFix:
|
||||
aslLevel = ASL_LEVEL_EMERG;
|
||||
break;
|
||||
default:
|
||||
aslLevel = ASL_LEVEL_DEBUG;
|
||||
}
|
||||
asl_log(NULL, NULL, aslLevel, "%s", message.UTF8String);
|
||||
};
|
||||
|
||||
void RCTSetLogFunction(RCTLogFunction logFunction)
|
||||
|
|
|
@ -47,6 +47,7 @@ RCT_EXTERN BOOL RCTClassOverridesInstanceMethod(Class cls, SEL selector);
|
|||
// Creates a standardized error object
|
||||
RCT_EXTERN NSDictionary *RCTMakeError(NSString *message, id toStringify, NSDictionary *extraData);
|
||||
RCT_EXTERN NSDictionary *RCTMakeAndLogError(NSString *message, id toStringify, NSDictionary *extraData);
|
||||
RCT_EXTERN NSDictionary *RCTJSErrorFromNSError(NSError *error);
|
||||
|
||||
// Returns YES if React is running in a test environment
|
||||
RCT_EXTERN BOOL RCTRunningInTestEnvironment(void);
|
||||
|
@ -58,7 +59,8 @@ RCT_EXTERN BOOL RCTImageHasAlpha(CGImageRef image);
|
|||
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);
|
||||
RCT_EXTERN id RCTNullIfNil(id value);
|
||||
|
||||
RCT_EXTERN NSDictionary *RCTJSErrorFromNSError(NSError *error);
|
||||
// Convert data to a Base64-encoded data URL
|
||||
RCT_EXTERN NSURL *RCTDataURL(NSString *mimeType, NSData *data);
|
||||
|
|
|
@ -238,6 +238,27 @@ NSDictionary *RCTMakeAndLogError(NSString *message, id toStringify, NSDictionary
|
|||
return error;
|
||||
}
|
||||
|
||||
// TODO: Can we just replace RCTMakeError with this function instead?
|
||||
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);
|
||||
}
|
||||
|
||||
BOOL RCTRunningInTestEnvironment(void)
|
||||
{
|
||||
static BOOL isTestEnvironment = NO;
|
||||
|
@ -277,23 +298,10 @@ id RCTNilIfNull(id value)
|
|||
return value == (id)kCFNull ? nil : value;
|
||||
}
|
||||
|
||||
// TODO: Can we just replace RCTMakeError with this function instead?
|
||||
NSDictionary *RCTJSErrorFromNSError(NSError *error)
|
||||
NSURL *RCTDataURL(NSString *mimeType, NSData *data)
|
||||
{
|
||||
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);
|
||||
return [NSURL URLWithString:
|
||||
[NSString stringWithFormat:@"data:%@;base64,%@", mimeType,
|
||||
[data base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]]];
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#import "RCTScrollableProtocol.h"
|
||||
#import "RCTShadowView.h"
|
||||
#import "RCTSparseArray.h"
|
||||
#import "RCTTouchHandler.h"
|
||||
#import "RCTUtils.h"
|
||||
#import "RCTView.h"
|
||||
#import "RCTViewManager.h"
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
137327E81AA5CF210034F82E /* RCTTabBarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 137327E21AA5CF210034F82E /* RCTTabBarItem.m */; };
|
||||
137327E91AA5CF210034F82E /* RCTTabBarItemManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 137327E41AA5CF210034F82E /* RCTTabBarItemManager.m */; };
|
||||
137327EA1AA5CF210034F82E /* RCTTabBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 137327E61AA5CF210034F82E /* RCTTabBarManager.m */; };
|
||||
138D6A141B53CD290074A87E /* RCTCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 138D6A131B53CD290074A87E /* RCTCache.m */; };
|
||||
13A1F71E1A75392D00D3D453 /* RCTKeyCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */; };
|
||||
13AF20451AE707F9005F5298 /* RCTSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 13AF20441AE707F9005F5298 /* RCTSlider.m */; };
|
||||
13B07FEF1A69327A00A75B9A /* RCTAlertManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FE81A69327A00A75B9A /* RCTAlertManager.m */; };
|
||||
|
@ -125,6 +126,8 @@
|
|||
137327E41AA5CF210034F82E /* RCTTabBarItemManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTabBarItemManager.m; sourceTree = "<group>"; };
|
||||
137327E51AA5CF210034F82E /* RCTTabBarManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTabBarManager.h; sourceTree = "<group>"; };
|
||||
137327E61AA5CF210034F82E /* RCTTabBarManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTabBarManager.m; sourceTree = "<group>"; };
|
||||
138D6A121B53CD290074A87E /* RCTCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTCache.h; sourceTree = "<group>"; };
|
||||
138D6A131B53CD290074A87E /* RCTCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTCache.m; sourceTree = "<group>"; };
|
||||
13A1F71C1A75392D00D3D453 /* RCTKeyCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTKeyCommands.h; sourceTree = "<group>"; };
|
||||
13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTKeyCommands.m; sourceTree = "<group>"; };
|
||||
13AF1F851AE6E777005F5298 /* RCTDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDefines.h; sourceTree = "<group>"; };
|
||||
|
@ -407,6 +410,8 @@
|
|||
83CBBA491A601E3B00E9B192 /* Base */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
138D6A121B53CD290074A87E /* RCTCache.h */,
|
||||
138D6A131B53CD290074A87E /* RCTCache.m */,
|
||||
83CBBA4A1A601E3B00E9B192 /* RCTAssert.h */,
|
||||
83CBBA4B1A601E3B00E9B192 /* RCTAssert.m */,
|
||||
14C2CA771B3ACB0400E6CBB2 /* RCTBatchedBridge.m */,
|
||||
|
@ -599,6 +604,7 @@
|
|||
1403F2B31B0AE60700C2A9A4 /* RCTPerfStats.m in Sources */,
|
||||
83CBBA691A601EF300E9B192 /* RCTEventDispatcher.m in Sources */,
|
||||
13E0674A1A70F434002CDEE1 /* RCTUIManager.m in Sources */,
|
||||
138D6A141B53CD290074A87E /* RCTCache.m in Sources */,
|
||||
13B0801B1A69489C00A75B9A /* RCTNavigatorManager.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
Loading…
Reference in New Issue