From 39f475ea9b6d97eff6b4f61ebf8bcb9fab9a7d46 Mon Sep 17 00:00:00 2001 From: Christopher Chedeau Date: Sat, 7 Feb 2015 17:23:25 -0800 Subject: [PATCH] 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 --- Examples/TicTacToe/TicTacToeApp.js | 19 ++-- Examples/UIExplorer/LayoutExample.js | 2 +- Examples/UIExplorer/NavigatorIOSExample.js | 1 + Examples/UIExplorer/ScrollViewExample.js | 2 +- Examples/UIExplorer/UIExplorerList.js | 4 +- Examples/UIExplorer/createExamplePage.js | 3 +- Libraries/Components/ListView/ListView.js | 2 +- .../Components/Navigation/NavigatorIOS.ios.js | 8 ++ .../XMLHttpRequest/XMLHttpRequest.ios.js | 5 ++ ReactKit/Base/RCTConvert.m | 87 +++++++++---------- packager/packager.js | 14 ++- .../__tests__/DependencyGraph-test.js | 26 ++++++ .../haste/DependencyGraph/index.js | 10 ++- 13 files changed, 125 insertions(+), 58 deletions(-) diff --git a/Examples/TicTacToe/TicTacToeApp.js b/Examples/TicTacToe/TicTacToeApp.js index 73440acd2..b91b090c0 100755 --- a/Examples/TicTacToe/TicTacToeApp.js +++ b/Examples/TicTacToe/TicTacToeApp.js @@ -40,7 +40,7 @@ class Board { return this; } - hasMove(row: number, col: number): boolean { + hasMark(row: number, col: number): boolean { return this.grid[row][col] !== 0; } @@ -132,7 +132,10 @@ var Cell = React.createClass({ render() { return ( - + @@ -161,7 +164,10 @@ var GameEndOverlay = React.createClass({ return ( {message} - + New Game @@ -185,7 +191,7 @@ var TicTacToeApp = React.createClass({ }, handleCellPress(row: number, col: number) { - if (this.state.board.hasMove(row, col)) { + if (this.state.board.hasMark(row, col)) { return; } @@ -214,7 +220,10 @@ var TicTacToeApp = React.createClass({ {rows} - + ); } diff --git a/Examples/UIExplorer/LayoutExample.js b/Examples/UIExplorer/LayoutExample.js index 5c8c976a5..746ef0ac6 100644 --- a/Examples/UIExplorer/LayoutExample.js +++ b/Examples/UIExplorer/LayoutExample.js @@ -124,7 +124,7 @@ var LayoutExample = React.createClass({ - {'oooooooooooooooo'.split('').map(() => )} + {'oooooooooooooooo'.split('').map((char, i) => )} diff --git a/Examples/UIExplorer/NavigatorIOSExample.js b/Examples/UIExplorer/NavigatorIOSExample.js index dc04c27c8..fa998528f 100644 --- a/Examples/UIExplorer/NavigatorIOSExample.js +++ b/Examples/UIExplorer/NavigatorIOSExample.js @@ -60,6 +60,7 @@ var NavigatorIOSExample = React.createClass({ this.props.navigator.push({ title: NavigatorIOSExample.title, component: NavigatorIOSExample, + backButtonTitle: 'Custom Back', passProps: {topExampleRoute: this.props.topExampleRoute || this.props.route}, }); })} diff --git a/Examples/UIExplorer/ScrollViewExample.js b/Examples/UIExplorer/ScrollViewExample.js index e9d9c8f93..bfb35d4bc 100644 --- a/Examples/UIExplorer/ScrollViewExample.js +++ b/Examples/UIExplorer/ScrollViewExample.js @@ -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']; THUMBS = THUMBS.concat(THUMBS); // double length of THUMBS -var createThumbRow = (uri, i) => ; +var createThumbRow = (uri, i) => ; var styles = StyleSheet.create({ scrollView: { diff --git a/Examples/UIExplorer/UIExplorerList.js b/Examples/UIExplorer/UIExplorerList.js index 9effbf8e4..af31617e3 100644 --- a/Examples/UIExplorer/UIExplorerList.js +++ b/Examples/UIExplorer/UIExplorerList.js @@ -45,10 +45,10 @@ var UIExplorerList = React.createClass({ ); }, - _renderRow: function(example) { + _renderRow: function(example, i) { invariant(example.title, 'Example must provide a title.'); return ( - + this._onPressRow(example)}> diff --git a/Examples/UIExplorer/createExamplePage.js b/Examples/UIExplorer/createExamplePage.js index 070395dad..39ed81133 100644 --- a/Examples/UIExplorer/createExamplePage.js +++ b/Examples/UIExplorer/createExamplePage.js @@ -20,7 +20,7 @@ var createExamplePage = function(title, exampleModule) { description: exampleModule.description, }, - getBlock: function(example) { + getBlock: function(example, i) { // Hack warning: This is a hack because the www UI explorer requires // renderComponent to be called. var originalRenderComponent = React.renderComponent; @@ -37,6 +37,7 @@ var createExamplePage = function(title, exampleModule) { React.render = originalRender; return ( {renderedComponent} diff --git a/Libraries/Components/ListView/ListView.js b/Libraries/Components/ListView/ListView.js index 844400d66..45539586b 100644 --- a/Libraries/Components/ListView/ListView.js +++ b/Libraries/Components/ListView/ListView.js @@ -104,7 +104,7 @@ var ListView = React.createClass({ initialListSize: PropTypes.number, /** * 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. */ onEndReached: PropTypes.func, diff --git a/Libraries/Components/Navigation/NavigatorIOS.ios.js b/Libraries/Components/Navigation/NavigatorIOS.ios.js index e134f89b8..efd983203 100644 --- a/Libraries/Components/Navigation/NavigatorIOS.ios.js +++ b/Libraries/Components/Navigation/NavigatorIOS.ios.js @@ -179,6 +179,13 @@ var NavigatorIOS = React.createClass({ */ 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 */ @@ -493,6 +500,7 @@ var NavigatorIOS = React.createClass({ this.props.itemWrapperStyle, route.wrapperStyle ]} + backButtonTitle={route.backButtonTitle} rightButtonTitle={route.rightButtonTitle} onNavRightButtonTap={route.onRightButtonPress} tintColor={this.props.tintColor}> diff --git a/Libraries/XMLHttpRequest/XMLHttpRequest.ios.js b/Libraries/XMLHttpRequest/XMLHttpRequest.ios.js index eb84c8350..042cbe4b9 100644 --- a/Libraries/XMLHttpRequest/XMLHttpRequest.ios.js +++ b/Libraries/XMLHttpRequest/XMLHttpRequest.ios.js @@ -58,6 +58,11 @@ class XMLHttpRequest { return ''; } + getResponseHeader(header: string): ?string { + /* Stub */ + return ''; + } + setRequestHeader(header: string, value: any): void { this._headers[header] = value; } diff --git a/ReactKit/Base/RCTConvert.m b/ReactKit/Base/RCTConvert.m index c77bef3fd..40519d812 100644 --- a/ReactKit/Base/RCTConvert.m +++ b/ReactKit/Base/RCTConvert.m @@ -114,7 +114,7 @@ RCT_CONVERTER_CUSTOM(NSUInteger, NSUInteger, [json unsignedIntegerValue]) RCTLogMustFix(@"Expected NSString for NSURL, received %@: %@", [json class], json); return nil; } - + NSString *path = json; if ([path isAbsolutePath]) { @@ -194,15 +194,15 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"] if (color) { return color; } - + if ([json isKindOfClass:[NSString class]]) { - + // Check named colors static NSDictionary *namedColors = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ namedColors = @{ - + // CSS colors @"aliceblue": @"#f0f8ff", @"antiquewhite": @"#faebd7", @@ -352,17 +352,16 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"] @"whitesmoke": @"#f5f5f5", @"yellow": @"#ffff00", @"yellowgreen": @"#9acd32", - + // Nonstandard color extensions @"transparent": @"rgba(0,0,0,0)", - @"clear": @"rgba(0,0,0,0)", }; }); NSString *colorString = namedColors[json]; if (!colorString) { colorString = json; } - + // Parse color NSUInteger red = -1; NSUInteger green = -1; @@ -384,32 +383,32 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"] } else { color = [UIColor colorWithRed:red / 255.0 green:green / 255.0 blue:blue / 255.0 alpha:alpha]; } - + } else if ([json isKindOfClass:[NSArray class]]) { - + if ([json count] < 3 || [json count] > 4) { - + RCTLogMustFix(@"Expected array with count 3 or 4, but count is %zd: %@", [json count], json); - + } else { - + // Color array color = [UIColor colorWithRed:[json[0] doubleValue] green:[json[1] doubleValue] blue:[json[2] doubleValue] alpha:[json count] > 3 ? [json[3] doubleValue] : 1]; } - + } else if ([json isKindOfClass:[NSDictionary class]]) { - + // Color dictionary color = [UIColor colorWithRed:[json[@"r"] doubleValue] green:[json[@"g"] doubleValue] blue:[json[@"b"] doubleValue] alpha:[json[@"a"] ?: @1 doubleValue]]; - + } else if (json && ![json isKindOfClass:[NSNull class]]) { - + 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) { color = [UIColor whiteColor]; } - + // Cache and return if (json) { 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); return nil; } - + if ([json length] == 0) { return nil; } - + UIImage *image = nil; NSString *path = json; if ([path isAbsolutePath]) { @@ -558,13 +557,13 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"] { // Create descriptor UIFontDescriptor *fontDescriptor = font.fontDescriptor ?: [UIFontDescriptor fontDescriptorWithName:RCTDefaultFontName size:RCTDefaultFontSize]; - + // Get font size CGFloat fontSize = [self CGFloat:size]; if (fontSize && !isnan(fontSize)) { fontDescriptor = [fontDescriptor fontDescriptorWithSize:fontSize]; } - + // Get font family NSString *familyName = [RCTConvert NSString:family]; if (familyName) { @@ -584,21 +583,21 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"] fontDescriptor = [fontDescriptor fontDescriptorWithFamily:familyName]; } } - + // Get font weight NSString *fontWeight = [RCTConvert NSString:weight]; if (fontWeight) { - + static NSSet *values; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ values = [NSSet setWithObjects:@"bold", @"normal", nil]; }); - + if (fontWeight && ![values containsObject:fontWeight]) { RCTLogError(@"Unrecognized font weight '%@', must be one of %@", fontWeight, values); } - + UIFontDescriptorSymbolicTraits symbolicTraits = fontDescriptor.symbolicTraits; if ([fontWeight isEqualToString:RCTBoldFontWeight]) { symbolicTraits |= UIFontDescriptorTraitBold; @@ -607,9 +606,9 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"] } fontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits:symbolicTraits]; } - + // TODO: font style - + // Create font return [UIFont fontWithDescriptor:fontDescriptor size:fontDescriptor.pointSize]; } @@ -670,7 +669,7 @@ static NSString *RCTGuessTypeEncoding(id target, NSString *key, id value, NSStri return @"@\"UIColor\""; } } - + return nil; } @@ -679,15 +678,15 @@ static NSDictionary *RCTConvertValue(id value, NSString *encoding) static NSDictionary *converters = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - + id (^numberConvert)(id) = ^(id val){ return [RCTConvert NSNumber:val]; }; - + id (^boolConvert)(id) = ^(id val){ return @([RCTConvert BOOL:val]); }; - + // TODO (#5906496): add the rest of RCTConvert here converters = @{ @@ -750,7 +749,7 @@ static NSDictionary *RCTConvertValue(id value, NSString *encoding) if (value == [NSNull null] && ![encoding isEqualToString:@"@\"NSNull\""]) { return nil; } - + // Convert value id (^converter)(id) = converters[encoding]; return converter ? converter(value) : value; @@ -772,23 +771,23 @@ BOOL RCTSetProperty(id target, NSString *keypath, id value) NSString *encoding = nil; objc_property_t property = class_getProperty([target class], [key UTF8String]); if (property) { - + // Get type info char *typeEncoding = property_copyAttributeValue(property, "T"); encoding = @(typeEncoding); free(typeEncoding); - + } else { - + // Check if setter exists SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:", [[key substringToIndex:1] uppercaseString], [key substringFromIndex:1]]); - + if (![target respondsToSelector:setter]) { return NO; } - + // Get type of first method argument Method method = class_getInstanceMethod([target class], setter); char *typeEncoding = method_copyArgumentType(method, 2); @@ -797,17 +796,17 @@ BOOL RCTSetProperty(id target, NSString *keypath, id value) free(typeEncoding); } } - + if (encoding.length == 0 || [encoding isEqualToString:@(@encode(id))]) { // Not enough info about the type encoding to be useful, so // try to guess the type from the value and property name encoding = RCTGuessTypeEncoding(target, key, value, encoding); } - + // Special case for numeric encodings, which may be enums if ([value isKindOfClass:[NSString class]] && [@"iIsSlLqQ" containsString:[encoding substringToIndex:1]]) { - + /** * NOTE: the property names below may seem weird, but it's * 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 if ([target isKindOfClass:[UITextField class]]) { static NSDictionary *specialCases = nil; @@ -859,7 +858,7 @@ BOOL RCTSetProperty(id target, NSString *keypath, id value) @"enablesReturnKeyAutomatically": ^(UITextField *f, NSInteger v){ f.enablesReturnKeyAutomatically = !!v; }, @"secureTextEntry": ^(UITextField *f, NSInteger v){ f.secureTextEntry = !!v; }}; }); - + void (^block)(UITextField *f, NSInteger v) = specialCases[key]; if (block) { @@ -867,7 +866,7 @@ BOOL RCTSetProperty(id target, NSString *keypath, id value) return YES; } } - + // Set converted value [target setValue:RCTConvertValue(value, encoding) forKey:key]; return YES; @@ -892,7 +891,7 @@ BOOL RCTCopyProperty(id target, id source, NSString *keypath) SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:", [[key substringToIndex:1] uppercaseString], [key substringFromIndex:1]]); - + if (![source respondsToSelector:setter] || ![target respondsToSelector:setter]) { return NO; diff --git a/packager/packager.js b/packager/packager.js index 4fcee0a3c..b59fbb18b 100644 --- a/packager/packager.js +++ b/packager/packager.js @@ -3,13 +3,25 @@ */ '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 blacklist = require('./blacklist.js'); var connect = require('connect'); var http = require('http'); var launchEditor = require('./launchEditor.js'); var parseCommandLine = require('./parseCommandLine.js'); -var path = require('path'); var options = parseCommandLine([{ command: 'port', diff --git a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/__tests__/DependencyGraph-test.js b/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/__tests__/DependencyGraph-test.js index 9eeb96859..fbd017250 100644 --- a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/__tests__/DependencyGraph-test.js +++ b/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/__tests__/DependencyGraph-test.js @@ -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() { var root = '/root'; fs.__setMockFilesystem({ diff --git a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js b/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js index f80bd0b3b..130708b5c 100644 --- a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js +++ b/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js @@ -267,9 +267,15 @@ DependecyGraph.prototype._findAndProcessPackage = function(files, root) { if (packagePath != null) { return readFile(packagePath, 'utf8') .then(function(content) { - var packageJson = JSON.parse(content); - if (packageJson.name == null) { + var packageJson; + try { + packageJson = JSON.parse(content); + } catch (e) { + debug('WARNING: malformed package.json: ', packagePath); + return q(); + } + if (packageJson.name == null) { debug( 'WARNING: package.json `%s` is missing a name field', packagePath