Updates from Fri 10 Apr
- Implemented response headers when using `XMLHttpRequest` | Nick Lockwood - [ReactNative] Don't redbox on flow config errors | Spencer Ahrens - [ReactNative] Fix suggestions in TextInput when setting value prop | Spencer Ahrens - Link LinkingIOS in SampleApp | Nick Lockwood - unify use of password and secureTextEntry for TextInput | Nick Lockwood - Added random js queue+execution time sampling in react native | Bryce Redd - [react_native] JS files from D1980312: [react_native] Fix webview | Andrei Coman - [react-packager] Correct module extension regexp | Amjad Masad - [react-packager] Implement the browser field package.json spec | Amjad Masad - [ReactNative] Bring back crash reporting | Alex Kotliarskyi - Remove duplicate word | Nick Lockwood - NavigatorIOS navigationBarHidden property support | Nick Lockwood - [Scroll] Include content insets in scroll events | Nick Lockwood
This commit is contained in:
parent
7047d6e191
commit
096f1d9c4c
|
@ -15,6 +15,7 @@
|
||||||
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
|
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
|
||||||
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
|
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
|
||||||
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
|
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
|
||||||
|
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
|
||||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||||
|
@ -80,6 +81,13 @@
|
||||||
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
|
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
|
||||||
remoteInfo = React;
|
remoteInfo = React;
|
||||||
};
|
};
|
||||||
|
78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
|
||||||
|
proxyType = 2;
|
||||||
|
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||||
|
remoteInfo = RCTLinking;
|
||||||
|
};
|
||||||
832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = {
|
832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
|
containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
|
||||||
|
@ -91,7 +99,6 @@
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocketDebugger.xcodeproj; path = ../../Libraries/RCTWebSocketDebugger/RCTWebSocketDebugger.xcodeproj; sourceTree = "<group>"; };
|
00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocketDebugger.xcodeproj; path = ../../Libraries/RCTWebSocketDebugger/RCTWebSocketDebugger.xcodeproj; sourceTree = "<group>"; };
|
||||||
00481BE91AC0C89D00671115 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; };
|
|
||||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = main.jsbundle; path = iOS/main.jsbundle; sourceTree = "<group>"; };
|
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = main.jsbundle; path = iOS/main.jsbundle; sourceTree = "<group>"; };
|
||||||
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../../Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = "<group>"; };
|
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../../Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = "<group>"; };
|
||||||
00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = ../../Libraries/AdSupport/RCTAdSupport.xcodeproj; sourceTree = "<group>"; };
|
00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = ../../Libraries/AdSupport/RCTAdSupport.xcodeproj; sourceTree = "<group>"; };
|
||||||
|
@ -107,6 +114,7 @@
|
||||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = iOS/Info.plist; sourceTree = "<group>"; };
|
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = iOS/Info.plist; sourceTree = "<group>"; };
|
||||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = iOS/main.m; sourceTree = "<group>"; };
|
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = iOS/main.m; sourceTree = "<group>"; };
|
||||||
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = ../../React/React.xcodeproj; sourceTree = "<group>"; };
|
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = ../../React/React.xcodeproj; sourceTree = "<group>"; };
|
||||||
|
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = "<group>"; };
|
||||||
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = "<group>"; };
|
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
@ -121,6 +129,7 @@
|
||||||
00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */,
|
00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */,
|
||||||
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
|
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
|
||||||
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
|
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
|
||||||
|
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,
|
||||||
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */,
|
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */,
|
||||||
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
|
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
|
||||||
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
|
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
|
||||||
|
@ -208,9 +217,18 @@
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
78C398B11ACF4ADC00677621 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
78C398B91ACF4ADC00677621 /* libRCTLinking.a */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
|
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,
|
||||||
146833FF1AC3E56700842450 /* React.xcodeproj */,
|
146833FF1AC3E56700842450 /* React.xcodeproj */,
|
||||||
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
|
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
|
||||||
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
|
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
|
||||||
|
@ -220,7 +238,6 @@
|
||||||
00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */,
|
00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */,
|
||||||
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
|
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
|
||||||
00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */,
|
00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */,
|
||||||
00481BE91AC0C89D00671115 /* libicucore.dylib */,
|
|
||||||
);
|
);
|
||||||
name = Libraries;
|
name = Libraries;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -309,6 +326,10 @@
|
||||||
ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */;
|
ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */;
|
||||||
ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
|
ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ProductGroup = 78C398B11ACF4ADC00677621 /* Products */;
|
||||||
|
ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */;
|
ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */;
|
||||||
ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
|
ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
|
||||||
|
@ -394,6 +415,13 @@
|
||||||
remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;
|
remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;
|
||||||
sourceTree = BUILT_PRODUCTS_DIR;
|
sourceTree = BUILT_PRODUCTS_DIR;
|
||||||
};
|
};
|
||||||
|
78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {
|
||||||
|
isa = PBXReferenceProxy;
|
||||||
|
fileType = archive.ar;
|
||||||
|
path = libRCTLinking.a;
|
||||||
|
remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */;
|
||||||
|
sourceTree = BUILT_PRODUCTS_DIR;
|
||||||
|
};
|
||||||
832341B51AAA6A8300B99B32 /* libRCTText.a */ = {
|
832341B51AAA6A8300B99B32 /* libRCTText.a */ = {
|
||||||
isa = PBXReferenceProxy;
|
isa = PBXReferenceProxy;
|
||||||
fileType = archive.ar;
|
fileType = archive.ar;
|
||||||
|
|
|
@ -251,7 +251,7 @@ exports.examples = [
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
<WithLabel label="true">
|
<WithLabel label="true">
|
||||||
<TextInput secureTextEntry={true} style={styles.default} value="abc" />
|
<TextInput password={true} style={styles.default} value="abc" />
|
||||||
</WithLabel>
|
</WithLabel>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -50,6 +50,7 @@ var RCTNavigatorItem = createReactIOSNativeComponentClass({
|
||||||
rightButtonTitle: true,
|
rightButtonTitle: true,
|
||||||
onNavRightButtonTap: true,
|
onNavRightButtonTap: true,
|
||||||
tintColor: true,
|
tintColor: true,
|
||||||
|
navigationBarHidden: true,
|
||||||
backButtonTitle: true,
|
backButtonTitle: true,
|
||||||
titleTextColor: true,
|
titleTextColor: true,
|
||||||
style: true,
|
style: true,
|
||||||
|
@ -235,6 +236,11 @@ var NavigatorIOS = React.createClass({
|
||||||
|
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Boolean value that indicates whether the navigation bar is hidden
|
||||||
|
*/
|
||||||
|
navigationBarHidden: PropTypes.bool,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default wrapper style for components in the navigator.
|
* The default wrapper style for components in the navigator.
|
||||||
* A common use case is to set the backgroundColor for every page
|
* A common use case is to set the backgroundColor for every page
|
||||||
|
@ -547,6 +553,7 @@ var NavigatorIOS = React.createClass({
|
||||||
backButtonTitle={route.backButtonTitle}
|
backButtonTitle={route.backButtonTitle}
|
||||||
rightButtonTitle={route.rightButtonTitle}
|
rightButtonTitle={route.rightButtonTitle}
|
||||||
onNavRightButtonTap={route.onRightButtonPress}
|
onNavRightButtonTap={route.onRightButtonPress}
|
||||||
|
navigationBarHidden={this.props.navigationBarHidden}
|
||||||
tintColor={this.props.tintColor}>
|
tintColor={this.props.tintColor}>
|
||||||
<Component
|
<Component
|
||||||
navigator={this.navigator}
|
navigator={this.navigator}
|
||||||
|
|
|
@ -198,12 +198,6 @@ var TextInput = React.createClass({
|
||||||
* automatically enables it when there is text. Default value is false.
|
* automatically enables it when there is text. Default value is false.
|
||||||
*/
|
*/
|
||||||
enablesReturnKeyAutomatically: PropTypes.bool,
|
enablesReturnKeyAutomatically: PropTypes.bool,
|
||||||
|
|
||||||
/**
|
|
||||||
* If true, the text input obscures the text entered so that sensitive text
|
|
||||||
* like passwords stay secure. Default value is false.
|
|
||||||
*/
|
|
||||||
secureTextEntry: PropTypes.bool,
|
|
||||||
/**
|
/**
|
||||||
* If true, the text input can be multiple lines. Default value is false.
|
* If true, the text input can be multiple lines. Default value is false.
|
||||||
*/
|
*/
|
||||||
|
@ -221,11 +215,17 @@ var TextInput = React.createClass({
|
||||||
*/
|
*/
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
onChangeText: PropTypes.func,
|
onChangeText: PropTypes.func,
|
||||||
|
/**
|
||||||
|
* Callback that is called when text input ends.
|
||||||
|
*/
|
||||||
onEndEditing: PropTypes.func,
|
onEndEditing: PropTypes.func,
|
||||||
|
/**
|
||||||
|
* Callback that is called when the text input's submit button is pressed.
|
||||||
|
*/
|
||||||
onSubmitEditing: PropTypes.func,
|
onSubmitEditing: PropTypes.func,
|
||||||
/**
|
/**
|
||||||
* If true, the TextInput will be a password field. Default value is false.
|
* If true, the text input obscures the text entered so that sensitive text
|
||||||
|
* like passwords stay secure. Default value is false.
|
||||||
*/
|
*/
|
||||||
password: PropTypes.bool,
|
password: PropTypes.bool,
|
||||||
/**
|
/**
|
||||||
|
@ -419,7 +419,7 @@ var TextInput = React.createClass({
|
||||||
keyboardType={keyboardType}
|
keyboardType={keyboardType}
|
||||||
returnKeyType={returnKeyType}
|
returnKeyType={returnKeyType}
|
||||||
enablesReturnKeyAutomatically={this.props.enablesReturnKeyAutomatically}
|
enablesReturnKeyAutomatically={this.props.enablesReturnKeyAutomatically}
|
||||||
secureTextEntry={this.props.secureTextEntry}
|
secureTextEntry={this.props.password || this.props.secureTextEntry}
|
||||||
onFocus={this._onFocus}
|
onFocus={this._onFocus}
|
||||||
onBlur={this._onBlur}
|
onBlur={this._onBlur}
|
||||||
onChange={this._onChange}
|
onChange={this._onChange}
|
||||||
|
@ -464,7 +464,7 @@ var TextInput = React.createClass({
|
||||||
keyboardType={keyboardType}
|
keyboardType={keyboardType}
|
||||||
returnKeyType={returnKeyType}
|
returnKeyType={returnKeyType}
|
||||||
enablesReturnKeyAutomatically={this.props.enablesReturnKeyAutomatically}
|
enablesReturnKeyAutomatically={this.props.enablesReturnKeyAutomatically}
|
||||||
secureTextEntry={this.props.secureTextEntry}
|
secureTextEntry={this.props.password || this.props.secureTextEntry}
|
||||||
onFocus={this._onFocus}
|
onFocus={this._onFocus}
|
||||||
onBlur={this._onBlur}
|
onBlur={this._onBlur}
|
||||||
onChange={this._onChange}
|
onChange={this._onChange}
|
||||||
|
@ -505,7 +505,7 @@ var TextInput = React.createClass({
|
||||||
onChange={this._onChange}
|
onChange={this._onChange}
|
||||||
onEndEditing={this.props.onEndEditing}
|
onEndEditing={this.props.onEndEditing}
|
||||||
onSubmitEditing={this.props.onSubmitEditing}
|
onSubmitEditing={this.props.onSubmitEditing}
|
||||||
password={this.props.password}
|
password={this.props.password || this.props.secureTextEntry}
|
||||||
placeholder={this.props.placeholder}
|
placeholder={this.props.placeholder}
|
||||||
value={this.state.bufferedValue}
|
value={this.state.bufferedValue}
|
||||||
/>;
|
/>;
|
||||||
|
|
|
@ -34,8 +34,8 @@ var WebViewState = keyMirror({
|
||||||
var WebView = React.createClass({
|
var WebView = React.createClass({
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
renderError: PropTypes.func.isRequired, // view to show if there's an error
|
renderError: PropTypes.func, // view to show if there's an error
|
||||||
renderLoading: PropTypes.func.isRequired, // loading indicator to show
|
renderLoading: PropTypes.func, // loading indicator to show
|
||||||
url: PropTypes.string.isRequired,
|
url: PropTypes.string.isRequired,
|
||||||
automaticallyAdjustContentInsets: PropTypes.bool,
|
automaticallyAdjustContentInsets: PropTypes.bool,
|
||||||
contentInset: EdgeInsetsPropType,
|
contentInset: EdgeInsetsPropType,
|
||||||
|
@ -66,10 +66,10 @@ var WebView = React.createClass({
|
||||||
var otherView = null;
|
var otherView = null;
|
||||||
|
|
||||||
if (this.state.viewState === WebViewState.LOADING) {
|
if (this.state.viewState === WebViewState.LOADING) {
|
||||||
otherView = this.props.renderLoading();
|
otherView = this.props.renderLoading && this.props.renderLoading();
|
||||||
} else if (this.state.viewState === WebViewState.ERROR) {
|
} else if (this.state.viewState === WebViewState.ERROR) {
|
||||||
var errorEvent = this.state.lastErrorEvent;
|
var errorEvent = this.state.lastErrorEvent;
|
||||||
otherView = this.props.renderError(
|
otherView = this.props.renderError && this.props.renderError(
|
||||||
errorEvent.domain,
|
errorEvent.domain,
|
||||||
errorEvent.code,
|
errorEvent.code,
|
||||||
errorEvent.description);
|
errorEvent.description);
|
||||||
|
|
|
@ -13,6 +13,9 @@
|
||||||
|
|
||||||
@interface RCTLinkingManager : NSObject <RCTBridgeModule>
|
@interface RCTLinkingManager : NSObject <RCTBridgeModule>
|
||||||
|
|
||||||
+ (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
|
+ (BOOL)application:(UIApplication *)application
|
||||||
|
openURL:(NSURL *)URL
|
||||||
|
sourceApplication:(NSString *)sourceApplication
|
||||||
|
annotation:(id)annotation;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -37,11 +37,11 @@ RCT_EXPORT_MODULE()
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (BOOL)application:(UIApplication *)application
|
+ (BOOL)application:(UIApplication *)application
|
||||||
openURL:(NSURL *)url
|
openURL:(NSURL *)URL
|
||||||
sourceApplication:(NSString *)sourceApplication
|
sourceApplication:(NSString *)sourceApplication
|
||||||
annotation:(id)annotation
|
annotation:(id)annotation
|
||||||
{
|
{
|
||||||
NSDictionary *payload = @{@"url": [url absoluteString]};
|
NSDictionary *payload = @{@"url": [URL absoluteString]};
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTOpenURLNotification
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTOpenURLNotification
|
||||||
object:self
|
object:self
|
||||||
userInfo:payload];
|
userInfo:payload];
|
||||||
|
@ -54,23 +54,22 @@ RCT_EXPORT_MODULE()
|
||||||
body:[notification userInfo]];
|
body:[notification userInfo]];
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(openURL:(NSURL *)url)
|
RCT_EXPORT_METHOD(openURL:(NSURL *)URL)
|
||||||
{
|
{
|
||||||
[[UIApplication sharedApplication] openURL:url];
|
[[UIApplication sharedApplication] openURL:URL];
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(canOpenURL:(NSURL *)url
|
RCT_EXPORT_METHOD(canOpenURL:(NSURL *)URL
|
||||||
callback:(RCTResponseSenderBlock)callback)
|
callback:(RCTResponseSenderBlock)callback)
|
||||||
{
|
{
|
||||||
BOOL supported = [[UIApplication sharedApplication] canOpenURL:url];
|
BOOL canOpen = [[UIApplication sharedApplication] canOpenURL:URL];
|
||||||
callback(@[@(supported)]);
|
callback(@[@(canOpen)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary *)constantsToExport
|
- (NSDictionary *)constantsToExport
|
||||||
{
|
{
|
||||||
return @{
|
NSURL *initialURL = _bridge.launchOptions[UIApplicationLaunchOptionsURLKey];
|
||||||
@"initialURL": [[_bridge.launchOptions objectForKey:UIApplicationLaunchOptionsURLKey] absoluteString] ?: [NSNull null]
|
return @{@"initialURL": [initialURL absoluteString] ?: [NSNull null]};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#import "RCTDataManager.h"
|
#import "RCTDataManager.h"
|
||||||
|
|
||||||
#import "RCTAssert.h"
|
#import "RCTAssert.h"
|
||||||
|
#import "RCTConvert.h"
|
||||||
#import "RCTLog.h"
|
#import "RCTLog.h"
|
||||||
#import "RCTUtils.h"
|
#import "RCTUtils.h"
|
||||||
|
|
||||||
|
@ -22,27 +23,18 @@ RCT_EXPORT_MODULE()
|
||||||
* The responseSender block won't be called on same thread as called.
|
* The responseSender block won't be called on same thread as called.
|
||||||
*/
|
*/
|
||||||
RCT_EXPORT_METHOD(queryData:(NSString *)queryType
|
RCT_EXPORT_METHOD(queryData:(NSString *)queryType
|
||||||
withQuery:(id)query
|
withQuery:(NSDictionary *)query
|
||||||
queryHash:(__unused NSString *)queryHash
|
queryHash:(__unused NSString *)queryHash
|
||||||
responseSender:(RCTResponseSenderBlock)responseSender)
|
responseSender:(RCTResponseSenderBlock)responseSender)
|
||||||
{
|
{
|
||||||
if ([queryType isEqualToString:@"http"]) {
|
if ([queryType isEqualToString:@"http"]) {
|
||||||
|
|
||||||
// Parse query
|
|
||||||
NSDictionary *queryDict = query;
|
|
||||||
if ([query isKindOfClass:[NSString class]]) {
|
|
||||||
// TODO: it would be more efficient just to send a dictionary
|
|
||||||
queryDict = RCTJSONParse(query, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build request
|
// Build request
|
||||||
NSURL *url = [NSURL URLWithString:queryDict[@"url"]];
|
NSURL *URL = [RCTConvert NSURL:query[@"url"]];
|
||||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
|
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
|
||||||
request.HTTPMethod = queryDict[@"method"] ?: @"GET";
|
request.HTTPMethod = [RCTConvert NSString:query[@"method"]] ?: @"GET";
|
||||||
request.allHTTPHeaderFields = queryDict[@"headers"];
|
request.allHTTPHeaderFields = [RCTConvert NSDictionary:query[@"headers"]];
|
||||||
if ([queryDict[@"data"] isKindOfClass:[NSString class]]) {
|
request.HTTPBody = [RCTConvert NSData:query[@"data"]];
|
||||||
request.HTTPBody = [queryDict[@"data"] dataUsingEncoding:NSUTF8StringEncoding];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build data task
|
// Build data task
|
||||||
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *connectionError) {
|
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *connectionError) {
|
||||||
|
@ -50,18 +42,27 @@ RCT_EXPORT_METHOD(queryData:(NSString *)queryType
|
||||||
// Build response
|
// Build response
|
||||||
NSDictionary *responseJSON;
|
NSDictionary *responseJSON;
|
||||||
if (connectionError == nil) {
|
if (connectionError == nil) {
|
||||||
NSStringEncoding encoding;
|
NSStringEncoding encoding = NSUTF8StringEncoding;
|
||||||
if (response.textEncodingName) {
|
if (response.textEncodingName) {
|
||||||
CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);
|
CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);
|
||||||
encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
|
encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
|
||||||
} else {
|
|
||||||
encoding = NSUTF8StringEncoding;
|
|
||||||
}
|
}
|
||||||
int responseCode = (int)[((NSHTTPURLResponse *)response) statusCode];
|
NSHTTPURLResponse *httpResponse = nil;
|
||||||
NSString *returnData = [[NSString alloc] initWithData:data encoding:encoding];
|
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
|
||||||
responseJSON = @{@"status": @(responseCode), @"responseText": returnData};
|
// Might be a local file request
|
||||||
|
httpResponse = (NSHTTPURLResponse *)response;
|
||||||
|
}
|
||||||
|
responseJSON = @{
|
||||||
|
@"status": @([httpResponse statusCode] ?: 200),
|
||||||
|
@"responseHeaders": [httpResponse allHeaderFields] ?: @{},
|
||||||
|
@"responseText": [[NSString alloc] initWithData:data encoding:encoding] ?: @""
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
responseJSON = @{@"status": @0, @"responseText": [connectionError localizedDescription]};
|
responseJSON = @{
|
||||||
|
@"status": @0,
|
||||||
|
@"responseHeaders": @{},
|
||||||
|
@"responseText": [connectionError localizedDescription]
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send response (won't be sent on same thread as caller)
|
// Send response (won't be sent on same thread as caller)
|
||||||
|
|
|
@ -22,12 +22,13 @@ class XMLHttpRequest extends XMLHttpRequestBase {
|
||||||
sendImpl(method: ?string, url: ?string, headers: Object, data: any): void {
|
sendImpl(method: ?string, url: ?string, headers: Object, data: any): void {
|
||||||
RCTDataManager.queryData(
|
RCTDataManager.queryData(
|
||||||
'http',
|
'http',
|
||||||
JSON.stringify({
|
{
|
||||||
method: method,
|
method: method,
|
||||||
url: url,
|
url: url,
|
||||||
data: data,
|
data: data,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
}),
|
},
|
||||||
|
// TODO: Do we need this? is it used anywhere?
|
||||||
'h' + crc32(method + '|' + url + '|' + data),
|
'h' + crc32(method + '|' + url + '|' + data),
|
||||||
(result) => {
|
(result) => {
|
||||||
result = JSON.parse(result);
|
result = JSON.parse(result);
|
||||||
|
|
|
@ -85,51 +85,31 @@ RCT_EXPORT_METHOD(getApplicationIconBadgeNumber:(RCTResponseSenderBlock)callback
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(requestPermissions)
|
RCT_EXPORT_METHOD(requestPermissions)
|
||||||
{
|
{
|
||||||
Class _UIUserNotificationSettings;
|
|
||||||
if ((_UIUserNotificationSettings = NSClassFromString(@"UIUserNotificationSettings"))) {
|
|
||||||
UIUserNotificationType types = UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert;
|
|
||||||
UIUserNotificationSettings *notificationSettings = [_UIUserNotificationSettings settingsForTypes:types categories:nil];
|
|
||||||
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
|
|
||||||
} else {
|
|
||||||
|
|
||||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
|
||||||
|
|
||||||
|
// if we are targeting iOS 7, *and* the new UIUserNotificationSettings
|
||||||
|
// class is not available, then register using the old mechanism
|
||||||
|
if (![UIUserNotificationSettings class]) {
|
||||||
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
|
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
|
||||||
UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert];
|
UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
UIUserNotificationType types = UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert;
|
||||||
|
UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
|
||||||
|
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(checkPermissions:(RCTResponseSenderBlock)callback)
|
RCT_EXPORT_METHOD(checkPermissions:(RCTResponseSenderBlock)callback)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
|
|
||||||
|
|
||||||
#define UIUserNotificationTypeAlert UIRemoteNotificationTypeAlert
|
|
||||||
#define UIUserNotificationTypeBadge UIRemoteNotificationTypeBadge
|
|
||||||
#define UIUserNotificationTypeSound UIRemoteNotificationTypeSound
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NSUInteger types;
|
|
||||||
if ([UIApplication instancesRespondToSelector:@selector(currentUserNotificationSettings)]) {
|
|
||||||
types = [[[UIApplication sharedApplication] currentUserNotificationSettings] types];
|
|
||||||
} else {
|
|
||||||
|
|
||||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
|
|
||||||
|
|
||||||
types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
NSMutableDictionary *permissions = [[NSMutableDictionary alloc] init];
|
NSMutableDictionary *permissions = [[NSMutableDictionary alloc] init];
|
||||||
permissions[@"alert"] = @((types & UIUserNotificationTypeAlert) > 0);
|
|
||||||
permissions[@"badge"] = @((types & UIUserNotificationTypeBadge) > 0);
|
UIUserNotificationType types = [[[UIApplication sharedApplication] currentUserNotificationSettings] types];
|
||||||
permissions[@"sound"] = @((types & UIUserNotificationTypeSound) > 0);
|
permissions[@"alert"] = @((BOOL)(types & UIUserNotificationTypeAlert));
|
||||||
|
permissions[@"badge"] = @((BOOL)(types & UIUserNotificationTypeBadge));
|
||||||
|
permissions[@"sound"] = @((BOOL)(types & UIUserNotificationTypeSound));
|
||||||
|
|
||||||
callback(@[permissions]);
|
callback(@[permissions]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ var StyleSheetValidation = require('StyleSheetValidation');
|
||||||
* Code quality:
|
* Code quality:
|
||||||
*
|
*
|
||||||
* - By moving styles away from the render function, you're making the code
|
* - By moving styles away from the render function, you're making the code
|
||||||
* code easier to understand.
|
* easier to understand.
|
||||||
* - Naming the styles is a good way to add meaning to the low level components
|
* - Naming the styles is a good way to add meaning to the low level components
|
||||||
* in the render function.
|
* in the render function.
|
||||||
*
|
*
|
||||||
|
|
|
@ -49,6 +49,9 @@ typedef struct section RCTHeaderSection;
|
||||||
#define RCTGetSectByNameFromHeader getsectbynamefromheader
|
#define RCTGetSectByNameFromHeader getsectbynamefromheader
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
NSString *const RCTEnqueueNotification = @"RCTEnqueueNotification";
|
||||||
|
NSString *const RCTDequeueNotification = @"RCTDequeueNotification";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function returns the module name for a given class.
|
* This function returns the module name for a given class.
|
||||||
*/
|
*/
|
||||||
|
@ -926,10 +929,10 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
||||||
|
|
||||||
- (void)_invokeAndProcessModule:(NSString *)module method:(NSString *)method arguments:(NSArray *)args
|
- (void)_invokeAndProcessModule:(NSString *)module method:(NSString *)method arguments:(NSArray *)args
|
||||||
{
|
{
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"JS_PERF_ENQUEUE" object:nil userInfo:nil];
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTEnqueueNotification object:nil userInfo:nil];
|
||||||
|
|
||||||
RCTJavaScriptCallback processResponse = ^(id json, NSError *error) {
|
RCTJavaScriptCallback processResponse = ^(id json, NSError *error) {
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"JS_PERF_DEQUEUE" object:nil userInfo:nil];
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTDequeueNotification object:nil userInfo:nil];
|
||||||
[self _handleBuffer:json];
|
[self _handleBuffer:json];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1038,6 +1041,9 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
||||||
}
|
}
|
||||||
@catch (NSException *exception) {
|
@catch (NSException *exception) {
|
||||||
RCTLogError(@"Exception thrown while invoking %@ on target %@ with params %@: %@", method.JSMethodName, module, params, exception);
|
RCTLogError(@"Exception thrown while invoking %@ on target %@ with params %@: %@", method.JSMethodName, module, params, exception);
|
||||||
|
if ([exception.name rangeOfString:@"Unhandled JS Exception"].location != NSNotFound) {
|
||||||
|
@throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
+ (NSDictionary *)NSDictionary:(id)json;
|
+ (NSDictionary *)NSDictionary:(id)json;
|
||||||
+ (NSString *)NSString:(id)json;
|
+ (NSString *)NSString:(id)json;
|
||||||
+ (NSNumber *)NSNumber:(id)json;
|
+ (NSNumber *)NSNumber:(id)json;
|
||||||
|
+ (NSData *)NSData:(id)json;
|
||||||
|
|
||||||
+ (NSURL *)NSURL:(id)json;
|
+ (NSURL *)NSURL:(id)json;
|
||||||
+ (NSURLRequest *)NSURLRequest:(id)json;
|
+ (NSURLRequest *)NSURLRequest:(id)json;
|
||||||
|
|
|
@ -50,6 +50,12 @@ RCT_CONVERTER(NSString *, NSString, description)
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (NSData *)NSData:(id)json
|
||||||
|
{
|
||||||
|
// TODO: should we automatically decode base64 data? Probably not...
|
||||||
|
return [[self NSString:json] dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
}
|
||||||
|
|
||||||
+ (NSURL *)NSURL:(id)json
|
+ (NSURL *)NSURL:(id)json
|
||||||
{
|
{
|
||||||
if (![json isKindOfClass:[NSString class]]) {
|
if (![json isKindOfClass:[NSString class]]) {
|
||||||
|
|
|
@ -97,6 +97,12 @@ RCT_IMPORT_METHOD(RCTEventEmitter, receiveEvent);
|
||||||
@"x": @(scrollView.contentOffset.x),
|
@"x": @(scrollView.contentOffset.x),
|
||||||
@"y": @(scrollView.contentOffset.y)
|
@"y": @(scrollView.contentOffset.y)
|
||||||
},
|
},
|
||||||
|
@"contentInset": @{
|
||||||
|
@"top": @(scrollView.contentInset.top),
|
||||||
|
@"left": @(scrollView.contentInset.left),
|
||||||
|
@"bottom": @(scrollView.contentInset.bottom),
|
||||||
|
@"right": @(scrollView.contentInset.right)
|
||||||
|
},
|
||||||
@"contentSize": @{
|
@"contentSize": @{
|
||||||
@"width": @(scrollView.contentSize.width),
|
@"width": @(scrollView.contentSize.width),
|
||||||
@"height": @(scrollView.contentSize.height)
|
@"height": @(scrollView.contentSize.height)
|
||||||
|
|
|
@ -21,4 +21,6 @@
|
||||||
|
|
||||||
- (instancetype)initWithDelegate:(id<RCTExceptionsManagerDelegate>)delegate NS_DESIGNATED_INITIALIZER;
|
- (instancetype)initWithDelegate:(id<RCTExceptionsManagerDelegate>)delegate NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSUInteger maxReloadAttempts;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -9,19 +9,27 @@
|
||||||
|
|
||||||
#import "RCTExceptionsManager.h"
|
#import "RCTExceptionsManager.h"
|
||||||
|
|
||||||
|
#import "RCTLog.h"
|
||||||
#import "RCTRedBox.h"
|
#import "RCTRedBox.h"
|
||||||
|
#import "RCTRootView.h"
|
||||||
|
|
||||||
@implementation RCTExceptionsManager
|
@implementation RCTExceptionsManager
|
||||||
{
|
{
|
||||||
__weak id<RCTExceptionsManagerDelegate> _delegate;
|
__weak id<RCTExceptionsManagerDelegate> _delegate;
|
||||||
|
NSUInteger _reloadRetries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef DEBUG
|
||||||
|
static NSUInteger RCTReloadRetries = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
RCT_EXPORT_MODULE()
|
RCT_EXPORT_MODULE()
|
||||||
|
|
||||||
- (instancetype)initWithDelegate:(id<RCTExceptionsManagerDelegate>)delegate
|
- (instancetype)initWithDelegate:(id<RCTExceptionsManagerDelegate>)delegate
|
||||||
{
|
{
|
||||||
if ((self = [super init])) {
|
if ((self = [super init])) {
|
||||||
_delegate = delegate;
|
_delegate = delegate;
|
||||||
|
_maxReloadAttempts = 0;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -36,9 +44,40 @@ RCT_EXPORT_METHOD(reportUnhandledException:(NSString *)message
|
||||||
{
|
{
|
||||||
if (_delegate) {
|
if (_delegate) {
|
||||||
[_delegate unhandledJSExceptionWithMessage:message stack:stack];
|
[_delegate unhandledJSExceptionWithMessage:message stack:stack];
|
||||||
} else {
|
return;
|
||||||
[[RCTRedBox sharedInstance] showErrorMessage:message withStack:stack];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
[[RCTRedBox sharedInstance] showErrorMessage:message withStack:stack];
|
||||||
|
#else
|
||||||
|
if (RCTReloadRetries < _maxReloadAttempts) {
|
||||||
|
RCTReloadRetries++;
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTReloadNotification object:nil];
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
NSError *error;
|
||||||
|
const NSUInteger MAX_SANITIZED_LENGTH = 75;
|
||||||
|
// Filter out numbers so the same base errors are mapped to the same categories independent of incorrect values.
|
||||||
|
NSString *pattern = @"[+-]?\\d+[,.]?\\d*";
|
||||||
|
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
|
||||||
|
RCTAssert(error == nil, @"Bad regex pattern: %@", pattern);
|
||||||
|
NSString *sanitizedMessage = [regex stringByReplacingMatchesInString:message
|
||||||
|
options:0
|
||||||
|
range:NSMakeRange(0, message.length)
|
||||||
|
withTemplate:@"<num>"];
|
||||||
|
if (sanitizedMessage.length > MAX_SANITIZED_LENGTH) {
|
||||||
|
sanitizedMessage = [[sanitizedMessage substringToIndex:MAX_SANITIZED_LENGTH] stringByAppendingString:@"..."];
|
||||||
|
}
|
||||||
|
NSMutableString *prettyStack = [@"\n" mutableCopy];
|
||||||
|
for (NSDictionary *frame in stack) {
|
||||||
|
[prettyStack appendFormat:@"%@@%@:%@\n", frame[@"methodName"], frame[@"lineNumber"], frame[@"column"]];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *name = [@"Unhandled JS Exception: " stringByAppendingString:sanitizedMessage];
|
||||||
|
[NSException raise:name format:@"Message: %@, stack: %@", message, prettyStack];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(updateExceptionMessage:(NSString *)message
|
RCT_EXPORT_METHOD(updateExceptionMessage:(NSString *)message
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
@property (nonatomic, copy) NSString *title;
|
@property (nonatomic, copy) NSString *title;
|
||||||
@property (nonatomic, copy) NSString *rightButtonTitle;
|
@property (nonatomic, copy) NSString *rightButtonTitle;
|
||||||
@property (nonatomic, copy) NSString *backButtonTitle;
|
@property (nonatomic, copy) NSString *backButtonTitle;
|
||||||
|
@property (nonatomic, assign) BOOL navigationBarHidden;
|
||||||
@property (nonatomic, copy) UIColor *tintColor;
|
@property (nonatomic, copy) UIColor *tintColor;
|
||||||
@property (nonatomic, copy) UIColor *barTintColor;
|
@property (nonatomic, copy) UIColor *barTintColor;
|
||||||
@property (nonatomic, copy) UIColor *titleTextColor;
|
@property (nonatomic, copy) UIColor *titleTextColor;
|
||||||
|
|
|
@ -24,6 +24,7 @@ RCT_EXPORT_MODULE()
|
||||||
RCT_EXPORT_VIEW_PROPERTY(title, NSString)
|
RCT_EXPORT_VIEW_PROPERTY(title, NSString)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(rightButtonTitle, NSString);
|
RCT_EXPORT_VIEW_PROPERTY(rightButtonTitle, NSString);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(backButtonTitle, NSString);
|
RCT_EXPORT_VIEW_PROPERTY(backButtonTitle, NSString);
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(navigationBarHidden, BOOL);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor);
|
RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(barTintColor, UIColor);
|
RCT_EXPORT_VIEW_PROPERTY(barTintColor, UIColor);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(titleTextColor, UIColor);
|
RCT_EXPORT_VIEW_PROPERTY(titleTextColor, UIColor);
|
||||||
|
|
|
@ -35,6 +35,13 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setText:(NSString *)text
|
||||||
|
{
|
||||||
|
if (![text isEqualToString:self.text]) {
|
||||||
|
[super setText:text];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (NSArray *)reactSubviews
|
- (NSArray *)reactSubviews
|
||||||
{
|
{
|
||||||
// TODO: do we support subviews of textfield in React?
|
// TODO: do we support subviews of textfield in React?
|
||||||
|
|
|
@ -65,7 +65,10 @@
|
||||||
if ([self.parentViewController isKindOfClass:[UINavigationController class]])
|
if ([self.parentViewController isKindOfClass:[UINavigationController class]])
|
||||||
{
|
{
|
||||||
|
|
||||||
[self.navigationController setNavigationBarHidden:!_navItem animated:animated];
|
[self.navigationController
|
||||||
|
setNavigationBarHidden:_navItem.navigationBarHidden
|
||||||
|
animated:animated];
|
||||||
|
|
||||||
if (!_navItem) {
|
if (!_navItem) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "react-native",
|
"name": "react-native",
|
||||||
"version": "0.3.9",
|
"version": "0.3.7",
|
||||||
"description": "A framework for building native apps using React",
|
"description": "A framework for building native apps using React",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -8,8 +8,11 @@
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var chalk = require('chalk');
|
||||||
var exec = require('child_process').exec;
|
var exec = require('child_process').exec;
|
||||||
|
|
||||||
|
var hasWarned = {};
|
||||||
|
|
||||||
function getFlowTypeCheckMiddleware(options) {
|
function getFlowTypeCheckMiddleware(options) {
|
||||||
return function(req, res, next) {
|
return function(req, res, next) {
|
||||||
if (options.skipflow) {
|
if (options.skipflow) {
|
||||||
|
@ -18,13 +21,19 @@ function getFlowTypeCheckMiddleware(options) {
|
||||||
if (options.flowroot || options.projectRoots.length === 1) {
|
if (options.flowroot || options.projectRoots.length === 1) {
|
||||||
var flowroot = options.flowroot || options.projectRoots[0];
|
var flowroot = options.flowroot || options.projectRoots[0];
|
||||||
} else {
|
} else {
|
||||||
|
if (!hasWarned.noRoot) {
|
||||||
|
hasWarned.noRoot = true;
|
||||||
console.warn('flow: No suitable root');
|
console.warn('flow: No suitable root');
|
||||||
|
}
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
exec('command -v flow >/dev/null 2>&1', function(error, stdout) {
|
exec('command -v flow >/dev/null 2>&1', function(error, stdout) {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.warn('flow: Skipping because not installed. Install with ' +
|
if (!hasWarned.noFlow) {
|
||||||
'`brew install flow`.');
|
hasWarned.noFlow = true;
|
||||||
|
console.warn(chalk.yellow('flow: Skipping because not installed. Install with ' +
|
||||||
|
'`brew install flow`.'));
|
||||||
|
}
|
||||||
return next();
|
return next();
|
||||||
} else {
|
} else {
|
||||||
return doFlowTypecheck(res, flowroot, next);
|
return doFlowTypecheck(res, flowroot, next);
|
||||||
|
@ -34,16 +43,21 @@ function getFlowTypeCheckMiddleware(options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function doFlowTypecheck(res, flowroot, next) {
|
function doFlowTypecheck(res, flowroot, next) {
|
||||||
// vjeux: big hack to make it work on the sample app because we don't generate a
|
|
||||||
// .flowconfig in the init script right now.
|
|
||||||
return next();
|
|
||||||
|
|
||||||
var flowCmd = 'cd "' + flowroot + '" && flow --json --timeout 20';
|
var flowCmd = 'cd "' + flowroot + '" && flow --json --timeout 20';
|
||||||
var start = Date.now();
|
var start = Date.now();
|
||||||
console.log('flow: Running static typechecks.');
|
// Log start message if flow is slow to let user know something is happening.
|
||||||
exec(flowCmd, function(flowError, stdout) {
|
var flowSlow = setTimeout(
|
||||||
|
function() {
|
||||||
|
console.log(chalk.gray('flow: Running static typechecks.'));
|
||||||
|
},
|
||||||
|
500
|
||||||
|
);
|
||||||
|
exec(flowCmd, function(flowError, stdout, stderr) {
|
||||||
|
clearTimeout(flowSlow);
|
||||||
if (!flowError) {
|
if (!flowError) {
|
||||||
console.log('flow: Typechecks passed (' + (Date.now() - start) + 'ms).');
|
console.log(chalk.gray(
|
||||||
|
'flow: Typechecks passed (' + (Date.now() - start) + 'ms).')
|
||||||
|
);
|
||||||
return next();
|
return next();
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
@ -65,24 +79,38 @@ function doFlowTypecheck(res, flowroot, next) {
|
||||||
});
|
});
|
||||||
errorNum++;
|
errorNum++;
|
||||||
});
|
});
|
||||||
var message = 'Flow found type errors. If you think these are wrong, ' +
|
|
||||||
'make sure flow is up to date, or disable with --skipflow.';
|
|
||||||
} catch (e) {
|
|
||||||
var message =
|
|
||||||
'Flow failed to provide parseable output:\n\n`' + stdout + '`';
|
|
||||||
console.error(message, '\nException: `', e, '`\n\n');
|
|
||||||
}
|
|
||||||
var error = {
|
var error = {
|
||||||
status: 500,
|
status: 500,
|
||||||
message: message,
|
message: 'Flow found type errors. If you think these are wrong, ' +
|
||||||
|
'make sure your flow bin and .flowconfig are up to date, or ' +
|
||||||
|
'disable with --skipflow.',
|
||||||
type: 'FlowError',
|
type: 'FlowError',
|
||||||
errors: errors,
|
errors: errors,
|
||||||
};
|
};
|
||||||
console.error('flow: Error running command `' + flowCmd + '`:\n', error);
|
console.error(chalk.yellow('flow: Error running command `' + flowCmd +
|
||||||
|
'`:\n' + JSON.stringify(error))
|
||||||
|
);
|
||||||
res.writeHead(error.status, {
|
res.writeHead(error.status, {
|
||||||
'Content-Type': 'application/json; charset=UTF-8',
|
'Content-Type': 'application/json; charset=UTF-8',
|
||||||
});
|
});
|
||||||
res.end(JSON.stringify(error));
|
res.end(JSON.stringify(error));
|
||||||
|
} catch (e) {
|
||||||
|
if (stderr.match(/Could not find a \.flowconfig/)) {
|
||||||
|
if (!hasWarned.noConfig) {
|
||||||
|
hasWarned.noConfig = true;
|
||||||
|
console.warn(chalk.yellow('flow: ' + stderr));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!hasWarned.brokenFlow) {
|
||||||
|
hasWarned.brokenFlow = true;
|
||||||
|
console.warn(chalk.yellow(
|
||||||
|
'Flow failed to provide parseable output:\n\n`' + stdout +
|
||||||
|
'`.\n' + 'stderr: `' + stderr + '`'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,42 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pit('should get dependencies with the correct extensions', function() {
|
||||||
|
var root = '/root';
|
||||||
|
fs.__setMockFilesystem({
|
||||||
|
'root': {
|
||||||
|
'index.js': [
|
||||||
|
'/**',
|
||||||
|
' * @providesModule index',
|
||||||
|
' */',
|
||||||
|
'require("a")'
|
||||||
|
].join('\n'),
|
||||||
|
'a.js': [
|
||||||
|
'/**',
|
||||||
|
' * @providesModule a',
|
||||||
|
' */',
|
||||||
|
].join('\n'),
|
||||||
|
'a.js.orig': [
|
||||||
|
'/**',
|
||||||
|
' * @providesModule a',
|
||||||
|
' */',
|
||||||
|
].join('\n'),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var dgraph = new DependencyGraph({
|
||||||
|
roots: [root],
|
||||||
|
fileWatcher: fileWatcher
|
||||||
|
});
|
||||||
|
return dgraph.load().then(function() {
|
||||||
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
.toEqual([
|
||||||
|
{id: 'index', altId: '/root/index.js', path: '/root/index.js', dependencies: ['a']},
|
||||||
|
{id: 'a', altId: '/root/a.js', path: '/root/a.js', dependencies: []},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
pit('should get dependencies with deprecated assets', function() {
|
pit('should get dependencies with deprecated assets', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
fs.__setMockFilesystem({
|
fs.__setMockFilesystem({
|
||||||
|
@ -674,6 +710,296 @@ describe('DependencyGraph', function() {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pit('should support simple browser field in packages', function() {
|
||||||
|
var root = '/root';
|
||||||
|
fs.__setMockFilesystem({
|
||||||
|
'root': {
|
||||||
|
'index.js': [
|
||||||
|
'/**',
|
||||||
|
' * @providesModule index',
|
||||||
|
' */',
|
||||||
|
'require("aPackage")',
|
||||||
|
].join('\n'),
|
||||||
|
'aPackage': {
|
||||||
|
'package.json': JSON.stringify({
|
||||||
|
name: 'aPackage',
|
||||||
|
main: 'main.js',
|
||||||
|
browser: 'client.js',
|
||||||
|
}),
|
||||||
|
'main.js': 'some other code',
|
||||||
|
'client.js': 'some code',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var dgraph = new DependencyGraph({
|
||||||
|
roots: [root],
|
||||||
|
fileWatcher: fileWatcher
|
||||||
|
});
|
||||||
|
return dgraph.load().then(function() {
|
||||||
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
.toEqual([
|
||||||
|
{ id: 'index', altId: '/root/index.js',
|
||||||
|
path: '/root/index.js',
|
||||||
|
dependencies: ['aPackage']
|
||||||
|
},
|
||||||
|
{ id: 'aPackage/client',
|
||||||
|
path: '/root/aPackage/client.js',
|
||||||
|
dependencies: []
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
pit('should supportbrowser field in packages w/o .js ext', function() {
|
||||||
|
var root = '/root';
|
||||||
|
fs.__setMockFilesystem({
|
||||||
|
'root': {
|
||||||
|
'index.js': [
|
||||||
|
'/**',
|
||||||
|
' * @providesModule index',
|
||||||
|
' */',
|
||||||
|
'require("aPackage")',
|
||||||
|
].join('\n'),
|
||||||
|
'aPackage': {
|
||||||
|
'package.json': JSON.stringify({
|
||||||
|
name: 'aPackage',
|
||||||
|
main: 'main.js',
|
||||||
|
browser: 'client',
|
||||||
|
}),
|
||||||
|
'main.js': 'some other code',
|
||||||
|
'client.js': 'some code',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var dgraph = new DependencyGraph({
|
||||||
|
roots: [root],
|
||||||
|
fileWatcher: fileWatcher
|
||||||
|
});
|
||||||
|
return dgraph.load().then(function() {
|
||||||
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
.toEqual([
|
||||||
|
{ id: 'index', altId: '/root/index.js',
|
||||||
|
path: '/root/index.js',
|
||||||
|
dependencies: ['aPackage']
|
||||||
|
},
|
||||||
|
{ id: 'aPackage/client',
|
||||||
|
path: '/root/aPackage/client.js',
|
||||||
|
dependencies: []
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
pit('should support mapping main in browser field json', function() {
|
||||||
|
var root = '/root';
|
||||||
|
fs.__setMockFilesystem({
|
||||||
|
'root': {
|
||||||
|
'index.js': [
|
||||||
|
'/**',
|
||||||
|
' * @providesModule index',
|
||||||
|
' */',
|
||||||
|
'require("aPackage")',
|
||||||
|
].join('\n'),
|
||||||
|
'aPackage': {
|
||||||
|
'package.json': JSON.stringify({
|
||||||
|
name: 'aPackage',
|
||||||
|
main: './main.js',
|
||||||
|
browser: {
|
||||||
|
'./main.js': './client.js',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
'main.js': 'some other code',
|
||||||
|
'client.js': 'some code',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var dgraph = new DependencyGraph({
|
||||||
|
roots: [root],
|
||||||
|
fileWatcher: fileWatcher
|
||||||
|
});
|
||||||
|
return dgraph.load().then(function() {
|
||||||
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
.toEqual([
|
||||||
|
{ id: 'index', altId: '/root/index.js',
|
||||||
|
path: '/root/index.js',
|
||||||
|
dependencies: ['aPackage']
|
||||||
|
},
|
||||||
|
{ id: 'aPackage/client',
|
||||||
|
path: '/root/aPackage/client.js',
|
||||||
|
dependencies: []
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
pit('should work do correct browser mapping w/o js ext', function() {
|
||||||
|
var root = '/root';
|
||||||
|
fs.__setMockFilesystem({
|
||||||
|
'root': {
|
||||||
|
'index.js': [
|
||||||
|
'/**',
|
||||||
|
' * @providesModule index',
|
||||||
|
' */',
|
||||||
|
'require("aPackage")',
|
||||||
|
].join('\n'),
|
||||||
|
'aPackage': {
|
||||||
|
'package.json': JSON.stringify({
|
||||||
|
name: 'aPackage',
|
||||||
|
main: './main.js',
|
||||||
|
browser: {
|
||||||
|
'./main': './client.js',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
'main.js': 'some other code',
|
||||||
|
'client.js': 'some code',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var dgraph = new DependencyGraph({
|
||||||
|
roots: [root],
|
||||||
|
fileWatcher: fileWatcher
|
||||||
|
});
|
||||||
|
return dgraph.load().then(function() {
|
||||||
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
.toEqual([
|
||||||
|
{ id: 'index', altId: '/root/index.js',
|
||||||
|
path: '/root/index.js',
|
||||||
|
dependencies: ['aPackage']
|
||||||
|
},
|
||||||
|
{ id: 'aPackage/client',
|
||||||
|
path: '/root/aPackage/client.js',
|
||||||
|
dependencies: []
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
pit('should support browser mapping of files', function() {
|
||||||
|
var root = '/root';
|
||||||
|
fs.__setMockFilesystem({
|
||||||
|
'root': {
|
||||||
|
'index.js': [
|
||||||
|
'/**',
|
||||||
|
' * @providesModule index',
|
||||||
|
' */',
|
||||||
|
'require("aPackage")',
|
||||||
|
].join('\n'),
|
||||||
|
'aPackage': {
|
||||||
|
'package.json': JSON.stringify({
|
||||||
|
name: 'aPackage',
|
||||||
|
main: './main.js',
|
||||||
|
browser: {
|
||||||
|
'./main': './client.js',
|
||||||
|
'./node.js': './not-node.js',
|
||||||
|
'./not-browser': './browser.js',
|
||||||
|
'./dir/server.js': './dir/client',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
'main.js': 'some other code',
|
||||||
|
'client.js': 'require("./node")\nrequire("./dir/server.js")',
|
||||||
|
'not-node.js': 'require("./not-browser")',
|
||||||
|
'not-browser.js': 'require("./dir/server")',
|
||||||
|
'browser.js': 'some browser code',
|
||||||
|
'dir': {
|
||||||
|
'server.js': 'some node code',
|
||||||
|
'client.js': 'some browser code',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var dgraph = new DependencyGraph({
|
||||||
|
roots: [root],
|
||||||
|
fileWatcher: fileWatcher
|
||||||
|
});
|
||||||
|
return dgraph.load().then(function() {
|
||||||
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
.toEqual([
|
||||||
|
{ id: 'index', altId: '/root/index.js',
|
||||||
|
path: '/root/index.js',
|
||||||
|
dependencies: ['aPackage']
|
||||||
|
},
|
||||||
|
{ id: 'aPackage/client',
|
||||||
|
path: '/root/aPackage/client.js',
|
||||||
|
dependencies: ['./node', './dir/server.js']
|
||||||
|
},
|
||||||
|
{ id: 'aPackage/not-node',
|
||||||
|
path: '/root/aPackage/not-node.js',
|
||||||
|
dependencies: ['./not-browser']
|
||||||
|
},
|
||||||
|
{ id: 'aPackage/browser',
|
||||||
|
path: '/root/aPackage/browser.js',
|
||||||
|
dependencies: []
|
||||||
|
},
|
||||||
|
{ id: 'aPackage/dir/client',
|
||||||
|
path: '/root/aPackage/dir/client.js',
|
||||||
|
dependencies: []
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
pit('should support browser mapping for packages', function() {
|
||||||
|
var root = '/root';
|
||||||
|
fs.__setMockFilesystem({
|
||||||
|
'root': {
|
||||||
|
'index.js': [
|
||||||
|
'/**',
|
||||||
|
' * @providesModule index',
|
||||||
|
' */',
|
||||||
|
'require("aPackage")',
|
||||||
|
].join('\n'),
|
||||||
|
'aPackage': {
|
||||||
|
'package.json': JSON.stringify({
|
||||||
|
name: 'aPackage',
|
||||||
|
browser: {
|
||||||
|
'node-package': 'browser-package',
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
'index.js': 'require("node-package")',
|
||||||
|
'node-package': {
|
||||||
|
'package.json': JSON.stringify({
|
||||||
|
'name': 'node-package',
|
||||||
|
}),
|
||||||
|
'index.js': 'some node code',
|
||||||
|
},
|
||||||
|
'browser-package': {
|
||||||
|
'package.json': JSON.stringify({
|
||||||
|
'name': 'browser-package',
|
||||||
|
}),
|
||||||
|
'index.js': 'some browser code',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var dgraph = new DependencyGraph({
|
||||||
|
roots: [root],
|
||||||
|
fileWatcher: fileWatcher
|
||||||
|
});
|
||||||
|
return dgraph.load().then(function() {
|
||||||
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
.toEqual([
|
||||||
|
{ id: 'index', altId: '/root/index.js',
|
||||||
|
path: '/root/index.js',
|
||||||
|
dependencies: ['aPackage']
|
||||||
|
},
|
||||||
|
{ id: 'aPackage/index',
|
||||||
|
path: '/root/aPackage/index.js',
|
||||||
|
dependencies: ['node-package']
|
||||||
|
},
|
||||||
|
{ id: 'browser-package/index',
|
||||||
|
path: '/root/aPackage/browser-package/index.js',
|
||||||
|
dependencies: []
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('file watch updating', function() {
|
describe('file watch updating', function() {
|
||||||
|
|
|
@ -65,7 +65,7 @@ function DependecyGraph(options) {
|
||||||
this._debugUpdateEvents = [];
|
this._debugUpdateEvents = [];
|
||||||
|
|
||||||
this._moduleExtPattern = new RegExp(
|
this._moduleExtPattern = new RegExp(
|
||||||
'.' + ['js'].concat(this._assetExts).join('|') + '$'
|
'\.(' + ['js'].concat(this._assetExts).join('|') + ')$'
|
||||||
);
|
);
|
||||||
|
|
||||||
// Kick off the search process to precompute the dependency graph.
|
// Kick off the search process to precompute the dependency graph.
|
||||||
|
@ -168,15 +168,22 @@ DependecyGraph.prototype.resolveDependency = function(
|
||||||
// Package relative modules starts with '.' or '..'.
|
// Package relative modules starts with '.' or '..'.
|
||||||
if (depModuleId[0] !== '.') {
|
if (depModuleId[0] !== '.') {
|
||||||
|
|
||||||
// 1. `depModuleId` is simply a top-level `providesModule`.
|
// Check if we need to map the dependency to something else via the
|
||||||
// 2. `depModuleId` is a package module but given the full path from the
|
// `browser` field in package.json
|
||||||
|
var fromPackageJson = this._lookupPackage(fromModule.path);
|
||||||
|
if (fromPackageJson && fromPackageJson.browser &&
|
||||||
|
fromPackageJson.browser[depModuleId]) {
|
||||||
|
depModuleId = fromPackageJson.browser[depModuleId];
|
||||||
|
}
|
||||||
|
|
||||||
|
// `depModuleId` is simply a top-level `providesModule`.
|
||||||
|
// `depModuleId` is a package module but given the full path from the
|
||||||
// package, i.e. package_name/module_name
|
// package, i.e. package_name/module_name
|
||||||
if (this._moduleById[sansExtJs(depModuleId)]) {
|
if (this._moduleById[sansExtJs(depModuleId)]) {
|
||||||
return this._moduleById[sansExtJs(depModuleId)];
|
return this._moduleById[sansExtJs(depModuleId)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. `depModuleId` is a package and it's depending on the "main"
|
// `depModuleId` is a package and it's depending on the "main" resolution.
|
||||||
// resolution.
|
|
||||||
packageJson = this._packagesById[depModuleId];
|
packageJson = this._packagesById[depModuleId];
|
||||||
|
|
||||||
// We are being forgiving here and raising an error because we could be
|
// We are being forgiving here and raising an error because we could be
|
||||||
|
@ -190,7 +197,25 @@ DependecyGraph.prototype.resolveDependency = function(
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var main = packageJson.main || 'index';
|
var main;
|
||||||
|
|
||||||
|
// We prioritize the `browser` field if it's a module path.
|
||||||
|
if (typeof packageJson.browser === 'string') {
|
||||||
|
main = packageJson.browser;
|
||||||
|
} else {
|
||||||
|
main = packageJson.main || 'index';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is a mapping for main in the `browser` field.
|
||||||
|
if (packageJson.browser && typeof packageJson.browser === 'object') {
|
||||||
|
var tmpMain = packageJson.browser[main] ||
|
||||||
|
packageJson.browser[withExtJs(main)] ||
|
||||||
|
packageJson.browser[sansExtJs(main)];
|
||||||
|
if (tmpMain) {
|
||||||
|
main = tmpMain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
modulePath = withExtJs(path.join(packageJson._root, main));
|
modulePath = withExtJs(path.join(packageJson._root, main));
|
||||||
dep = this._graph[modulePath];
|
dep = this._graph[modulePath];
|
||||||
|
|
||||||
|
@ -207,8 +232,7 @@ DependecyGraph.prototype.resolveDependency = function(
|
||||||
return dep;
|
return dep;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// 4. `depModuleId` is a module defined in a package relative to
|
// `depModuleId` is a module defined in a package relative to `fromModule`.
|
||||||
// `fromModule`.
|
|
||||||
packageJson = this._lookupPackage(fromModule.path);
|
packageJson = this._lookupPackage(fromModule.path);
|
||||||
|
|
||||||
if (packageJson == null) {
|
if (packageJson == null) {
|
||||||
|
@ -224,12 +248,23 @@ DependecyGraph.prototype.resolveDependency = function(
|
||||||
var dir = path.dirname(fromModule.path);
|
var dir = path.dirname(fromModule.path);
|
||||||
modulePath = path.join(dir, depModuleId);
|
modulePath = path.join(dir, depModuleId);
|
||||||
|
|
||||||
|
if (packageJson.browser && typeof packageJson.browser === 'object') {
|
||||||
|
var relPath = './' + path.relative(packageJson._root, modulePath);
|
||||||
|
var tmpModulePath = packageJson.browser[withExtJs(relPath)] ||
|
||||||
|
packageJson.browser[sansExtJs(relPath)];
|
||||||
|
if (tmpModulePath) {
|
||||||
|
modulePath = path.join(packageJson._root, tmpModulePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// JS modules can be required without extensios.
|
||||||
if (this._assetExts.indexOf(extname(modulePath)) === -1) {
|
if (this._assetExts.indexOf(extname(modulePath)) === -1) {
|
||||||
modulePath = withExtJs(modulePath);
|
modulePath = withExtJs(modulePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
dep = this._graph[modulePath];
|
dep = this._graph[modulePath];
|
||||||
|
|
||||||
|
// Maybe the dependency is a directory and there is an index.js inside it.
|
||||||
if (dep == null) {
|
if (dep == null) {
|
||||||
modulePath = path.join(dir, depModuleId, 'index.js');
|
modulePath = path.join(dir, depModuleId, 'index.js');
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue