2015-02-07 updates

- Random little fixes | Andres Suarez
- Add backButtonTitle to Navigator | Nick Poulden
- [react-pacakger] Ignore malformed package.json | Amjad Masad
- Renamed hasMove to hasMark | Rich Seymour
- Update XMLHttpRequest.ios.js | Nick Poulden
- Warn about missing dependencies for issue #16 | Andrew McCloud
This commit is contained in:
Christopher Chedeau 2015-02-07 17:23:25 -08:00
parent 462c7ed8ef
commit 39f475ea9b
13 changed files with 125 additions and 58 deletions

View File

@ -40,7 +40,7 @@ class Board {
return this; return this;
} }
hasMove(row: number, col: number): boolean { hasMark(row: number, col: number): boolean {
return this.grid[row][col] !== 0; return this.grid[row][col] !== 0;
} }
@ -132,7 +132,10 @@ var Cell = React.createClass({
render() { render() {
return ( return (
<TouchableHighlight onPress={this.props.onPress} underlayColor={'clear'} activeOpacity={0.5}> <TouchableHighlight
onPress={this.props.onPress}
underlayColor="transparent"
activeOpacity={0.5}>
<View style={[styles.cell, this.cellStyle()]}> <View style={[styles.cell, this.cellStyle()]}>
<Image source={{uri: this.imageContents()}} /> <Image source={{uri: this.imageContents()}} />
</View> </View>
@ -161,7 +164,10 @@ var GameEndOverlay = React.createClass({
return ( return (
<View style={styles.overlay}> <View style={styles.overlay}>
<Text style={styles.overlayMessage}>{message}</Text> <Text style={styles.overlayMessage}>{message}</Text>
<TouchableHighlight onPress={this.props.onRestart} underlayColor={'clear'} activeOpacity={0.5}> <TouchableHighlight
onPress={this.props.onRestart}
underlayColor="transparent"
activeOpacity={0.5}>
<View style={styles.newGame}> <View style={styles.newGame}>
<Text style={styles.newGameText}>New Game</Text> <Text style={styles.newGameText}>New Game</Text>
</View> </View>
@ -185,7 +191,7 @@ var TicTacToeApp = React.createClass({
}, },
handleCellPress(row: number, col: number) { handleCellPress(row: number, col: number) {
if (this.state.board.hasMove(row, col)) { if (this.state.board.hasMark(row, col)) {
return; return;
} }
@ -214,7 +220,10 @@ var TicTacToeApp = React.createClass({
<View style={styles.board}> <View style={styles.board}>
{rows} {rows}
</View> </View>
<GameEndOverlay board={this.state.board} onRestart={this.restartGame} /> <GameEndOverlay
board={this.state.board}
onRestart={this.restartGame}
/>
</View> </View>
); );
} }

View File

@ -124,7 +124,7 @@ var LayoutExample = React.createClass({
</UIExplorerBlock> </UIExplorerBlock>
<UIExplorerBlock title="Flex Wrap"> <UIExplorerBlock title="Flex Wrap">
<CircleBlock style={{flexWrap: 'wrap'}}> <CircleBlock style={{flexWrap: 'wrap'}}>
{'oooooooooooooooo'.split('').map(() => <Circle />)} {'oooooooooooooooo'.split('').map((char, i) => <Circle key={i} />)}
</CircleBlock> </CircleBlock>
</UIExplorerBlock> </UIExplorerBlock>
</UIExplorerPage> </UIExplorerPage>

View File

@ -60,6 +60,7 @@ var NavigatorIOSExample = React.createClass({
this.props.navigator.push({ this.props.navigator.push({
title: NavigatorIOSExample.title, title: NavigatorIOSExample.title,
component: NavigatorIOSExample, component: NavigatorIOSExample,
backButtonTitle: 'Custom Back',
passProps: {topExampleRoute: this.props.topExampleRoute || this.props.route}, passProps: {topExampleRoute: this.props.topExampleRoute || this.props.route},
}); });
})} })}

View File

@ -54,7 +54,7 @@ var Thumb = React.createClass({
var THUMBS = ['https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851549_767334479959628_274486868_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851579_767334503292959_179092627_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851589_767334513292958_1747022277_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851563_767334559959620_1193692107_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851593_767334566626286_1953955109_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851591_767334523292957_797560749_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851567_767334529959623_843148472_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851548_767334489959627_794462220_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851575_767334539959622_441598241_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851573_767334549959621_534583464_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851583_767334573292952_1519550680_n.png']; var THUMBS = ['https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851549_767334479959628_274486868_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851579_767334503292959_179092627_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851589_767334513292958_1747022277_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851563_767334559959620_1193692107_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851593_767334566626286_1953955109_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851591_767334523292957_797560749_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851567_767334529959623_843148472_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851548_767334489959627_794462220_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851575_767334539959622_441598241_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851573_767334549959621_534583464_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851583_767334573292952_1519550680_n.png'];
THUMBS = THUMBS.concat(THUMBS); // double length of THUMBS THUMBS = THUMBS.concat(THUMBS); // double length of THUMBS
var createThumbRow = (uri, i) => <Thumb uri={uri}/>; var createThumbRow = (uri, i) => <Thumb key={i} uri={uri} />;
var styles = StyleSheet.create({ var styles = StyleSheet.create({
scrollView: { scrollView: {

View File

@ -45,10 +45,10 @@ var UIExplorerList = React.createClass({
); );
}, },
_renderRow: function(example) { _renderRow: function(example, i) {
invariant(example.title, 'Example must provide a title.'); invariant(example.title, 'Example must provide a title.');
return ( return (
<View> <View key={i}>
<TouchableHighlight onPress={() => this._onPressRow(example)}> <TouchableHighlight onPress={() => this._onPressRow(example)}>
<View style={styles.row}> <View style={styles.row}>
<Text style={styles.rowTitleText}> <Text style={styles.rowTitleText}>

View File

@ -20,7 +20,7 @@ var createExamplePage = function(title, exampleModule) {
description: exampleModule.description, description: exampleModule.description,
}, },
getBlock: function(example) { getBlock: function(example, i) {
// Hack warning: This is a hack because the www UI explorer requires // Hack warning: This is a hack because the www UI explorer requires
// renderComponent to be called. // renderComponent to be called.
var originalRenderComponent = React.renderComponent; var originalRenderComponent = React.renderComponent;
@ -37,6 +37,7 @@ var createExamplePage = function(title, exampleModule) {
React.render = originalRender; React.render = originalRender;
return ( return (
<UIExplorerBlock <UIExplorerBlock
key={i}
title={example.title} title={example.title}
description={example.description}> description={example.description}>
{renderedComponent} {renderedComponent}

View File

@ -104,7 +104,7 @@ var ListView = React.createClass({
initialListSize: PropTypes.number, initialListSize: PropTypes.number,
/** /**
* Called when all rows have been rendered and the list has been scrolled * Called when all rows have been rendered and the list has been scrolled
* to within onEndReachedThreashold of the bottom. The native scroll * to within onEndReachedThreshold of the bottom. The native scroll
* event is provided. * event is provided.
*/ */
onEndReached: PropTypes.func, onEndReached: PropTypes.func,

View File

@ -179,6 +179,13 @@ var NavigatorIOS = React.createClass({
*/ */
passProps: PropTypes.object, passProps: PropTypes.object,
/**
* If set, the left header button will appear with this name. Note that
* this doesn't apply for the header of the current view, but the ones
* of the views that are pushed afterward.
*/
backButtonTitle: PropTypes.string,
/** /**
* If set, the right header button will appear with this name * If set, the right header button will appear with this name
*/ */
@ -493,6 +500,7 @@ var NavigatorIOS = React.createClass({
this.props.itemWrapperStyle, this.props.itemWrapperStyle,
route.wrapperStyle route.wrapperStyle
]} ]}
backButtonTitle={route.backButtonTitle}
rightButtonTitle={route.rightButtonTitle} rightButtonTitle={route.rightButtonTitle}
onNavRightButtonTap={route.onRightButtonPress} onNavRightButtonTap={route.onRightButtonPress}
tintColor={this.props.tintColor}> tintColor={this.props.tintColor}>

View File

@ -58,6 +58,11 @@ class XMLHttpRequest {
return ''; return '';
} }
getResponseHeader(header: string): ?string {
/* Stub */
return '';
}
setRequestHeader(header: string, value: any): void { setRequestHeader(header: string, value: any): void {
this._headers[header] = value; this._headers[header] = value;
} }

View File

@ -114,7 +114,7 @@ RCT_CONVERTER_CUSTOM(NSUInteger, NSUInteger, [json unsignedIntegerValue])
RCTLogMustFix(@"Expected NSString for NSURL, received %@: %@", [json class], json); RCTLogMustFix(@"Expected NSString for NSURL, received %@: %@", [json class], json);
return nil; return nil;
} }
NSString *path = json; NSString *path = json;
if ([path isAbsolutePath]) if ([path isAbsolutePath])
{ {
@ -194,15 +194,15 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"]
if (color) { if (color) {
return color; return color;
} }
if ([json isKindOfClass:[NSString class]]) { if ([json isKindOfClass:[NSString class]]) {
// Check named colors // Check named colors
static NSDictionary *namedColors = nil; static NSDictionary *namedColors = nil;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
namedColors = @{ namedColors = @{
// CSS colors // CSS colors
@"aliceblue": @"#f0f8ff", @"aliceblue": @"#f0f8ff",
@"antiquewhite": @"#faebd7", @"antiquewhite": @"#faebd7",
@ -352,17 +352,16 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"]
@"whitesmoke": @"#f5f5f5", @"whitesmoke": @"#f5f5f5",
@"yellow": @"#ffff00", @"yellow": @"#ffff00",
@"yellowgreen": @"#9acd32", @"yellowgreen": @"#9acd32",
// Nonstandard color extensions // Nonstandard color extensions
@"transparent": @"rgba(0,0,0,0)", @"transparent": @"rgba(0,0,0,0)",
@"clear": @"rgba(0,0,0,0)",
}; };
}); });
NSString *colorString = namedColors[json]; NSString *colorString = namedColors[json];
if (!colorString) { if (!colorString) {
colorString = json; colorString = json;
} }
// Parse color // Parse color
NSUInteger red = -1; NSUInteger red = -1;
NSUInteger green = -1; NSUInteger green = -1;
@ -384,32 +383,32 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"]
} else { } else {
color = [UIColor colorWithRed:red / 255.0 green:green / 255.0 blue:blue / 255.0 alpha:alpha]; color = [UIColor colorWithRed:red / 255.0 green:green / 255.0 blue:blue / 255.0 alpha:alpha];
} }
} else if ([json isKindOfClass:[NSArray class]]) { } else if ([json isKindOfClass:[NSArray class]]) {
if ([json count] < 3 || [json count] > 4) { if ([json count] < 3 || [json count] > 4) {
RCTLogMustFix(@"Expected array with count 3 or 4, but count is %zd: %@", [json count], json); RCTLogMustFix(@"Expected array with count 3 or 4, but count is %zd: %@", [json count], json);
} else { } else {
// Color array // Color array
color = [UIColor colorWithRed:[json[0] doubleValue] color = [UIColor colorWithRed:[json[0] doubleValue]
green:[json[1] doubleValue] green:[json[1] doubleValue]
blue:[json[2] doubleValue] blue:[json[2] doubleValue]
alpha:[json count] > 3 ? [json[3] doubleValue] : 1]; alpha:[json count] > 3 ? [json[3] doubleValue] : 1];
} }
} else if ([json isKindOfClass:[NSDictionary class]]) { } else if ([json isKindOfClass:[NSDictionary class]]) {
// Color dictionary // Color dictionary
color = [UIColor colorWithRed:[json[@"r"] doubleValue] color = [UIColor colorWithRed:[json[@"r"] doubleValue]
green:[json[@"g"] doubleValue] green:[json[@"g"] doubleValue]
blue:[json[@"b"] doubleValue] blue:[json[@"b"] doubleValue]
alpha:[json[@"a"] ?: @1 doubleValue]]; alpha:[json[@"a"] ?: @1 doubleValue]];
} else if (json && ![json isKindOfClass:[NSNull class]]) { } else if (json && ![json isKindOfClass:[NSNull class]]) {
RCTLogMustFix(@"Expected NSArray, NSDictionary or NSString for UIColor, received %@: %@", [json class], json); RCTLogMustFix(@"Expected NSArray, NSDictionary or NSString for UIColor, received %@: %@", [json class], json);
} }
@ -417,7 +416,7 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"]
if (!color) { if (!color) {
color = [UIColor whiteColor]; color = [UIColor whiteColor];
} }
// Cache and return // Cache and return
if (json) { if (json) {
colorCache[json] = color; colorCache[json] = color;
@ -513,11 +512,11 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"]
RCTLogMustFix(@"Expected NSString for UIImage, received %@: %@", [json class], json); RCTLogMustFix(@"Expected NSString for UIImage, received %@: %@", [json class], json);
return nil; return nil;
} }
if ([json length] == 0) { if ([json length] == 0) {
return nil; return nil;
} }
UIImage *image = nil; UIImage *image = nil;
NSString *path = json; NSString *path = json;
if ([path isAbsolutePath]) { if ([path isAbsolutePath]) {
@ -558,13 +557,13 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"]
{ {
// Create descriptor // Create descriptor
UIFontDescriptor *fontDescriptor = font.fontDescriptor ?: [UIFontDescriptor fontDescriptorWithName:RCTDefaultFontName size:RCTDefaultFontSize]; UIFontDescriptor *fontDescriptor = font.fontDescriptor ?: [UIFontDescriptor fontDescriptorWithName:RCTDefaultFontName size:RCTDefaultFontSize];
// Get font size // Get font size
CGFloat fontSize = [self CGFloat:size]; CGFloat fontSize = [self CGFloat:size];
if (fontSize && !isnan(fontSize)) { if (fontSize && !isnan(fontSize)) {
fontDescriptor = [fontDescriptor fontDescriptorWithSize:fontSize]; fontDescriptor = [fontDescriptor fontDescriptorWithSize:fontSize];
} }
// Get font family // Get font family
NSString *familyName = [RCTConvert NSString:family]; NSString *familyName = [RCTConvert NSString:family];
if (familyName) { if (familyName) {
@ -584,21 +583,21 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"]
fontDescriptor = [fontDescriptor fontDescriptorWithFamily:familyName]; fontDescriptor = [fontDescriptor fontDescriptorWithFamily:familyName];
} }
} }
// Get font weight // Get font weight
NSString *fontWeight = [RCTConvert NSString:weight]; NSString *fontWeight = [RCTConvert NSString:weight];
if (fontWeight) { if (fontWeight) {
static NSSet *values; static NSSet *values;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
values = [NSSet setWithObjects:@"bold", @"normal", nil]; values = [NSSet setWithObjects:@"bold", @"normal", nil];
}); });
if (fontWeight && ![values containsObject:fontWeight]) { if (fontWeight && ![values containsObject:fontWeight]) {
RCTLogError(@"Unrecognized font weight '%@', must be one of %@", fontWeight, values); RCTLogError(@"Unrecognized font weight '%@', must be one of %@", fontWeight, values);
} }
UIFontDescriptorSymbolicTraits symbolicTraits = fontDescriptor.symbolicTraits; UIFontDescriptorSymbolicTraits symbolicTraits = fontDescriptor.symbolicTraits;
if ([fontWeight isEqualToString:RCTBoldFontWeight]) { if ([fontWeight isEqualToString:RCTBoldFontWeight]) {
symbolicTraits |= UIFontDescriptorTraitBold; symbolicTraits |= UIFontDescriptorTraitBold;
@ -607,9 +606,9 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"]
} }
fontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits:symbolicTraits]; fontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits:symbolicTraits];
} }
// TODO: font style // TODO: font style
// Create font // Create font
return [UIFont fontWithDescriptor:fontDescriptor size:fontDescriptor.pointSize]; return [UIFont fontWithDescriptor:fontDescriptor size:fontDescriptor.pointSize];
} }
@ -670,7 +669,7 @@ static NSString *RCTGuessTypeEncoding(id target, NSString *key, id value, NSStri
return @"@\"UIColor\""; return @"@\"UIColor\"";
} }
} }
return nil; return nil;
} }
@ -679,15 +678,15 @@ static NSDictionary *RCTConvertValue(id value, NSString *encoding)
static NSDictionary *converters = nil; static NSDictionary *converters = nil;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
id (^numberConvert)(id) = ^(id val){ id (^numberConvert)(id) = ^(id val){
return [RCTConvert NSNumber:val]; return [RCTConvert NSNumber:val];
}; };
id (^boolConvert)(id) = ^(id val){ id (^boolConvert)(id) = ^(id val){
return @([RCTConvert BOOL:val]); return @([RCTConvert BOOL:val]);
}; };
// TODO (#5906496): add the rest of RCTConvert here // TODO (#5906496): add the rest of RCTConvert here
converters = converters =
@{ @{
@ -750,7 +749,7 @@ static NSDictionary *RCTConvertValue(id value, NSString *encoding)
if (value == [NSNull null] && ![encoding isEqualToString:@"@\"NSNull\""]) { if (value == [NSNull null] && ![encoding isEqualToString:@"@\"NSNull\""]) {
return nil; return nil;
} }
// Convert value // Convert value
id (^converter)(id) = converters[encoding]; id (^converter)(id) = converters[encoding];
return converter ? converter(value) : value; return converter ? converter(value) : value;
@ -772,23 +771,23 @@ BOOL RCTSetProperty(id target, NSString *keypath, id value)
NSString *encoding = nil; NSString *encoding = nil;
objc_property_t property = class_getProperty([target class], [key UTF8String]); objc_property_t property = class_getProperty([target class], [key UTF8String]);
if (property) { if (property) {
// Get type info // Get type info
char *typeEncoding = property_copyAttributeValue(property, "T"); char *typeEncoding = property_copyAttributeValue(property, "T");
encoding = @(typeEncoding); encoding = @(typeEncoding);
free(typeEncoding); free(typeEncoding);
} else { } else {
// Check if setter exists // Check if setter exists
SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:", SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",
[[key substringToIndex:1] uppercaseString], [[key substringToIndex:1] uppercaseString],
[key substringFromIndex:1]]); [key substringFromIndex:1]]);
if (![target respondsToSelector:setter]) { if (![target respondsToSelector:setter]) {
return NO; return NO;
} }
// Get type of first method argument // Get type of first method argument
Method method = class_getInstanceMethod([target class], setter); Method method = class_getInstanceMethod([target class], setter);
char *typeEncoding = method_copyArgumentType(method, 2); char *typeEncoding = method_copyArgumentType(method, 2);
@ -797,17 +796,17 @@ BOOL RCTSetProperty(id target, NSString *keypath, id value)
free(typeEncoding); free(typeEncoding);
} }
} }
if (encoding.length == 0 || [encoding isEqualToString:@(@encode(id))]) { if (encoding.length == 0 || [encoding isEqualToString:@(@encode(id))]) {
// Not enough info about the type encoding to be useful, so // Not enough info about the type encoding to be useful, so
// try to guess the type from the value and property name // try to guess the type from the value and property name
encoding = RCTGuessTypeEncoding(target, key, value, encoding); encoding = RCTGuessTypeEncoding(target, key, value, encoding);
} }
// Special case for numeric encodings, which may be enums // Special case for numeric encodings, which may be enums
if ([value isKindOfClass:[NSString class]] && if ([value isKindOfClass:[NSString class]] &&
[@"iIsSlLqQ" containsString:[encoding substringToIndex:1]]) { [@"iIsSlLqQ" containsString:[encoding substringToIndex:1]]) {
/** /**
* NOTE: the property names below may seem weird, but it's * NOTE: the property names below may seem weird, but it's
* because they are tested as case-sensitive suffixes, so * because they are tested as case-sensitive suffixes, so
@ -843,7 +842,7 @@ BOOL RCTSetProperty(id target, NSString *keypath, id value)
} }
} }
} }
// Another nasty special case // Another nasty special case
if ([target isKindOfClass:[UITextField class]]) { if ([target isKindOfClass:[UITextField class]]) {
static NSDictionary *specialCases = nil; static NSDictionary *specialCases = nil;
@ -859,7 +858,7 @@ BOOL RCTSetProperty(id target, NSString *keypath, id value)
@"enablesReturnKeyAutomatically": ^(UITextField *f, NSInteger v){ f.enablesReturnKeyAutomatically = !!v; }, @"enablesReturnKeyAutomatically": ^(UITextField *f, NSInteger v){ f.enablesReturnKeyAutomatically = !!v; },
@"secureTextEntry": ^(UITextField *f, NSInteger v){ f.secureTextEntry = !!v; }}; @"secureTextEntry": ^(UITextField *f, NSInteger v){ f.secureTextEntry = !!v; }};
}); });
void (^block)(UITextField *f, NSInteger v) = specialCases[key]; void (^block)(UITextField *f, NSInteger v) = specialCases[key];
if (block) if (block)
{ {
@ -867,7 +866,7 @@ BOOL RCTSetProperty(id target, NSString *keypath, id value)
return YES; return YES;
} }
} }
// Set converted value // Set converted value
[target setValue:RCTConvertValue(value, encoding) forKey:key]; [target setValue:RCTConvertValue(value, encoding) forKey:key];
return YES; return YES;
@ -892,7 +891,7 @@ BOOL RCTCopyProperty(id target, id source, NSString *keypath)
SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:", SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",
[[key substringToIndex:1] uppercaseString], [[key substringToIndex:1] uppercaseString],
[key substringFromIndex:1]]); [key substringFromIndex:1]]);
if (![source respondsToSelector:setter] if (![source respondsToSelector:setter]
|| ![target respondsToSelector:setter]) { || ![target respondsToSelector:setter]) {
return NO; return NO;

View File

@ -3,13 +3,25 @@
*/ */
'use strict'; 'use strict';
var fs = require('fs');
var path = require('path');
if (!fs.existsSync(path.resolve(__dirname, '..', 'node_modules'))) {
console.log(
'\n' +
'Could not find dependencies.\n' +
'Ensure dependencies are installed - ' +
'run \'npm install\' from project root.\n'
);
process.exit();
}
var ReactPackager = require('./react-packager'); var ReactPackager = require('./react-packager');
var blacklist = require('./blacklist.js'); var blacklist = require('./blacklist.js');
var connect = require('connect'); var connect = require('connect');
var http = require('http'); var http = require('http');
var launchEditor = require('./launchEditor.js'); var launchEditor = require('./launchEditor.js');
var parseCommandLine = require('./parseCommandLine.js'); var parseCommandLine = require('./parseCommandLine.js');
var path = require('path');
var options = parseCommandLine([{ var options = parseCommandLine([{
command: 'port', command: 'port',

View File

@ -122,6 +122,32 @@ describe('DependencyGraph', function() {
}); });
}); });
pit('should ignore malformed packages', function() {
var root = '/root';
fs.__setMockFilesystem({
'root': {
'index.js': [
'/**',
' * @providesModule index',
' */',
'require("aPackage")',
].join('\n'),
'aPackage': {
'package.json': 'lol',
'main.js': 'lol'
}
}
});
var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher});
return dgraph.load().then(function() {
expect(dgraph.getOrderedDependencies('/root/index.js'))
.toEqual([
{id: 'index', path: '/root/index.js', dependencies: ['aPackage']},
]);
});
});
pit('can have multiple modules with the same name', function() { pit('can have multiple modules with the same name', function() {
var root = '/root'; var root = '/root';
fs.__setMockFilesystem({ fs.__setMockFilesystem({

View File

@ -267,9 +267,15 @@ DependecyGraph.prototype._findAndProcessPackage = function(files, root) {
if (packagePath != null) { if (packagePath != null) {
return readFile(packagePath, 'utf8') return readFile(packagePath, 'utf8')
.then(function(content) { .then(function(content) {
var packageJson = JSON.parse(content); var packageJson;
if (packageJson.name == null) { try {
packageJson = JSON.parse(content);
} catch (e) {
debug('WARNING: malformed package.json: ', packagePath);
return q();
}
if (packageJson.name == null) {
debug( debug(
'WARNING: package.json `%s` is missing a name field', 'WARNING: package.json `%s` is missing a name field',
packagePath packagePath