Merge pull request #1839 from a2/Update_Wed_1_Jul

Updates from Wed 1 Jul
This commit is contained in:
Alexsander Akers 2015-07-02 12:15:35 +01:00
Родитель 4e6f48c650 13be9454cc
Коммит 1d1386e735
44 изменённых файлов: 272 добавлений и 511 удалений

Просмотреть файл

@ -40,9 +40,9 @@ suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-2]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-2]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-3]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-3]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
[version]
0.12.0
0.13.1

Просмотреть файл

@ -15,13 +15,13 @@ install:
- cp $(brew --prefix nvm)/nvm-exec .nvm/
- export NVM_DIR=.nvm
- source $(brew --prefix nvm)/nvm.sh
- nvm install v0.10
- nvm install iojs-v2
- npm config set spin=false
- npm install
script:
- |
nvm use v0.10
nvm use iojs-v2
if [ "$TEST_TYPE" = objc ]
then

Просмотреть файл

@ -26,6 +26,8 @@ var {
} = React;
var TimerMixin = require('react-timer-mixin');
var invariant = require('invariant');
var MovieCell = require('./MovieCell');
var MovieScreen = require('./MovieScreen');
@ -73,18 +75,16 @@ var SearchScreen = React.createClass({
this.searchMovies('');
},
_urlForQueryAndPage: function(query: string, pageNumber: ?number): string {
_urlForQueryAndPage: function(query: string, pageNumber: number): string {
var apiKey = API_KEYS[this.state.queryNumber % API_KEYS.length];
if (query) {
return (
// $FlowFixMe(>=0.13.0) - pageNumber may be null or undefined
API_URL + 'movies.json?apikey=' + apiKey + '&q=' +
encodeURIComponent(query) + '&page_limit=20&page=' + pageNumber
);
} else {
// With no query, load latest movies
return (
// $FlowFixMe(>=0.13.0) - pageNumber may be null or undefined
API_URL + 'lists/movies/in_theaters.json?apikey=' + apiKey +
'&page_limit=20&page=' + pageNumber
);
@ -176,6 +176,7 @@ var SearchScreen = React.createClass({
});
var page = resultsCache.nextPageNumberForQuery[query];
invariant(page != null, 'Next page number for "%s" is missing', query);
fetch(this._urlForQueryAndPage(query, page))
.then((response) => response.json())
.catch((error) => {

Просмотреть файл

@ -33,4 +33,4 @@ node_modules/react-native/Libraries/react-native/react-native-interface.js
module.system=haste
[version]
0.12.0
0.13.1

Просмотреть файл

@ -17,11 +17,12 @@
var React = require('react-native');
var {
ActionSheetIOS,
StyleSheet,
Text,
View,
} = React;
var ActionSheetIOS = require('ActionSheetIOS');
var BUTTONS = [
'Button Index: 0',
'Button Index: 1',

Просмотреть файл

@ -15,10 +15,9 @@
*/
'use strict';
var AdSupportIOS = require('AdSupportIOS');
var React = require('react-native');
var {
AdSupportIOS,
StyleSheet,
Text,
View,

Просмотреть файл

@ -16,9 +16,9 @@
'use strict';
var React = require('react-native');
var StyleSheet = require('StyleSheet');
var {
MapView,
StyleSheet,
Text,
TextInput,
View,

Просмотреть файл

@ -6,12 +6,14 @@
'use strict';
var React = require('React');
var {
StyleSheet,
View,
} = React;
var StyleSheet = require('StyleSheet');
var TimerMixin = require('react-timer-mixin');
var UIExplorerBlock = require('UIExplorerBlock');
var UIExplorerPage = require('UIExplorerPage');
var View = require('View');
var UIExplorerBlock = require('./UIExplorerBlock');
var UIExplorerPage = require('./UIExplorerPage');
var TransformExample = React.createClass({

Просмотреть файл

@ -17,14 +17,16 @@
'use strict';
var React = require('react-native');
var Dimensions = require('Dimensions');
var DrawerLayoutAndroid = require('DrawerLayoutAndroid');
var ToolbarAndroid = require('ToolbarAndroid');
var UIExplorerList = require('./UIExplorerList');
var {
Dimensions,
StyleSheet,
View,
} = React;
var UIExplorerList = require('./UIExplorerList');
// TODO: these should be exposed by the 'react-native' module.
var DrawerLayoutAndroid = require('DrawerLayoutAndroid');
var ToolbarAndroid = require('ToolbarAndroid');
var DRAWER_WIDTH_LEFT = 56;

Просмотреть файл

@ -21,6 +21,7 @@ var {
ListView,
PixelRatio,
Platform,
Settings,
StyleSheet,
Text,
TextInput,
@ -29,13 +30,20 @@ var {
} = React;
var { TestModule } = React.addons;
var Settings = require('Settings');
import type { ExampleModule } from 'ExampleTypes';
var createExamplePage = require('./createExamplePage');
var COMMON_COMPONENTS = [
require('./ImageExample'),
require('./ListViewExample'),
require('./ListViewPagingExample'),
require('./MapViewExample'),
require('./Navigator/NavigatorExample'),
require('./ScrollViewExample'),
require('./TextInputExample'),
require('./TouchableExample'),
require('./ViewExample'),
require('./WebViewExample'),
];
@ -51,23 +59,15 @@ if (Platform.OS === 'ios') {
var COMPONENTS = COMMON_COMPONENTS.concat([
require('./ActivityIndicatorIOSExample'),
require('./DatePickerIOSExample'),
require('./ImageExample'),
require('./ListViewExample'),
require('./ListViewPagingExample'),
require('./MapViewExample'),
require('./Navigator/NavigatorExample'),
require('./NavigatorIOSColorsExample'),
require('./NavigatorIOSExample'),
require('./PickerIOSExample'),
require('./ProgressViewIOSExample'),
require('./ScrollViewExample'),
require('./SegmentedControlIOSExample'),
require('./SliderIOSExample'),
require('./SwitchIOSExample'),
require('./TabBarIOSExample'),
require('./TextExample.ios'),
require('./TextInputExample'),
require('./TouchableExample'),
]);
var APIS = COMMON_APIS.concat([

Просмотреть файл

@ -16,7 +16,6 @@
'use strict';
var React = require('react-native');
var StyleSheet = require('StyleSheet');
var {
StyleSheet,
Text,

Просмотреть файл

@ -20,6 +20,12 @@ var Touchable = require('Touchable');
var merge = require('merge');
var onlyChild = require('onlyChild');
var invariant = require('invariant');
invariant(
AnimationExperimental || POPAnimation,
'Please add the RCTAnimationExperimental framework to your project, or add //Libraries/FBReactKit:RCTPOPAnimation to your BUCK file if running internally within Facebook.'
);
type State = {
animationID: ?number;
};

Просмотреть файл

@ -43,6 +43,8 @@ var NavigationType = {
other: RCTWebViewManager.NavigationType.Other,
};
var JSNavigationScheme = RCTWebViewManager.JSNavigationScheme;
type ErrorEvent = {
domain: any;
code: any;
@ -75,6 +77,7 @@ var defaultRenderError = (errorDomain, errorCode, errorDesc) => (
var WebView = React.createClass({
statics: {
JSNavigationScheme: JSNavigationScheme,
NavigationType: NavigationType,
},
@ -86,7 +89,6 @@ var WebView = React.createClass({
bounces: PropTypes.bool,
scrollEnabled: PropTypes.bool,
automaticallyAdjustContentInsets: PropTypes.bool,
shouldInjectAJAXHandler: PropTypes.bool,
contentInset: EdgeInsetsPropType,
onNavigationStateChange: PropTypes.func,
startInLoadingState: PropTypes.bool, // force WebView to show loadingView on first load
@ -95,6 +97,11 @@ var WebView = React.createClass({
* Used for android only, JS is enabled by default for WebView on iOS
*/
javaScriptEnabledAndroid: PropTypes.bool,
/**
* Used for iOS only, sets the JS to be injected when the webpage loads.
*/
injectedJavascriptIOS: PropTypes.string,
/**
* Used for iOS only, sets whether the webpage scales to fit the view and the
* user can change the scale
@ -152,9 +159,9 @@ var WebView = React.createClass({
style={webViewStyles}
url={this.props.url}
html={this.props.html}
injectedJavascriptIOS={this.props.injectedJavascriptIOS}
bounces={this.props.bounces}
scrollEnabled={this.props.scrollEnabled}
shouldInjectAJAXHandler={this.props.shouldInjectAJAXHandler}
contentInset={this.props.contentInset}
automaticallyAdjustContentInsets={this.props.automaticallyAdjustContentInsets}
onLoadingStart={this.onLoadingStart}

Просмотреть файл

@ -14,7 +14,7 @@ typedef void (^RCTImageDownloadBlock)(UIImage *image, NSError *error);
@interface RCTImageDownloader : NSObject
+ (instancetype)sharedInstance;
+ (RCTImageDownloader *)sharedInstance;
/**
* Downloads a block of raw data and returns it. Note that the callback block

Просмотреть файл

@ -9,25 +9,27 @@
#import "RCTImageDownloader.h"
#import "RCTCache.h"
#import "RCTLog.h"
#import "RCTUtils.h"
typedef void (^RCTCachedDataDownloadBlock)(BOOL cached, NSData *data, NSError *error);
CGSize RCTTargetSizeForClipRect(CGRect);
CGRect RCTClipRect(CGSize, CGFloat, CGSize, CGFloat, UIViewContentMode);
@implementation RCTImageDownloader
{
RCTCache *_cache;
NSURLCache *_cache;
dispatch_queue_t _processingQueue;
NSMutableDictionary *_pendingBlocks;
}
+ (instancetype)sharedInstance
+ (RCTImageDownloader *)sharedInstance
{
static RCTImageDownloader *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
sharedInstance = [[RCTImageDownloader alloc] init];
});
return sharedInstance;
}
@ -35,27 +37,22 @@ typedef void (^RCTCachedDataDownloadBlock)(BOOL cached, NSData *data, NSError *e
- (instancetype)init
{
if ((self = [super init])) {
_cache = [[RCTCache alloc] initWithName:@"RCTImageDownloader"];
_cache = [[NSURLCache alloc] initWithMemoryCapacity:5 * 1024 * 1024 diskCapacity:200 * 1024 * 1024 diskPath:@"React/RCTImageDownloader"];
_processingQueue = dispatch_queue_create("com.facebook.React.DownloadProcessingQueue", DISPATCH_QUEUE_SERIAL);
_pendingBlocks = [[NSMutableDictionary alloc] init];
}
return self;
}
static NSString *RCTCacheKeyForURL(NSURL *url)
{
return url.absoluteString;
return self;
}
- (id)_downloadDataForURL:(NSURL *)url block:(RCTCachedDataDownloadBlock)block
{
NSString *cacheKey = RCTCacheKeyForURL(url);
NSString *cacheKey = url.absoluteString;
__block BOOL cancelled = NO;
__block NSURLSessionDataTask *task = nil;
dispatch_block_t cancel = ^{
cancelled = YES;
dispatch_async(_processingQueue, ^{
@ -88,21 +85,28 @@ static NSString *RCTCacheKeyForURL(NSURL *url)
});
};
if ([_cache hasDataForKey:cacheKey]) {
[_cache fetchDataForKey:cacheKey completionHandler:^(NSData *data) {
if (!cancelled) {
runBlocks(YES, data, nil);
}
}];
} else {
task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!cancelled) {
runBlocks(NO, data, error);
}
}];
task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!cancelled) {
runBlocks(NO, data, error);
}
[task resume];
}
RCTImageDownloader *strongSelf = weakSelf;
NSCachedURLResponse *cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:response data:data userInfo:nil storagePolicy:NSURLCacheStorageAllowed];
[strongSelf->_cache storeCachedResponse:cachedResponse forDataTask:task];
task = nil;
}];
[_cache getCachedResponseForDataTask:task completionHandler:^(NSCachedURLResponse *cachedResponse) {
if (cancelled) {
return;
}
if (cachedResponse) {
runBlocks(YES, cachedResponse.data, nil);
} else {
[task resume];
}
}];
}
});
@ -111,22 +115,78 @@ static NSString *RCTCacheKeyForURL(NSURL *url)
- (id)downloadDataForURL:(NSURL *)url block:(RCTDataDownloadBlock)block
{
NSString *cacheKey = RCTCacheKeyForURL(url);
__weak RCTImageDownloader *weakSelf = self;
return [self _downloadDataForURL:url block:^(BOOL cached, NSData *data, NSError *error) {
if (!cached) {
RCTImageDownloader *strongSelf = weakSelf;
[strongSelf->_cache setData:data forKey:cacheKey];
}
block(data, error);
}];
}
- (id)downloadImageForURL:(NSURL *)url
size:(CGSize)size
scale:(CGFloat)scale
resizeMode:(UIViewContentMode)resizeMode
backgroundColor:(UIColor *)backgroundColor
block:(RCTImageDownloadBlock)block
{
return [self downloadDataForURL:url block:^(NSData *data, NSError *error) {
if (!data || error) {
block(nil, error);
return;
}
if (CGSizeEqualToSize(size, CGSizeZero)) {
// Target size wasn't available yet, so abort image drawing
block(nil, nil);
return;
}
UIImage *image = [UIImage imageWithData:data scale:scale];
if (image) {
// Get scale and size
CGFloat destScale = scale ?: RCTScreenScale();
CGRect imageRect = RCTClipRect(image.size, image.scale, size, destScale, resizeMode);
CGSize destSize = RCTTargetSizeForClipRect(imageRect);
// Opacity optimizations
UIColor *blendColor = nil;
BOOL opaque = !RCTImageHasAlpha(image.CGImage);
if (!opaque && backgroundColor) {
CGFloat alpha;
[backgroundColor getRed:NULL green:NULL blue:NULL alpha:&alpha];
if (alpha > 0.999) { // no benefit to blending if background is translucent
opaque = YES;
blendColor = backgroundColor;
}
}
// Decompress image at required size
UIGraphicsBeginImageContextWithOptions(destSize, opaque, destScale);
if (blendColor) {
[blendColor setFill];
UIRectFill((CGRect){CGPointZero, destSize});
}
[image drawInRect:imageRect];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
block(image, nil);
}];
}
- (void)cancelDownload:(id)downloadToken
{
if (downloadToken) {
((dispatch_block_t)downloadToken)();
}
}
@end
/**
* Returns the optimal context size for an image drawn using the clip rect
* returned by RCTClipRect.
*/
CGSize RCTTargetSizeForClipRect(CGRect);
CGSize RCTTargetSizeForClipRect(CGRect clipRect)
{
return (CGSize){
@ -141,7 +201,6 @@ CGSize RCTTargetSizeForClipRect(CGRect clipRect)
* then calculates the optimal rectangle to draw the image into so that it will
* be sized and positioned correctly if drawn using the specified content mode.
*/
CGRect RCTClipRect(CGSize, CGFloat, CGSize, CGFloat, UIViewContentMode);
CGRect RCTClipRect(CGSize sourceSize, CGFloat sourceScale,
CGSize destSize, CGFloat destScale,
UIViewContentMode resizeMode)
@ -202,66 +261,3 @@ CGRect RCTClipRect(CGSize sourceSize, CGFloat sourceScale,
return (CGRect){CGPointZero, destSize};
}
}
- (id)downloadImageForURL:(NSURL *)url
size:(CGSize)size
scale:(CGFloat)scale
resizeMode:(UIViewContentMode)resizeMode
backgroundColor:(UIColor *)backgroundColor
block:(RCTImageDownloadBlock)block
{
return [self downloadDataForURL:url block:^(NSData *data, NSError *error) {
if (!data || error) {
block(nil, error);
return;
}
if (CGSizeEqualToSize(size, CGSizeZero)) {
// Target size wasn't available yet, so abort image drawing
block(nil, nil);
return;
}
UIImage *image = [UIImage imageWithData:data scale:scale];
if (image) {
// Get scale and size
CGFloat destScale = scale ?: RCTScreenScale();
CGRect imageRect = RCTClipRect(image.size, image.scale, size, destScale, resizeMode);
CGSize destSize = RCTTargetSizeForClipRect(imageRect);
// Opacity optimizations
UIColor *blendColor = nil;
BOOL opaque = !RCTImageHasAlpha(image.CGImage);
if (!opaque && backgroundColor) {
CGFloat alpha;
[backgroundColor getRed:NULL green:NULL blue:NULL alpha:&alpha];
if (alpha > 0.999) { // no benefit to blending if background is translucent
opaque = YES;
blendColor = backgroundColor;
}
}
// Decompress image at required size
UIGraphicsBeginImageContextWithOptions(destSize, opaque, destScale);
if (blendColor) {
[blendColor setFill];
UIRectFill((CGRect){CGPointZero, destSize});
}
[image drawInRect:imageRect];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
block(image, nil);
}];
}
- (void)cancelDownload:(id)downloadToken
{
if (downloadToken) {
((dispatch_block_t)downloadToken)();
}
}
@end

Просмотреть файл

@ -21,11 +21,6 @@ var setImmediate = require('setImmediate');
type Handle = number;
/**
* Maximum time a handle can be open before warning in DEV.
*/
var DEV_TIMEOUT = 2000;
var _emitter = new EventEmitter();
var _interactionSet = new Set();
var _addInteractionSet = new Set();
@ -94,14 +89,6 @@ var InteractionManager = {
scheduleUpdate();
var handle = ++_inc;
_addInteractionSet.add(handle);
if (__DEV__) {
// Capture the stack trace of what created the handle.
var error = new Error(
'InteractionManager: interaction handle not cleared within ' +
DEV_TIMEOUT + ' ms.'
);
setDevTimeoutHandle(handle, error, DEV_TIMEOUT);
}
return handle;
},
@ -166,19 +153,4 @@ function processUpdate() {
_deleteInteractionSet.clear();
}
/**
* Wait until `timeout` has passed and warn if the handle has not been cleared.
*/
function setDevTimeoutHandle(
handle: Handle,
error: Error,
timeout: number
): void {
setTimeout(() => {
if (_interactionSet.has(handle)) {
console.warn(error.message + '\n' + error.stack);
}
}, timeout);
}
module.exports = InteractionManager;

Просмотреть файл

@ -55,7 +55,7 @@ RCT_EXPORT_METHOD(verifySnapshot:(RCTResponseSenderBlock)callback)
}];
}
RCT_EXPORT_METHOD(sendAppEvent:(NSString *)name body:(id)body)
RCT_EXPORT_METHOD(sendAppEvent:(NSString *)name body:(nullable id)body)
{
[_bridge.eventDispatcher sendAppEventWithName:name body:body];
}

4
Libraries/react-native/react-native.js поставляемый
Просмотреть файл

@ -42,11 +42,14 @@ var ReactNative = Object.assign(Object.create(require('React')), {
WebView: require('WebView'),
// APIs
ActionSheetIOS: require('ActionSheetIOS'),
AdSupportIOS: require('AdSupportIOS'),
AlertIOS: require('AlertIOS'),
AppRegistry: require('AppRegistry'),
AppStateIOS: require('AppStateIOS'),
AsyncStorage: require('AsyncStorage'),
CameraRoll: require('CameraRoll'),
Dimensions: require('Dimensions'),
ImagePickerIOS: require('ImagePickerIOS'),
InteractionManager: require('InteractionManager'),
LayoutAnimation: require('LayoutAnimation'),
@ -55,6 +58,7 @@ var ReactNative = Object.assign(Object.create(require('React')), {
PanResponder: require('PanResponder'),
PixelRatio: require('PixelRatio'),
PushNotificationIOS: require('PushNotificationIOS'),
Settings: require('Settings'),
StatusBarIOS: require('StatusBarIOS'),
StyleSheet: require('StyleSheet'),
VibrationIOS: require('VibrationIOS'),

Просмотреть файл

@ -22,7 +22,7 @@ Pod::Spec.new do |s|
s.default_subspec = 'Core'
s.requires_arc = true
s.platform = :ios, "7.0"
s.prepare_command = 'npm install'
s.prepare_command = 'npm install --production'
s.preserve_paths = "cli.js", "Libraries/**/*.js", "lint", "linter.js", "node_modules", "package.json", "packager", "PATENTS", "react-native-cli"
s.header_mappings_dir = "."

Просмотреть файл

@ -219,6 +219,9 @@ RCT_NOT_IMPLEMENTED(-initWithBundleURL:(__unused NSURL *)bundleURL
[_frameUpdateObservers addObject:moduleData];
}
}
[[NSNotificationCenter defaultCenter] postNotificationName:RCTDidCreateNativeModules
object:self];
}
- (void)initJS
@ -721,7 +724,7 @@ RCT_NOT_IMPLEMENTED(-initWithBundleURL:(__unused NSURL *)bundleURL
RCTProfileEndEvent(@"DispatchFrameUpdate", @"objc_call", nil);
dispatch_async(dispatch_get_main_queue(), ^{
[self.perfStats.jsGraph tick:displayLink.timestamp];
[self.perfStats.jsGraph onTick:displayLink.timestamp];
});
}
@ -731,7 +734,7 @@ RCT_NOT_IMPLEMENTED(-initWithBundleURL:(__unused NSURL *)bundleURL
RCTProfileImmediateEvent(@"VSYNC", displayLink.timestamp, @"g");
[self.perfStats.uiGraph tick:displayLink.timestamp];
[self.perfStats.uiGraph onTick:displayLink.timestamp];
}
- (void)startProfiling

Просмотреть файл

@ -33,6 +33,11 @@ RCT_EXTERN NSString *const RCTJavaScriptDidLoadNotification;
*/
RCT_EXTERN NSString *const RCTJavaScriptDidFailToLoadNotification;
/**
* This notification fires when the bridge created all registered native modules
*/
RCT_EXTERN NSString *const RCTDidCreateNativeModules;
/**
* This block can be used to instantiate modules that require additional
* init parameters, or additional configuration prior to being used.

Просмотреть файл

@ -20,6 +20,7 @@
NSString *const RCTReloadNotification = @"RCTReloadNotification";
NSString *const RCTJavaScriptDidLoadNotification = @"RCTJavaScriptDidLoadNotification";
NSString *const RCTJavaScriptDidFailToLoadNotification = @"RCTJavaScriptDidFailToLoadNotification";
NSString *const RCTDidCreateNativeModules = @"RCTDidCreateNativeModules";
@class RCTBatchedBridge;

Просмотреть файл

@ -1,29 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
@interface RCTCache : NSObject
- (instancetype)init; // name = @"default"
- (instancetype)initWithName:(NSString *)name;
@property (nonatomic, assign) NSUInteger maximumDiskSize; // in bytes
#pragma mark - Retrieval
- (BOOL)hasDataForKey:(NSString *)key;
- (void)fetchDataForKey:(NSString *)key completionHandler:(void (^)(NSData *data))completionHandler;
#pragma mark - Insertion
- (void)setData:(NSData *)data forKey:(NSString *)key;
- (void)removeAllData;
@end

Просмотреть файл

@ -1,234 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "RCTCache.h"
#import <UIKit/UIKit.h>
#import <sys/xattr.h>
#import "RCTAssert.h"
static NSString *const RCTCacheSubdirectoryName = @"React";
static NSString *const RCTKeyExtendedAttributeName = @"com.facebook.React.RCTCacheManager.Key";
static NSMapTable *RCTLivingCachesByName;
static NSError *RCTPOSIXError(int errorNumber)
{
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: @(strerror(errorNumber))
};
return [NSError errorWithDomain:NSPOSIXErrorDomain code:errorNumber userInfo:userInfo];
}
static NSString *RCTGetExtendedAttribute(NSURL *fileURL, NSString *key, NSError **error)
{
const char *path = fileURL.fileSystemRepresentation;
ssize_t length = getxattr(path, key.UTF8String, NULL, 0, 0, 0);
if (length <= 0) {
if (error) *error = RCTPOSIXError(errno);
return nil;
}
char *buffer = malloc(length);
length = getxattr(path, key.UTF8String, buffer, length, 0, 0);
if (length > 0) {
return [[NSString alloc] initWithBytesNoCopy:buffer length:length encoding:NSUTF8StringEncoding freeWhenDone:YES];
}
free(buffer);
if (error) *error = RCTPOSIXError(errno);
return nil;
}
static BOOL RCTSetExtendedAttribute(NSURL *fileURL, NSString *key, NSString *value, NSError **error)
{
const char *path = fileURL.fileSystemRepresentation;
int result;
if (value) {
const char *valueUTF8String = value.UTF8String;
result = setxattr(path, key.UTF8String, valueUTF8String, strlen(valueUTF8String), 0, 0);
} else {
result = removexattr(path, key.UTF8String, 0);
}
if (result) {
if (error) *error = RCTPOSIXError(errno);
return NO;
}
return YES;
}
#pragma mark - Cache Record -
@interface RCTCacheRecord : NSObject
@property (readonly) NSUUID *UUID;
@property (readonly, weak) dispatch_queue_t queue;
@property (nonatomic, copy) NSData *data;
@end
@implementation RCTCacheRecord
- (instancetype)initWithUUID:(NSUUID *)UUID
{
if ((self = [super init])) {
_UUID = [UUID copy];
}
return self;
}
- (void)enqueueBlock:(dispatch_block_t)block
{
dispatch_queue_t queue = _queue;
if (!queue) {
NSString *queueName = [NSString stringWithFormat:@"com.facebook.React.RCTCache.%@", _UUID.UUIDString];
queue = dispatch_queue_create(queueName.UTF8String, DISPATCH_QUEUE_SERIAL);
_queue = queue;
}
dispatch_async(queue, block);
}
@end
#pragma mark - Cache
@implementation RCTCache
{
NSString *_name;
NSFileManager *_fileManager;
NSMutableDictionary *_storage;
NSURL *_cacheDirectoryURL;
}
+ (void)initialize
{
if (self == [RCTCache class]) {
RCTLivingCachesByName = [NSMapTable strongToWeakObjectsMapTable];
}
}
- (instancetype)init
{
return [self initWithName:@"default"];
}
- (instancetype)initWithName:(NSString *)name
{
RCTAssertParam(name);
RCTAssert(name.length < NAME_MAX, @"Name must be fewer than %i characters in length.", NAME_MAX);
RCTCache *cachedCache = [RCTLivingCachesByName objectForKey:name];
if (cachedCache) {
self = cachedCache;
return self;
}
if ((self = [super init])) {
_name = [name copy];
_fileManager = [[NSFileManager alloc] init];
_storage = [NSMutableDictionary dictionary];
NSURL *cacheDirectoryURL = [[_fileManager URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject];
cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:RCTCacheSubdirectoryName isDirectory:YES];
_cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:name isDirectory:YES];
[_fileManager createDirectoryAtURL:_cacheDirectoryURL withIntermediateDirectories:YES attributes:nil error:NULL];
NSArray *fileURLs = [_fileManager contentsOfDirectoryAtURL:_cacheDirectoryURL includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsHiddenFiles error:NULL];
for (NSURL *fileURL in fileURLs) {
NSUUID *UUID = [[NSUUID alloc] initWithUUIDString:fileURL.lastPathComponent];
if (!UUID) continue;
NSString *key = RCTGetExtendedAttribute(fileURL, RCTKeyExtendedAttributeName, NULL);
if (!key) {
[_fileManager removeItemAtURL:fileURL error:NULL];
continue;
}
_storage[key] = [[RCTCacheRecord alloc] initWithUUID:UUID];
}
}
return self;
}
- (BOOL)hasDataForKey:(NSString *)key
{
return _storage[key] != nil;
}
- (void)fetchDataForKey:(NSString *)key completionHandler:(void (^)(NSData *))completionHandler
{
NSParameterAssert(key.length > 0);
NSParameterAssert(completionHandler != nil);
RCTCacheRecord *record = _storage[key];
if (!record) {
completionHandler(nil);
return;
}
[record enqueueBlock:^{
if (!record.data) {
record.data = [NSData dataWithContentsOfURL:[_cacheDirectoryURL URLByAppendingPathComponent:record.UUID.UUIDString]];
}
completionHandler(record.data);
}];
}
- (void)setData:(NSData *)data forKey:(NSString *)key
{
NSParameterAssert(key.length > 0);
RCTCacheRecord *record = _storage[key];
if (!record) {
if (!data) return;
record = [[RCTCacheRecord alloc] initWithUUID:[NSUUID UUID]];
_storage[key] = record;
}
NSURL *fileURL = [_cacheDirectoryURL URLByAppendingPathComponent:record.UUID.UUIDString];
UIBackgroundTaskIdentifier identifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
[record enqueueBlock:^{
if (data) {
[data writeToURL:fileURL options:NSDataWritingAtomic error:NULL];
RCTSetExtendedAttribute(fileURL, RCTKeyExtendedAttributeName, key, NULL);
} else {
[_fileManager removeItemAtURL:fileURL error:NULL];
}
if (identifier != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:identifier];
}
}];
}
- (void)removeAllData
{
UIBackgroundTaskIdentifier identifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
dispatch_group_t group = dispatch_group_create();
for (RCTCacheRecord *record in _storage.allValues) {
NSURL *fileURL = [_cacheDirectoryURL URLByAppendingPathComponent:record.UUID.UUIDString];
dispatch_group_async(group, record.queue, ^{
[_fileManager removeItemAtURL:fileURL error:NULL];
});
}
if (identifier != UIBackgroundTaskInvalid) {
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] endBackgroundTask:identifier];
});
}
[_storage removeAllObjects];
}
@end

Просмотреть файл

@ -18,6 +18,6 @@ typedef NS_ENUM(NSUInteger, RCTFPSGraphPosition) {
- (instancetype)initWithFrame:(CGRect)frame graphPosition:(RCTFPSGraphPosition)position name:(NSString *)name color:(UIColor *)color NS_DESIGNATED_INITIALIZER;
- (void)tick:(NSTimeInterval)timestamp;
- (void)onTick:(NSTimeInterval)timestamp;
@end

Просмотреть файл

@ -93,7 +93,7 @@ RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder)
return label;
}
- (void)tick:(NSTimeInterval)timestamp
- (void)onTick:(NSTimeInterval)timestamp
{
_frameCount++;
if (_prevTime == -1) {

Просмотреть файл

@ -67,16 +67,5 @@ typedef void (^RCTJavaScriptCallback)(id json, NSError *error);
@end
static const char *RCTJavaScriptExecutorID = "RCTJavaScriptExecutorID";
__used static void RCTSetExecutorID(id<RCTJavaScriptExecutor> executor)
{
static NSUInteger executorID = 0;
if (executor) {
objc_setAssociatedObject(executor, RCTJavaScriptExecutorID, @(++executorID), OBJC_ASSOCIATION_RETAIN);
}
}
__used static NSNumber *RCTGetExecutorID(id<RCTJavaScriptExecutor> executor)
{
return executor ? objc_getAssociatedObject(executor, RCTJavaScriptExecutorID) : @0;
}
void RCTSetExecutorID(id<RCTJavaScriptExecutor> executor);
NSNumber *RCTGetExecutorID(id<RCTJavaScriptExecutor> executor);

Просмотреть файл

@ -0,0 +1,26 @@
/**
* 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 "RCTJavaScriptExecutor.h"
static const char *RCTJavaScriptExecutorID = "RCTJavaScriptExecutorID";
void RCTSetExecutorID(id<RCTJavaScriptExecutor> executor)
{
static NSUInteger executorID = 0;
if (executor) {
objc_setAssociatedObject(executor, RCTJavaScriptExecutorID, @(++executorID), OBJC_ASSOCIATION_RETAIN);
}
}
NSNumber *RCTGetExecutorID(id<RCTJavaScriptExecutor> executor)
{
return executor ? objc_getAssociatedObject(executor, RCTJavaScriptExecutorID) : @0;
}

Просмотреть файл

@ -40,10 +40,12 @@
static NSRegularExpression *typeRegex;
static NSRegularExpression *selectorRegex;
if (!typeRegex) {
NSString *unusedPattern = @"(?:(?:__unused|__attribute__\\(\\(unused\\)\\)))";
NSString *unusedPattern = @"(?:__unused|__attribute__\\(\\(unused\\)\\))";
NSString *constPattern = @"(?:const)";
NSString *constUnusedPattern = [NSString stringWithFormat:@"(?:(?:%@|%@)\\s*)", unusedPattern, constPattern];
NSString *pattern = [NSString stringWithFormat:@"\\(%1$@?(\\w+?)(?:\\s*\\*)?%1$@?\\)", constUnusedPattern];
NSString *nullabilityPattern = @"(?:__nullable|__nonnull|nullable|nonnull)";
NSString *annotationPattern = [NSString stringWithFormat:@"(?:(?:%@|%@|%@)\\s*)",
unusedPattern, constPattern, nullabilityPattern];
NSString *pattern = [NSString stringWithFormat:@"\\(%1$@?(\\w+?)(?:\\s*\\*)?%1$@?\\)", annotationPattern];
typeRegex = [[NSRegularExpression alloc] initWithPattern:pattern options:0 error:NULL];
selectorRegex = [[NSRegularExpression alloc] initWithPattern:@"(?<=:).*?(?=[a-zA-Z_]+:|$)" options:0 error:NULL];

Просмотреть файл

@ -65,8 +65,8 @@
58114A501AAE93D500E7D092 /* RCTAsyncLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A4E1AAE93D500E7D092 /* RCTAsyncLocalStorage.m */; };
58C571C11AA56C1900CDF9C8 /* RCTDatePickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58C571BF1AA56C1900CDF9C8 /* RCTDatePickerManager.m */; };
63F014C01B02080B003B75D2 /* RCTPointAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 63F014BF1B02080B003B75D2 /* RCTPointAnnotation.m */; };
783ABB351B38A9D3003FFD95 /* RCTJavaScriptExecutor.m in Sources */ = {isa = PBXBuildFile; fileRef = 783ABB341B38A9D3003FFD95 /* RCTJavaScriptExecutor.m */; };
830A229E1A66C68A008503DA /* RCTRootView.m in Sources */ = {isa = PBXBuildFile; fileRef = 830A229D1A66C68A008503DA /* RCTRootView.m */; };
830BA4551A8E3BDA00D53203 /* RCTCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 830BA4541A8E3BDA00D53203 /* RCTCache.m */; };
832348161A77A5AA00B55238 /* Layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FC71A68125100A75B9A /* Layout.c */; };
83CBBA511A601E3B00E9B192 /* RCTAssert.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA4B1A601E3B00E9B192 /* RCTAssert.m */; };
83CBBA521A601E3B00E9B192 /* RCTLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA4E1A601E3B00E9B192 /* RCTLog.m */; };
@ -216,11 +216,10 @@
58C571C01AA56C1900CDF9C8 /* RCTDatePickerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDatePickerManager.h; sourceTree = "<group>"; };
63F014BE1B02080B003B75D2 /* RCTPointAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPointAnnotation.h; sourceTree = "<group>"; };
63F014BF1B02080B003B75D2 /* RCTPointAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPointAnnotation.m; sourceTree = "<group>"; };
783ABB341B38A9D3003FFD95 /* RCTJavaScriptExecutor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTJavaScriptExecutor.m; sourceTree = "<group>"; };
830213F31A654E0800B993E6 /* RCTBridgeModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTBridgeModule.h; sourceTree = "<group>"; };
830A229C1A66C68A008503DA /* RCTRootView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRootView.h; sourceTree = "<group>"; };
830A229D1A66C68A008503DA /* RCTRootView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRootView.m; sourceTree = "<group>"; };
830BA4531A8E3BDA00D53203 /* RCTCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTCache.h; sourceTree = "<group>"; };
830BA4541A8E3BDA00D53203 /* RCTCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTCache.m; sourceTree = "<group>"; };
83BEE46C1A6D19BC00B5863B /* RCTSparseArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSparseArray.h; sourceTree = "<group>"; };
83BEE46D1A6D19BC00B5863B /* RCTSparseArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSparseArray.m; sourceTree = "<group>"; };
83CBBA2E1A601D0E00E9B192 /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; };
@ -425,8 +424,6 @@
83CBBA5E1A601EAA00E9B192 /* RCTBridge.h */,
83CBBA5F1A601EAA00E9B192 /* RCTBridge.m */,
830213F31A654E0800B993E6 /* RCTBridgeModule.h */,
830BA4531A8E3BDA00D53203 /* RCTCache.h */,
830BA4541A8E3BDA00D53203 /* RCTCache.m */,
83CBBACA1A6023D300E9B192 /* RCTConvert.h */,
83CBBACB1A6023D300E9B192 /* RCTConvert.m */,
13AF1F851AE6E777005F5298 /* RCTDefines.h */,
@ -434,6 +431,7 @@
83CBBA661A601EF300E9B192 /* RCTEventDispatcher.m */,
83CBBA4C1A601E3B00E9B192 /* RCTInvalidating.h */,
83CBBA631A601ECA00E9B192 /* RCTJavaScriptExecutor.h */,
783ABB341B38A9D3003FFD95 /* RCTJavaScriptExecutor.m */,
13A1F71C1A75392D00D3D453 /* RCTKeyCommands.h */,
13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */,
83CBBA4D1A601E3B00E9B192 /* RCTLog.h */,
@ -579,6 +577,7 @@
134FCB3D1A6E7F0800051CC8 /* RCTContextExecutor.m in Sources */,
14C2CA781B3ACB0400E6CBB2 /* RCTBatchedBridge.m in Sources */,
13E067591A70F44B002CDEE1 /* UIView+React.m in Sources */,
783ABB351B38A9D3003FFD95 /* RCTJavaScriptExecutor.m in Sources */,
14F484561AABFCE100FDF6B9 /* RCTSliderManager.m in Sources */,
14C2CA741B3AC64300E6CBB2 /* RCTModuleData.m in Sources */,
142014191B32094000CC17BA /* RCTPerformanceLogger.m in Sources */,
@ -601,7 +600,6 @@
131B6AF51AF1093D00FFC3E0 /* RCTSegmentedControlManager.m in Sources */,
58114A171AAE854800E7D092 /* RCTPickerManager.m in Sources */,
13B0801A1A69489C00A75B9A /* RCTNavigator.m in Sources */,
830BA4551A8E3BDA00D53203 /* RCTCache.m in Sources */,
137327E71AA5CF210034F82E /* RCTTabBar.m in Sources */,
00C1A2B31AC0B7E000E89A1C /* RCTDevMenu.m in Sources */,
63F014C01B02080B003B75D2 /* RCTPointAnnotation.m in Sources */,

Просмотреть файл

@ -9,14 +9,16 @@
#import "RCTView.h"
extern NSString *const RCTJSNavigationScheme;
@class RCTEventDispatcher;
@interface RCTWebView : RCTView
@property (nonatomic, strong) NSURL *URL;
@property (nonatomic, assign) UIEdgeInsets contentInset;
@property (nonatomic, assign) BOOL shouldInjectAJAXHandler;
@property (nonatomic, assign) BOOL automaticallyAdjustContentInsets;
@property (nonatomic, copy) NSString *injectedJavascriptIOS;
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;

Просмотреть файл

@ -18,6 +18,13 @@
#import "RCTView.h"
#import "UIView+React.h"
// Special scheme that allow JS to notify the WebView to emit
// navigation event.
//
// JavaScript Example:
// window.location.href = 'react-js-navigation://hello'
NSString *const RCTJSNavigationScheme = @"react-js-navigation";
@interface RCTWebView () <UIWebViewDelegate, RCTAutoInsetsProtocol>
@end
@ -26,6 +33,7 @@
{
RCTEventDispatcher *_eventDispatcher;
UIWebView *_webView;
NSString *_injectedJavascriptIOS;
}
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
@ -118,6 +126,19 @@ RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder)
return _webView.backgroundColor;
}
- (void)setinjectedJavascriptIOS:(NSString *)jsStr
{
if (_injectedJavascriptIOS == jsStr) {
return;
}
if ([_injectedJavascriptIOS isEqualToString:jsStr]) {
return;
}
_injectedJavascriptIOS = [jsStr copy];
}
- (NSMutableDictionary *)baseEvent
{
NSURL *url = _webView.request.URL;
@ -136,7 +157,6 @@ RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder)
#pragma mark - UIWebViewDelegate methods
static NSString *const RCTJSAJAXScheme = @"react-ajax";
- (BOOL)webView:(__unused UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
@ -152,8 +172,8 @@ static NSString *const RCTJSAJAXScheme = @"react-ajax";
[_eventDispatcher sendInputEventWithName:@"topLoadingStart" body:event];
}
// AJAX handler
return ![request.URL.scheme isEqualToString:RCTJSAJAXScheme];
// JS Navigation handler
return ![request.URL.scheme isEqualToString:RCTJSNavigationScheme];
}
- (void)webView:(__unused UIWebView *)webView didFailLoadWithError:(NSError *)error
@ -177,33 +197,8 @@ static NSString *const RCTJSAJAXScheme = @"react-ajax";
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
if (_shouldInjectAJAXHandler) {
// From http://stackoverflow.com/questions/5353278/uiwebviewdelegate-not-monitoring-xmlhttprequest
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"\
var s_ajaxListener = new Object(); \n\
s_ajaxListener.tempOpen = XMLHttpRequest.prototype.open; \n\
s_ajaxListener.tempSend = XMLHttpRequest.prototype.send; \n\
s_ajaxListener.callback = function() { \n\
window.location.href = '%@://' + this.url; \n\
} \n\
XMLHttpRequest.prototype.open = function(a,b) { \n\
s_ajaxListener.tempOpen.apply(this, arguments); \n\
s_ajaxListener.method = a; \n\
s_ajaxListener.url = b; \n\
if (a.toLowerCase() === 'get') { \n\
s_ajaxListener.data = (b.split('?'))[1]; \n\
} \n\
} \n\
XMLHttpRequest.prototype.send = function(a,b) { \n\
s_ajaxListener.tempSend.apply(this, arguments); \n\
if (s_ajaxListener.method.toLowerCase() === 'post') { \n\
s_ajaxListener.data = a; \n\
} \n\
s_ajaxListener.callback(); \n\
} \n\
", RCTJSAJAXScheme]];
if (_injectedJavascriptIOS != nil) {
[webView stringByEvaluatingJavaScriptFromString:_injectedJavascriptIOS];
}
// we only need the final 'finishLoad' call so only fire the event when we're actually done loading.

Просмотреть файл

@ -27,14 +27,15 @@ RCT_REMAP_VIEW_PROPERTY(url, URL, NSURL);
RCT_REMAP_VIEW_PROPERTY(html, HTML, NSString);
RCT_REMAP_VIEW_PROPERTY(bounces, _webView.scrollView.bounces, BOOL);
RCT_REMAP_VIEW_PROPERTY(scrollEnabled, _webView.scrollView.scrollEnabled, BOOL);
RCT_REMAP_VIEW_PROPERTY(scalesPageToFit, _webView.scalesPageToFit, BOOL);
RCT_EXPORT_VIEW_PROPERTY(injectedJavascriptIOS, NSString);
RCT_EXPORT_VIEW_PROPERTY(contentInset, UIEdgeInsets);
RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustContentInsets, BOOL);
RCT_EXPORT_VIEW_PROPERTY(shouldInjectAJAXHandler, BOOL);
RCT_REMAP_VIEW_PROPERTY(scalesPageToFit, _webView.scalesPageToFit, BOOL);
- (NSDictionary *)constantsToExport
{
return @{
@"JSNavigationScheme": RCTJSNavigationScheme,
@"NavigationType": @{
@"LinkClicked": @(UIWebViewNavigationTypeLinkClicked),
@"FormSubmitted": @(UIWebViewNavigationTypeFormSubmitted),

Просмотреть файл

@ -72,7 +72,7 @@
"yargs": "1.3.2"
},
"devDependencies": {
"jest-cli": "0.4.5",
"jest-cli": "facebook/jest#0.5.x",
"babel-eslint": "3.1.5",
"eslint": "0.21.2",
"eslint-plugin-react": "2.3.0"

Просмотреть файл

@ -8,6 +8,8 @@
*/
'use strict';
var path = require('path');
// Don't forget to everything listed here to `testConfig.json`
// modulePathIgnorePatterns.
var sharedBlacklist = [
@ -24,7 +26,7 @@ var platformBlacklists = {
ios: [
'node_modules/react-tools/src/browser/ui/React.js',
'node_modules/react-tools/src/browser/eventPlugins/ResponderEventPlugin.js',
// 'node_modules/react-tools/src/vendor/core/ExecutionEnvironment.js',
'node_modules/react-tools/src/vendor/core/ExecutionEnvironment.js',
'.web.js',
'.android.js',
],
@ -32,14 +34,16 @@ var platformBlacklists = {
'node_modules/react-tools/src/browser/ui/React.js',
'node_modules/react-tools/src/browser/eventPlugins/ResponderEventPlugin.js',
'node_modules/react-tools/src/browser/ReactTextComponent.js',
// 'node_modules/react-tools/src/vendor/core/ExecutionEnvironment.js',
'node_modules/react-tools/src/vendor/core/ExecutionEnvironment.js',
'.web.js',
'.ios.js',
],
};
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
var escaped = str.replace(/[\-\[\]\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
// convert the '/' into an escaped local file separator
return escaped.replace(/\//g,'\\' + path.sep);
}
function blacklist(platform, additionalBlacklist) {

Просмотреть файл

@ -25,7 +25,7 @@
},
"dependencies": {},
"devDependencies": {
"jest-cli": "0.4.5",
"jest-cli": "git://github.com/facebook/jest#0.5.x",
"eslint": "0.9.2"
}
}

Просмотреть файл

@ -12,6 +12,7 @@ var fs = require('fs');
var path = require('path');
var execFile = require('child_process').execFile;
var http = require('http');
var isAbsolutePath = require('absolute-path');
var getFlowTypeCheckMiddleware = require('./getFlowTypeCheckMiddleware');
@ -56,6 +57,11 @@ var options = parseCommandLine([{
}, {
command: 'nonPersistent',
description: 'Disable file watcher'
}, {
command: 'transformer',
type: 'string',
default: require.resolve('./transformer.js'),
description: 'Specify a custom transformer to be used (absolute path)'
}]);
if (options.projectRoots) {
@ -63,8 +69,9 @@ if (options.projectRoots) {
options.projectRoots = options.projectRoots.split(',');
}
} else {
if (__dirname.match(/node_modules\/react-native\/packager$/)) {
// packager is running from node_modules of another project
// match on either path separator
if (__dirname.match(/node_modules[\/\\]react-native[\/\\]packager$/)) {
// packager is running from node_modules of another project
options.projectRoots = [path.resolve(__dirname, '../../..')];
} else if (__dirname.match(/Pods\/React\/packager$/)) {
// packager is running from node_modules of another project
@ -91,7 +98,8 @@ if (options.assetRoots) {
});
}
} else {
if (__dirname.match(/node_modules\/react-native\/packager$/)) {
// match on either path separator
if (__dirname.match(/node_modules[\/\\]react-native[\/\\]packager$/)) {
options.assetRoots = [path.resolve(__dirname, '../../..')];
} else if (__dirname.match(/Pods\/React\/packager$/)) {
options.assetRoots = [path.resolve(__dirname, '../../..')];
@ -208,12 +216,17 @@ function statusPageMiddleware(req, res, next) {
}
function getAppMiddleware(options) {
var transformerPath = options.transformer;
if (!isAbsolutePath(transformerPath)) {
transformerPath = path.resolve(process.cwd(), transformerPath);
}
return ReactPackager.middleware({
nonPersistent: options.nonPersistent,
projectRoots: options.projectRoots,
blacklistRE: blacklist(options.platform),
cacheVersion: '2',
transformModulePath: require.resolve('./transformer.js'),
transformModulePath: transformerPath,
assetRoots: options.assetRoots,
assetExts: ['png', 'jpeg', 'jpg'],
polyfillModuleNames: [

2
packager/react-packager/index.js поставляемый
Просмотреть файл

@ -8,7 +8,7 @@
*/
'use strict';
require('babel/register')({
require('babel-core/register')({
only: /react-packager\/src/
});

Просмотреть файл

@ -2353,7 +2353,8 @@ describe('DependencyGraph', function() {
}
callbacks.push(callback);
return this;
}
},
isWatchman: () => Promise.resolve(false),
};
});

Просмотреть файл

@ -29,6 +29,7 @@ const validateOpts = declareOpts({
},
ignoreFilePath: {
type: 'function',
default: function(){}
},
fileWatcher: {

Просмотреть файл

@ -1,21 +1,11 @@
'use strict';
const nodeCrawl = require('./node');
//const watchmanCrawl = require('./watchman');
const watchmanCrawl = require('./watchman');
function crawl(roots, options) {
return nodeCrawl(roots, options);
// Although, in theory, watchman should be much faster;
// there is currently a bottleneck somewhere in the
// encoding/decoding that is causing it to be slower
// than node crawling. However, this should be fixed soon.
// https://github.com/facebook/watchman/issues/113
/*
const {fileWatcher} = options;
return fileWatcher.isWatchman().then(isWatchman => {
console.log(isWatchman);
if (!isWatchman) {
return false;
}
@ -30,7 +20,7 @@ function crawl(roots, options) {
}
return nodeCrawl(roots, options);
});*/
});
}
module.exports = crawl;

Просмотреть файл

@ -36,7 +36,7 @@ function watchmanRecReadDir(roots, {ignore, fileWatcher, exts}) {
}
}
const cmd = Promise.promisify(watcher.client.command.bind(watcher.client));
const cmd = Promise.denodeify(watcher.client.command.bind(watcher.client));
return cmd(['query', watchedRoot, {
'suffix': exts,
'expression': ['allof', ['type', 'f'], 'exists', dirExpr],

Просмотреть файл

@ -12,9 +12,11 @@ const EventEmitter = require('events').EventEmitter;
const sane = require('sane');
const Promise = require('promise');
const exec = require('child_process').exec;
const _ = require('underscore');
const MAX_WAIT_TIME = 25000;
// TODO(amasad): can we use watchman version command instead?r
const detectingWatcherClass = new Promise(function(resolve) {
exec('which watchman', function(err, out) {
if (err || out.length === 0) {
@ -79,9 +81,11 @@ class FileWatcher extends EventEmitter {
static createDummyWatcher() {
const ev = new EventEmitter();
ev.end = function() {
return Promise.resolve();
};
_.extend(ev, {
isWatchman: () => Promise.resolve(false),
end: () => Promise.resolve(),
});
return ev;
}
}

Просмотреть файл

@ -10,7 +10,7 @@
*/
'use strict';
var babel = require('babel');
var babel = require('babel-core');
function transform(srcTxt, filename, options) {
var result = babel.transform(srcTxt, {