mirror of
https://github.com/status-im/react-native.git
synced 2025-03-04 03:10:47 +00:00
Merge pull request #1583 from sahrens/Update_Wed_Jun_10
Update wed jun 10
This commit is contained in:
commit
643d292099
@ -50,8 +50,8 @@ var GeolocationExample = React.createClass({
|
||||
componentDidMount: function() {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(initialPosition) => this.setState({initialPosition}),
|
||||
(error) => console.error(error),
|
||||
{enableHighAccuracy: true, timeout: 100, maximumAge: 1000}
|
||||
(error) => alert(error.message),
|
||||
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
|
||||
);
|
||||
this.watchID = navigator.geolocation.watchPosition((lastPosition) => {
|
||||
this.setState({lastPosition});
|
||||
|
@ -27,7 +27,7 @@ var CIRCLE_COLOR = 'blue';
|
||||
var CIRCLE_HIGHLIGHT_COLOR = 'green';
|
||||
|
||||
|
||||
var NavigatorIOSExample = React.createClass({
|
||||
var PanResponderExample = React.createClass({
|
||||
|
||||
statics: {
|
||||
title: 'PanResponder Sample',
|
||||
@ -133,4 +133,4 @@ var styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = NavigatorIOSExample;
|
||||
module.exports = PanResponderExample;
|
||||
|
@ -30,6 +30,7 @@
|
||||
1497CFB21B21F5E400C1F8F2 /* RCTSparseArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFAA1B21F5E400C1F8F2 /* RCTSparseArrayTests.m */; };
|
||||
1497CFB31B21F5E400C1F8F2 /* RCTUIManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFAB1B21F5E400C1F8F2 /* RCTUIManagerTests.m */; };
|
||||
14AADF051AC3DBB1002390C9 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14AADF041AC3DB95002390C9 /* libReact.a */; };
|
||||
14B6DA821B276C5900BF4DD1 /* libRCTTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58005BEE1ABA80530062E044 /* libRCTTest.a */; };
|
||||
14D6D7111B220EB3001FB087 /* libOCMock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14D6D7101B220EB3001FB087 /* libOCMock.a */; };
|
||||
14D6D71E1B2222EF001FB087 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 147CED4B1AB34F8C00DA3E4C /* libRCTActionSheet.a */; };
|
||||
14D6D71F1B2222EF001FB087 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1344545A1AAFCAAE003F0779 /* libRCTAdSupport.a */; };
|
||||
@ -44,7 +45,6 @@
|
||||
14D6D7281B2222EF001FB087 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDED91B0651EA00C62182 /* libRCTWebSocket.a */; };
|
||||
14D6D7291B2222EF001FB087 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14AADF041AC3DB95002390C9 /* libReact.a */; };
|
||||
14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14DC67F11AB71876001358AB /* libRCTPushNotification.a */; };
|
||||
58005BF21ABA80A60062E044 /* libRCTTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58005BEE1ABA80530062E044 /* libRCTTest.a */; };
|
||||
834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 834C36D21AF8DA610019C93C /* libRCTSettings.a */; };
|
||||
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
@ -229,7 +229,6 @@
|
||||
1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */,
|
||||
14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */,
|
||||
834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */,
|
||||
58005BF21ABA80A60062E044 /* libRCTTest.a in Frameworks */,
|
||||
134180011AA9153C003F314A /* libRCTText.a in Frameworks */,
|
||||
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */,
|
||||
139FDEDB1B0651FB00C62182 /* libRCTWebSocket.a in Frameworks */,
|
||||
@ -240,6 +239,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
14B6DA821B276C5900BF4DD1 /* libRCTTest.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -865,7 +865,7 @@
|
||||
"$(SRCROOT)/../../React/**",
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/UIExplorer/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited)";
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = UIExplorer;
|
||||
@ -883,7 +883,7 @@
|
||||
"$(SRCROOT)/../../React/**",
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/UIExplorer/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited)";
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = UIExplorer;
|
||||
@ -907,6 +907,12 @@
|
||||
INFOPLIST_FILE = UIExplorerIntegrationTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-framework",
|
||||
XCTest,
|
||||
"-ObjC",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UIExplorer.app/UIExplorer";
|
||||
};
|
||||
@ -926,6 +932,12 @@
|
||||
INFOPLIST_FILE = UIExplorerIntegrationTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-framework",
|
||||
XCTest,
|
||||
"-ObjC",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UIExplorer.app/UIExplorer";
|
||||
};
|
||||
|
@ -280,7 +280,7 @@
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../React/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.2;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -319,7 +319,7 @@
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../React/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.2;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
|
@ -28,14 +28,11 @@
|
||||
'use strict';
|
||||
|
||||
var AnimationsDebugModule = require('NativeModules').AnimationsDebugModule;
|
||||
var BackAndroid = require('BackAndroid');
|
||||
var Dimensions = require('Dimensions');
|
||||
var InteractionMixin = require('InteractionMixin');
|
||||
var NavigatorBreadcrumbNavigationBar = require('NavigatorBreadcrumbNavigationBar');
|
||||
var NavigatorInterceptor = require('NavigatorInterceptor');
|
||||
var NavigatorNavigationBar = require('NavigatorNavigationBar');
|
||||
var NavigatorSceneConfigs = require('NavigatorSceneConfigs');
|
||||
var NavigatorStaticContextContainer = require('NavigatorStaticContextContainer');
|
||||
var PanResponder = require('PanResponder');
|
||||
var Platform = require('Platform');
|
||||
var React = require('React');
|
||||
@ -47,7 +44,6 @@ var View = require('View');
|
||||
|
||||
var clamp = require('clamp');
|
||||
var flattenStyle = require('flattenStyle');
|
||||
var getNavigatorContext = require('getNavigatorContext');
|
||||
var invariant = require('invariant');
|
||||
var rebound = require('rebound');
|
||||
|
||||
@ -165,40 +161,6 @@ var GESTURE_ACTIONS = [
|
||||
* - `popToTop()` - Pop to the first scene in the stack, unmounting every
|
||||
* other scene
|
||||
*
|
||||
* ### Navigation Context
|
||||
*
|
||||
* The navigator context object is made available to scenes through the
|
||||
* `renderScene` function. Alternatively, any scene or component inside a
|
||||
* Navigator can get the navigation context by calling
|
||||
* `Navigator.getContext(this)`.
|
||||
*
|
||||
* Unlike the Navigator methods, the functions in navigation context do not
|
||||
* directly control a specific navigator. Instead, the navigator context allows
|
||||
* a scene to request navigation from its parents. Navigation requests will
|
||||
* travel up through the hierarchy of Navigators, and will be resolved by the
|
||||
* deepest active navigator.
|
||||
*
|
||||
* Navigation context objects contain the following:
|
||||
*
|
||||
* - `getCurrentRoutes()` - returns the routes for the closest navigator
|
||||
* - `jumpBack()` - Jump backward without unmounting the current scene
|
||||
* - `jumpForward()` - Jump forward to the next scene in the route stack
|
||||
* - `jumpTo(route)` - Transition to an existing scene without unmounting
|
||||
* - `parentNavigator` - a refrence to the parent navigation context
|
||||
* - `push(route)` - Navigate forward to a new scene, squashing any scenes
|
||||
* that you could `jumpForward` to
|
||||
* - `pop()` - Transition back and unmount the current scene
|
||||
* - `replace(route)` - Replace the current scene with a new route
|
||||
* - `replaceAtIndex(route, index)` - Replace a scene as specified by an index
|
||||
* - `replacePrevious(route)` - Replace the previous scene
|
||||
* - `route` - The route that was used to render the scene with this context
|
||||
* - `immediatelyResetRouteStack(routeStack)` - Reset every scene with an
|
||||
* array of routes
|
||||
* - `popToRoute(route)` - Pop to a particular scene, as specified by it's
|
||||
* route. All scenes after it will be unmounted
|
||||
* - `popToTop()` - Pop to the first scene in the stack, unmounting every
|
||||
* other scene
|
||||
*
|
||||
*/
|
||||
var Navigator = React.createClass({
|
||||
|
||||
@ -273,17 +235,10 @@ var Navigator = React.createClass({
|
||||
sceneStyle: View.propTypes.style,
|
||||
},
|
||||
|
||||
contextTypes: {
|
||||
// TODO (t6707746) Re-enable this when owner context switches to parent context
|
||||
// navigator: PropTypes.object,
|
||||
},
|
||||
|
||||
statics: {
|
||||
BreadcrumbNavigationBar: NavigatorBreadcrumbNavigationBar,
|
||||
NavigationBar: NavigatorNavigationBar,
|
||||
SceneConfigs: NavigatorSceneConfigs,
|
||||
Interceptor: NavigatorInterceptor,
|
||||
getContext: getNavigatorContext,
|
||||
},
|
||||
|
||||
mixins: [TimerMixin, InteractionMixin, Subscribable.Mixin],
|
||||
@ -328,34 +283,8 @@ var Navigator = React.createClass({
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.parentNavigator = getNavigatorContext(this) || this.props.navigator;
|
||||
this._subRouteFocus = [];
|
||||
this.navigatorContext = {
|
||||
// Actions for child navigators or interceptors:
|
||||
setHandlerForIndex: this.setHandlerForIndex,
|
||||
request: this.request,
|
||||
|
||||
// Contextual utilities
|
||||
parentNavigator: this.parentNavigator,
|
||||
getCurrentRoutes: this.getCurrentRoutes,
|
||||
// `route` is injected by NavigatorStaticContextContainer
|
||||
|
||||
// Contextual nav action
|
||||
pop: this.requestPop,
|
||||
|
||||
jumpBack: this.jumpBack,
|
||||
jumpForward: this.jumpForward,
|
||||
jumpTo: this.jumpTo,
|
||||
popToRoute: this.popToRoute,
|
||||
push: this.push,
|
||||
replace: this.replace,
|
||||
replaceAtIndex: this.replaceAtIndex,
|
||||
replacePrevious: this.replacePrevious,
|
||||
replacePreviousAndPop: this.replacePreviousAndPop,
|
||||
immediatelyResetRouteStack: this.immediatelyResetRouteStack,
|
||||
resetTo: this.resetTo,
|
||||
popToTop: this.popToTop,
|
||||
};
|
||||
this.parentNavigator = this.props.navigator;
|
||||
this._handlers = {};
|
||||
this.springSystem = new rebound.SpringSystem();
|
||||
this.spring = this.springSystem.createSpring();
|
||||
@ -386,91 +315,13 @@ var Navigator = React.createClass({
|
||||
this._emitWillFocus(this.state.routeStack[this.state.presentedIndex]);
|
||||
},
|
||||
|
||||
request: function(action, arg1, arg2) {
|
||||
if (this.parentNavigator) {
|
||||
return this.parentNavigator.request.apply(null, arguments);
|
||||
}
|
||||
return this._handleRequest.apply(null, arguments);
|
||||
},
|
||||
|
||||
requestPop: function(popToBeforeRoute) {
|
||||
return this.request('pop', popToBeforeRoute);
|
||||
},
|
||||
|
||||
requestPopTo: function(route) {
|
||||
return this.request('popTo', route);
|
||||
},
|
||||
|
||||
_handleRequest: function(action, arg1, arg2) {
|
||||
var childHandler = this._handlers[this.state.presentedIndex];
|
||||
if (childHandler && childHandler(action, arg1, arg2)) {
|
||||
return true;
|
||||
}
|
||||
switch (action) {
|
||||
case 'pop':
|
||||
return this._handlePop(arg1);
|
||||
case 'push':
|
||||
return this._handlePush(arg1);
|
||||
default:
|
||||
invariant(false, 'Unsupported request type ' + action);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
_handlePop: function(popToBeforeRoute) {
|
||||
if (popToBeforeRoute) {
|
||||
var popToBeforeRouteIndex = this.state.routeStack.indexOf(popToBeforeRoute);
|
||||
if (popToBeforeRouteIndex === -1) {
|
||||
return false;
|
||||
}
|
||||
invariant(
|
||||
popToBeforeRouteIndex <= this.state.presentedIndex,
|
||||
'Cannot pop past a route that is forward in the navigator'
|
||||
);
|
||||
this._popN(this.state.presentedIndex - popToBeforeRouteIndex + 1);
|
||||
return true;
|
||||
}
|
||||
if (this.state.presentedIndex === 0) {
|
||||
return false;
|
||||
}
|
||||
this.pop();
|
||||
return true;
|
||||
},
|
||||
|
||||
_handlePush: function(route) {
|
||||
this.push(route);
|
||||
return true;
|
||||
},
|
||||
|
||||
setHandlerForIndex: function(index, handler) {
|
||||
this._handlers[index] = handler;
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this._handleSpringUpdate();
|
||||
this._emitDidFocus(this.state.routeStack[this.state.presentedIndex]);
|
||||
if (this.parentNavigator) {
|
||||
this.parentNavigator.setHandler(this._handleRequest);
|
||||
} else if (Platform.OS === 'android') {
|
||||
// There is no navigator in our props or context, so this is the
|
||||
// top-level navigator. We will handle back button presses here
|
||||
BackAndroid.addEventListener('hardwareBackPress', this._handleAndroidBackPress);
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
if (this.parentNavigator) {
|
||||
this.parentNavigator.setHandler(null);
|
||||
} else if (Platform.OS === 'android') {
|
||||
BackAndroid.removeEventListener('hardwareBackPress', this._handleAndroidBackPress);
|
||||
}
|
||||
},
|
||||
|
||||
_handleAndroidBackPress: function() {
|
||||
var didPop = this.requestPop();
|
||||
if (!didPop) {
|
||||
BackAndroid.exitApp();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -532,8 +383,7 @@ var Navigator = React.createClass({
|
||||
this.spring.getSpringConfig().tension = sceneConfig.springTension;
|
||||
this.spring.setVelocity(velocity || sceneConfig.defaultTransitionVelocity);
|
||||
this.spring.setEndValue(1);
|
||||
var willFocusRoute = this._subRouteFocus[this.state.presentedIndex] || this.state.routeStack[this.state.presentedIndex];
|
||||
this._emitWillFocus(willFocusRoute);
|
||||
this._emitWillFocus(this.state.routeStack[this.state.presentedIndex]);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -611,23 +461,12 @@ var Navigator = React.createClass({
|
||||
},
|
||||
|
||||
_emitDidFocus: function(route) {
|
||||
if (this._lastDidFocus === route) {
|
||||
return;
|
||||
}
|
||||
this._lastDidFocus = route;
|
||||
if (this.props.onDidFocus) {
|
||||
this.props.onDidFocus(route);
|
||||
}
|
||||
if (this.parentNavigator && this.parentNavigator.onDidFocus) {
|
||||
this.parentNavigator.onDidFocus(route);
|
||||
}
|
||||
},
|
||||
|
||||
_emitWillFocus: function(route) {
|
||||
if (this._lastWillFocus === route) {
|
||||
return;
|
||||
}
|
||||
this._lastWillFocus = route;
|
||||
var navBar = this._navBar;
|
||||
if (navBar && navBar.handleWillFocus) {
|
||||
navBar.handleWillFocus(route);
|
||||
@ -635,9 +474,6 @@ var Navigator = React.createClass({
|
||||
if (this.props.onWillFocus) {
|
||||
this.props.onWillFocus(route);
|
||||
}
|
||||
if (this.parentNavigator && this.parentNavigator.onWillFocus) {
|
||||
this.parentNavigator.onWillFocus(route);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1237,41 +1073,20 @@ var Navigator = React.createClass({
|
||||
var shouldRenderScene =
|
||||
i >= this.state.updatingRangeStart &&
|
||||
i <= this.state.updatingRangeStart + this.state.updatingRangeLength;
|
||||
var sceneNavigatorContext = {
|
||||
...this.navigatorContext,
|
||||
route,
|
||||
setHandler: (handler) => {
|
||||
this.navigatorContext.setHandlerForIndex(i, handler);
|
||||
},
|
||||
onWillFocus: (childRoute) => {
|
||||
this._subRouteFocus[i] = childRoute;
|
||||
if (this.state.presentedIndex === i) {
|
||||
this._emitWillFocus(childRoute);
|
||||
}
|
||||
},
|
||||
onDidFocus: (childRoute) => {
|
||||
this._subRouteFocus[i] = childRoute;
|
||||
if (this.state.presentedIndex === i) {
|
||||
this._emitDidFocus(childRoute);
|
||||
}
|
||||
},
|
||||
};
|
||||
var scene = shouldRenderScene ?
|
||||
this._renderScene(route, i, sceneNavigatorContext) : null;
|
||||
var scene = shouldRenderScene ? this._renderScene(route, i) : null;
|
||||
return (
|
||||
<NavigatorStaticContextContainer
|
||||
navigatorContext={sceneNavigatorContext}
|
||||
<StaticContainer
|
||||
key={'nav' + i}
|
||||
shouldUpdate={shouldRenderScene}>
|
||||
{scene}
|
||||
</NavigatorStaticContextContainer>
|
||||
</StaticContainer>
|
||||
);
|
||||
},
|
||||
|
||||
_renderScene: function(route, i, sceneNavigatorContext) {
|
||||
_renderScene: function(route, i) {
|
||||
var child = this.props.renderScene(
|
||||
route,
|
||||
sceneNavigatorContext
|
||||
this
|
||||
);
|
||||
var disabledSceneStyle = null;
|
||||
if (i !== this.state.presentedIndex) {
|
||||
@ -1311,7 +1126,7 @@ var Navigator = React.createClass({
|
||||
}
|
||||
return React.cloneElement(this.props.navigationBar, {
|
||||
ref: (navBar) => { this._navBar = navBar; },
|
||||
navigator: this.navigatorContext,
|
||||
navigator: this,
|
||||
navState: this.state,
|
||||
});
|
||||
},
|
||||
|
@ -1,97 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||
*
|
||||
* Facebook, Inc. (“Facebook”) owns all right, title and interest, including
|
||||
* all intellectual property and other proprietary rights, in and to the React
|
||||
* Native CustomComponents software (the “Software”). Subject to your
|
||||
* compliance with these terms, you are hereby granted a non-exclusive,
|
||||
* worldwide, royalty-free copyright license to (1) use and copy the Software;
|
||||
* and (2) reproduce and distribute the Software as part of your own software
|
||||
* (“Your Software”). Facebook reserves all rights not expressly granted to
|
||||
* you in this license agreement.
|
||||
*
|
||||
* THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR
|
||||
* EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @providesModule NavigatorInterceptor
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('React');
|
||||
|
||||
var getNavigatorContext = require('getNavigatorContext');
|
||||
|
||||
var NavigatorInterceptor = React.createClass({
|
||||
|
||||
contextTypes: {
|
||||
navigator: React.PropTypes.object,
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.navigator = getNavigatorContext(this);
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.navigator.setHandler(this._navigatorHandleRequest);
|
||||
},
|
||||
|
||||
childContextTypes: {
|
||||
navigator: React.PropTypes.object,
|
||||
},
|
||||
|
||||
getChildContext: function() {
|
||||
return {
|
||||
navigator: {
|
||||
...this.navigator,
|
||||
setHandler: (handler) => {
|
||||
this._childNavigationHandler = handler;
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this.navigator.setHandler(null);
|
||||
},
|
||||
|
||||
_navigatorHandleRequest: function(action, arg1, arg2) {
|
||||
if (this._interceptorHandle(action, arg1, arg2)) {
|
||||
return true;
|
||||
}
|
||||
if (this._childNavigationHandler && this._childNavigationHandler(action, arg1, arg2)) {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
_interceptorHandle: function(action, arg1, arg2) {
|
||||
if (this.props.onRequest && this.props.onRequest(action, arg1, arg2)) {
|
||||
return true;
|
||||
}
|
||||
switch (action) {
|
||||
case 'pop':
|
||||
return this.props.onPopRequest && this.props.onPopRequest(arg1, arg2);
|
||||
case 'popTo':
|
||||
return this.props.onPopToRequest && this.props.onPopToRequest(arg1, arg2);
|
||||
case 'push':
|
||||
return this.props.onPushRequest && this.props.onPushRequest(arg1, arg2);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return this.props.children;
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
module.exports = NavigatorInterceptor;
|
@ -1,53 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||
*
|
||||
* Facebook, Inc. (“Facebook”) owns all right, title and interest, including
|
||||
* all intellectual property and other proprietary rights, in and to the React
|
||||
* Native CustomComponents software (the “Software”). Subject to your
|
||||
* compliance with these terms, you are hereby granted a non-exclusive,
|
||||
* worldwide, royalty-free copyright license to (1) use and copy the Software;
|
||||
* and (2) reproduce and distribute the Software as part of your own software
|
||||
* (“Your Software”). Facebook reserves all rights not expressly granted to
|
||||
* you in this license agreement.
|
||||
*
|
||||
* THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR
|
||||
* EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @providesModule NavigatorStaticContextContainer
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('React');
|
||||
var StaticContainer = require('StaticContainer.react');
|
||||
|
||||
var PropTypes = React.PropTypes;
|
||||
|
||||
var NavigatorStaticContextContainer = React.createClass({
|
||||
|
||||
childContextTypes: {
|
||||
navigator: PropTypes.object,
|
||||
},
|
||||
|
||||
getChildContext: function() {
|
||||
return {
|
||||
navigator: this.props.navigatorContext,
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<StaticContainer {...this.props} />
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = NavigatorStaticContextContainer;
|
@ -1,37 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||
*
|
||||
* Facebook, Inc. (“Facebook”) owns all right, title and interest, including
|
||||
* all intellectual property and other proprietary rights, in and to the React
|
||||
* Native CustomComponents software (the “Software”). Subject to your
|
||||
* compliance with these terms, you are hereby granted a non-exclusive,
|
||||
* worldwide, royalty-free copyright license to (1) use and copy the Software;
|
||||
* and (2) reproduce and distribute the Software as part of your own software
|
||||
* (“Your Software”). Facebook reserves all rights not expressly granted to
|
||||
* you in this license agreement.
|
||||
*
|
||||
* THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR
|
||||
* EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @providesModule getNavigatorContext
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
|
||||
var ReactInstanceMap = require('ReactInstanceMap');
|
||||
|
||||
function getNavigatorContext(el) {
|
||||
// TODO (t6707746): replace with `el.context.navigator` when parent context is supported
|
||||
return ReactInstanceMap.get(el)._context.navigator;
|
||||
}
|
||||
|
||||
module.exports = getNavigatorContext;
|
@ -152,7 +152,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -186,7 +186,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
|
@ -151,7 +151,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -186,7 +186,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
|
@ -152,7 +152,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -186,7 +186,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
|
@ -21,17 +21,17 @@
|
||||
/**
|
||||
* This notification triggers a reload of all bridges currently running.
|
||||
*/
|
||||
extern NSString *const RCTReloadNotification;
|
||||
RCT_EXTERN NSString *const RCTReloadNotification;
|
||||
|
||||
/**
|
||||
* This notification fires when the bridge has finished loading.
|
||||
*/
|
||||
extern NSString *const RCTJavaScriptDidLoadNotification;
|
||||
RCT_EXTERN NSString *const RCTJavaScriptDidLoadNotification;
|
||||
|
||||
/**
|
||||
* This notification fires when the bridge failed to load.
|
||||
*/
|
||||
extern NSString *const RCTJavaScriptDidFailToLoadNotification;
|
||||
RCT_EXTERN NSString *const RCTJavaScriptDidFailToLoadNotification;
|
||||
|
||||
/**
|
||||
* This block can be used to instantiate modules that require additional
|
||||
@ -43,6 +43,13 @@ extern NSString *const RCTJavaScriptDidFailToLoadNotification;
|
||||
*/
|
||||
typedef NSArray *(^RCTBridgeModuleProviderBlock)(void);
|
||||
|
||||
/**
|
||||
* Register the given class as a bridge module. All modules must be registered
|
||||
* prior to the first bridge initialization.
|
||||
*
|
||||
*/
|
||||
RCT_EXTERN void RCTRegisterModule(Class);
|
||||
|
||||
/**
|
||||
* This function returns the module name for a given class.
|
||||
*/
|
||||
|
@ -70,6 +70,30 @@ typedef struct section RCTHeaderSection;
|
||||
NSString *const RCTEnqueueNotification = @"RCTEnqueueNotification";
|
||||
NSString *const RCTDequeueNotification = @"RCTDequeueNotification";
|
||||
|
||||
static NSDictionary *RCTModuleIDsByName;
|
||||
static NSArray *RCTModuleNamesByID;
|
||||
static NSArray *RCTModuleClassesByID;
|
||||
void RCTRegisterModule(Class moduleClass)
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
RCTModuleIDsByName = [[NSMutableDictionary alloc] init];
|
||||
RCTModuleNamesByID = [[NSMutableArray alloc] init];
|
||||
RCTModuleClassesByID = [[NSMutableArray alloc] init];
|
||||
});
|
||||
|
||||
RCTAssert([moduleClass conformsToProtocol:@protocol(RCTBridgeModule)],
|
||||
@"%@ does not conform to the RCTBridgeModule protocol",
|
||||
NSStringFromClass(moduleClass));
|
||||
|
||||
// Register module
|
||||
NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass);
|
||||
((NSMutableDictionary *)RCTModuleIDsByName)[moduleName] = @(RCTModuleNamesByID.count);
|
||||
[(NSMutableArray *)RCTModuleNamesByID addObject:moduleName];
|
||||
[(NSMutableArray *)RCTModuleClassesByID addObject:moduleClass];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns the module name for a given class.
|
||||
*/
|
||||
@ -122,93 +146,6 @@ static NSArray *RCTJSMethods(void)
|
||||
return JSMethods;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function scans all exported modules available at runtime and returns an
|
||||
* array. As a backup, it also scans all classes that implement the
|
||||
* RTCBridgeModule protocol to ensure they've been exported. This scanning
|
||||
* functionality is disabled in release mode to improve startup performance.
|
||||
*/
|
||||
static NSDictionary *RCTModuleIDsByName;
|
||||
static NSArray *RCTModuleNamesByID;
|
||||
static NSArray *RCTModuleClassesByID;
|
||||
static NSArray *RCTBridgeModuleClassesByModuleID(void)
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
|
||||
RCTModuleIDsByName = [[NSMutableDictionary alloc] init];
|
||||
RCTModuleNamesByID = [[NSMutableArray alloc] init];
|
||||
RCTModuleClassesByID = [[NSMutableArray alloc] init];
|
||||
|
||||
Dl_info info;
|
||||
dladdr(&RCTBridgeModuleClassesByModuleID, &info);
|
||||
|
||||
const RCTHeaderValue mach_header = (RCTHeaderValue)info.dli_fbase;
|
||||
unsigned long size;
|
||||
const uint8_t *sectionData = getsectiondata(mach_header, "__DATA", "RCTExportModule", &size);
|
||||
if (sectionData) {
|
||||
for (const uint8_t *addr = sectionData;
|
||||
addr < sectionData + size;
|
||||
addr += sizeof(const char **)) {
|
||||
|
||||
// Get data entry
|
||||
NSString *entry = @(*(const char **)addr);
|
||||
NSArray *parts = [[entry substringWithRange:(NSRange){2, entry.length - 3}]
|
||||
componentsSeparatedByString:@" "];
|
||||
|
||||
// Parse class name
|
||||
NSString *moduleClassName = parts[0];
|
||||
NSRange categoryRange = [moduleClassName rangeOfString:@"("];
|
||||
if (categoryRange.length) {
|
||||
moduleClassName = [moduleClassName substringToIndex:categoryRange.location];
|
||||
}
|
||||
|
||||
// Get class
|
||||
Class cls = NSClassFromString(moduleClassName);
|
||||
RCTAssert([cls conformsToProtocol:@protocol(RCTBridgeModule)],
|
||||
@"%@ does not conform to the RCTBridgeModule protocol",
|
||||
NSStringFromClass(cls));
|
||||
|
||||
// Register module
|
||||
NSString *moduleName = RCTBridgeModuleNameForClass(cls);
|
||||
((NSMutableDictionary *)RCTModuleIDsByName)[moduleName] = @(RCTModuleNamesByID.count);
|
||||
[(NSMutableArray *)RCTModuleNamesByID addObject:moduleName];
|
||||
[(NSMutableArray *)RCTModuleClassesByID addObject:cls];
|
||||
}
|
||||
}
|
||||
|
||||
if (RCT_DEBUG) {
|
||||
|
||||
// We may be able to get rid of this check in future, once people
|
||||
// get used to the new registration system. That would potentially
|
||||
// allow you to create modules that are not automatically registered
|
||||
|
||||
static unsigned int classCount;
|
||||
Class *classes = objc_copyClassList(&classCount);
|
||||
for (unsigned int i = 0; i < classCount; i++)
|
||||
{
|
||||
Class cls = classes[i];
|
||||
Class superclass = cls;
|
||||
while (superclass)
|
||||
{
|
||||
if (class_conformsToProtocol(superclass, @protocol(RCTBridgeModule)))
|
||||
{
|
||||
if (![RCTModuleClassesByID containsObject:cls]) {
|
||||
RCTLogError(@"Class %@ was not exported. Did you forget to use RCT_EXPORT_MODULE()?", NSStringFromClass(cls));
|
||||
}
|
||||
break;
|
||||
}
|
||||
superclass = class_getSuperclass(superclass);
|
||||
}
|
||||
}
|
||||
free(classes);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return RCTModuleClassesByID;
|
||||
}
|
||||
|
||||
// TODO: Can we just replace RCTMakeError with this function instead?
|
||||
static NSDictionary *RCTJSErrorFromNSError(NSError *error)
|
||||
{
|
||||
@ -278,25 +215,42 @@ static NSDictionary *RCTJSErrorFromNSError(NSError *error)
|
||||
dispatch_block_t _methodQueue;
|
||||
}
|
||||
|
||||
- (instancetype)initWithReactMethodName:(NSString *)reactMethodName
|
||||
objCMethodName:(NSString *)objCMethodName
|
||||
JSMethodName:(NSString *)JSMethodName
|
||||
- (instancetype)initWithObjCMethodName:(NSString *)objCMethodName
|
||||
JSMethodName:(NSString *)JSMethodName
|
||||
moduleClass:(Class)moduleClass
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
static NSRegularExpression *typeRegex;
|
||||
static NSRegularExpression *selectorRegex;
|
||||
if (!typeRegex) {
|
||||
NSString *unusedPattern = @"(?:(?:__unused|__attribute__\\(\\(unused\\)\\)))";
|
||||
NSString *constPattern = @"(?:const)";
|
||||
NSString *constUnusedPattern = [NSString stringWithFormat:@"(?:(?:%@|%@)\\s*)", unusedPattern, constPattern];
|
||||
NSString *pattern = [NSString stringWithFormat:@"\\(%1$@?(\\w+?)(?:\\s*\\*)?%1$@?\\)", constUnusedPattern];
|
||||
typeRegex = [[NSRegularExpression alloc] initWithPattern:pattern options:0 error:NULL];
|
||||
|
||||
NSArray *parts = [[reactMethodName substringWithRange:(NSRange){2, reactMethodName.length - 3}] componentsSeparatedByString:@" "];
|
||||
|
||||
// Parse class and method
|
||||
_moduleClassName = parts[0];
|
||||
NSRange categoryRange = [_moduleClassName rangeOfString:@"("];
|
||||
if (categoryRange.length) {
|
||||
_moduleClassName = [_moduleClassName substringToIndex:categoryRange.location];
|
||||
selectorRegex = [[NSRegularExpression alloc] initWithPattern:@"(?<=:).*?(?=[a-zA-Z_]+:|$)" options:0 error:NULL];
|
||||
}
|
||||
|
||||
NSString *selectorString = [parts[1] substringFromIndex:14];
|
||||
_selector = NSSelectorFromString(selectorString);
|
||||
_JSMethodName = JSMethodName ?: ({
|
||||
NSString *methodName = selectorString;
|
||||
NSMutableArray *argumentNames = [NSMutableArray array];
|
||||
[typeRegex enumerateMatchesInString:objCMethodName options:0 range:NSMakeRange(0, objCMethodName.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
|
||||
NSString *argumentName = [objCMethodName substringWithRange:[result rangeAtIndex:1]];
|
||||
[argumentNames addObject:argumentName];
|
||||
}];
|
||||
|
||||
// Remove the parameters' type and name
|
||||
objCMethodName = [selectorRegex stringByReplacingMatchesInString:objCMethodName
|
||||
options:0
|
||||
range:NSMakeRange(0, objCMethodName.length)
|
||||
withTemplate:@""];
|
||||
// Remove any spaces since `selector : (Type)name` is a valid syntax
|
||||
objCMethodName = [objCMethodName stringByReplacingOccurrencesOfString:@" " withString:@""];
|
||||
|
||||
_moduleClass = moduleClass;
|
||||
_moduleClassName = NSStringFromClass(_moduleClass);
|
||||
_selector = NSSelectorFromString(objCMethodName);
|
||||
_JSMethodName = JSMethodName.length > 0 ? JSMethodName : ({
|
||||
NSString *methodName = NSStringFromSelector(_selector);
|
||||
NSRange colonRange = [methodName rangeOfString:@":"];
|
||||
if (colonRange.length) {
|
||||
methodName = [methodName substringToIndex:colonRange.location];
|
||||
@ -304,31 +258,6 @@ static NSDictionary *RCTJSErrorFromNSError(NSError *error)
|
||||
methodName;
|
||||
});
|
||||
|
||||
static NSRegularExpression *regExp;
|
||||
if (!regExp) {
|
||||
NSString *unusedPattern = @"(?:(?:__unused|__attribute__\\(\\(unused\\)\\)))";
|
||||
NSString *constPattern = @"(?:const)";
|
||||
NSString *constUnusedPattern = [NSString stringWithFormat:@"(?:(?:%@|%@)\\s*)", unusedPattern, constPattern];
|
||||
NSString *pattern = [NSString stringWithFormat:@"\\(%1$@?(\\w+?)(?:\\s*\\*)?%1$@?\\)", constUnusedPattern];
|
||||
regExp = [[NSRegularExpression alloc] initWithPattern:pattern options:0 error:NULL];
|
||||
}
|
||||
|
||||
NSMutableArray *argumentNames = [NSMutableArray array];
|
||||
[regExp enumerateMatchesInString:objCMethodName options:0 range:NSMakeRange(0, objCMethodName.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
|
||||
NSString *argumentName = [objCMethodName substringWithRange:[result rangeAtIndex:1]];
|
||||
[argumentNames addObject:argumentName];
|
||||
}];
|
||||
|
||||
// Extract class and method details
|
||||
_moduleClass = NSClassFromString(_moduleClassName);
|
||||
|
||||
if (RCT_DEBUG) {
|
||||
|
||||
// Sanity check
|
||||
RCTAssert([_moduleClass conformsToProtocol:@protocol(RCTBridgeModule)],
|
||||
@"You are attempting to export the method %@, but %@ does not \
|
||||
conform to the RCTBridgeModule Protocol", objCMethodName, _moduleClassName);
|
||||
}
|
||||
|
||||
// Get method signature
|
||||
_methodSignature = [_moduleClass instanceMethodSignatureForSelector:_selector];
|
||||
@ -554,44 +483,33 @@ static RCTSparseArray *RCTExportedMethodsByModuleID(void)
|
||||
static RCTSparseArray *methodsByModuleID;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
methodsByModuleID = [[RCTSparseArray alloc] initWithCapacity:[RCTModuleClassesByID count]];
|
||||
|
||||
Dl_info info;
|
||||
dladdr(&RCTExportedMethodsByModuleID, &info);
|
||||
[RCTModuleClassesByID enumerateObjectsUsingBlock:^(Class moduleClass, NSUInteger moduleID, BOOL *stop) {
|
||||
|
||||
const RCTHeaderValue mach_header = (RCTHeaderValue)info.dli_fbase;
|
||||
methodsByModuleID[moduleID] = [[NSMutableArray alloc] init];
|
||||
|
||||
unsigned long size;
|
||||
const uint8_t *sectionData = getsectiondata(mach_header, "__DATA", "RCTExport", &size);
|
||||
unsigned int methodCount;
|
||||
Method *methods = class_copyMethodList(object_getClass(moduleClass), &methodCount);
|
||||
|
||||
if (sectionData == NULL) {
|
||||
return;
|
||||
}
|
||||
for (unsigned int i = 0; i < methodCount; i++) {
|
||||
Method method = methods[i];
|
||||
SEL selector = method_getName(method);
|
||||
if ([NSStringFromSelector(selector) hasPrefix:@"__rct_export__"]) {
|
||||
NSArray *entries = ((NSArray *(*)(id, SEL))objc_msgSend)(moduleClass, selector);
|
||||
RCTModuleMethod *moduleMethod =
|
||||
[[RCTModuleMethod alloc] initWithObjCMethodName:entries[1]
|
||||
JSMethodName:entries[0]
|
||||
moduleClass:moduleClass];
|
||||
|
||||
NSArray *classes = RCTBridgeModuleClassesByModuleID();
|
||||
NSMutableDictionary *methodsByModuleClassName = [NSMutableDictionary dictionaryWithCapacity:[classes count]];
|
||||
[methodsByModuleID[moduleID] addObject:moduleMethod];
|
||||
}
|
||||
}
|
||||
|
||||
for (const uint8_t *addr = sectionData;
|
||||
addr < sectionData + size;
|
||||
addr += sizeof(const char **) * 3) {
|
||||
free(methods);
|
||||
|
||||
// Get data entry
|
||||
const char **entries = (const char **) addr;
|
||||
|
||||
// Create method
|
||||
RCTModuleMethod *moduleMethod =
|
||||
[[RCTModuleMethod alloc] initWithReactMethodName:@(entries[0])
|
||||
objCMethodName:@(entries[1])
|
||||
JSMethodName:strlen(entries[2]) ? @(entries[2]) : nil];
|
||||
// Cache method
|
||||
NSArray *methods = methodsByModuleClassName[moduleMethod.moduleClassName];
|
||||
methodsByModuleClassName[moduleMethod.moduleClassName] =
|
||||
methods ? [methods arrayByAddingObject:moduleMethod] : @[moduleMethod];
|
||||
}
|
||||
|
||||
methodsByModuleID = [[RCTSparseArray alloc] initWithCapacity:[classes count]];
|
||||
[classes enumerateObjectsUsingBlock:^(Class moduleClass, NSUInteger moduleID, BOOL *stop) {
|
||||
methodsByModuleID[moduleID] = methodsByModuleClassName[NSStringFromClass(moduleClass)];
|
||||
}];
|
||||
|
||||
});
|
||||
|
||||
return methodsByModuleID;
|
||||
@ -630,7 +548,7 @@ static NSDictionary *RCTRemoteModulesConfig(NSDictionary *modulesByName)
|
||||
dispatch_once(&onceToken, ^{
|
||||
|
||||
remoteModuleConfigByClassName = [[NSMutableDictionary alloc] init];
|
||||
[RCTBridgeModuleClassesByModuleID() enumerateObjectsUsingBlock:^(Class moduleClass, NSUInteger moduleID, BOOL *stop) {
|
||||
[RCTModuleClassesByID enumerateObjectsUsingBlock:^(Class moduleClass, NSUInteger moduleID, BOOL *stop) {
|
||||
|
||||
NSArray *methods = RCTExportedMethodsByModuleID()[moduleID];
|
||||
NSMutableDictionary *methodsByName = [NSMutableDictionary dictionaryWithCapacity:methods.count];
|
||||
@ -768,6 +686,38 @@ static NSDictionary *RCTLocalModulesConfig()
|
||||
|
||||
static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
||||
|
||||
#if RCT_DEBUG
|
||||
+ (void)initialize
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
|
||||
static unsigned int classCount;
|
||||
Class *classes = objc_copyClassList(&classCount);
|
||||
|
||||
for (unsigned int i = 0; i < classCount; i++)
|
||||
{
|
||||
Class cls = classes[i];
|
||||
Class superclass = cls;
|
||||
while (superclass)
|
||||
{
|
||||
if (class_conformsToProtocol(superclass, @protocol(RCTBridgeModule)))
|
||||
{
|
||||
if (![RCTModuleClassesByID containsObject:cls]) {
|
||||
RCTLogError(@"Class %@ was not exported. Did you forget to use RCT_EXPORT_MODULE()?", NSStringFromClass(cls));
|
||||
}
|
||||
break;
|
||||
}
|
||||
superclass = class_getSuperclass(superclass);
|
||||
}
|
||||
}
|
||||
|
||||
free(classes);
|
||||
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
|
||||
moduleProvider:(RCTBridgeModuleProviderBlock)block
|
||||
launchOptions:(NSDictionary *)launchOptions
|
||||
@ -1006,7 +956,7 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
||||
// Instantiate modules
|
||||
_modulesByID = [[RCTSparseArray alloc] init];
|
||||
NSMutableDictionary *modulesByName = [preregisteredModules mutableCopy];
|
||||
[RCTBridgeModuleClassesByModuleID() enumerateObjectsUsingBlock:^(Class moduleClass, NSUInteger moduleID, BOOL *stop) {
|
||||
[RCTModuleClassesByID enumerateObjectsUsingBlock:^(Class moduleClass, NSUInteger moduleID, BOOL *stop) {
|
||||
NSString *moduleName = RCTModuleNamesByID[moduleID];
|
||||
// Check if module instance has already been registered for this name
|
||||
id<RCTBridgeModule> module = modulesByName[moduleName];
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTDefines.h"
|
||||
|
||||
@class RCTBridge;
|
||||
|
||||
/**
|
||||
@ -62,8 +64,9 @@ extern const dispatch_queue_t RCTJSThread;
|
||||
* match the Objective-C class name.
|
||||
*/
|
||||
#define RCT_EXPORT_MODULE(js_name) \
|
||||
+ (NSString *)moduleName { __attribute__((used, section("__DATA,RCTExportModule" \
|
||||
))) static const char *__rct_export_entry__ = { __func__ }; return @#js_name; }
|
||||
RCT_EXTERN void RCTRegisterModule(Class); \
|
||||
+ (NSString *)moduleName { return @#js_name; } \
|
||||
+ (void)load { RCTRegisterModule([self class]); }
|
||||
|
||||
/**
|
||||
* Wrap the parameter line of your method implementation with this macro to
|
||||
@ -173,11 +176,10 @@ extern const dispatch_queue_t RCTJSThread;
|
||||
* Like RCT_EXTERN_REMAP_METHOD, but allows setting a custom JavaScript name.
|
||||
*/
|
||||
#define RCT_EXTERN_REMAP_METHOD(js_name, method) \
|
||||
- (void)__rct_export__##method { \
|
||||
__attribute__((used, section("__DATA,RCTExport"))) \
|
||||
__attribute__((__aligned__(1))) \
|
||||
static const char *__rct_export_entry__[] = { __func__, #method, #js_name }; \
|
||||
}
|
||||
+ (NSArray *)RCT_CONCAT(__rct_export__, __COUNTER__) { \
|
||||
return @[@#js_name, @#method]; \
|
||||
} \
|
||||
|
||||
|
||||
/**
|
||||
* The queue that will be used to call all exported methods. If omitted, this
|
||||
|
@ -74,3 +74,11 @@
|
||||
#define RCT_NSASSERT 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Concat two literals. Supports macro expansions
|
||||
*
|
||||
* i.e. RCT_CONCAT(foo, __FILE__)
|
||||
*/
|
||||
#define RCT_CONCAT2(A, B) A ## B
|
||||
#define RCT_CONCAT(A, B) RCT_CONCAT2(A, B)
|
||||
|
Loading…
x
Reference in New Issue
Block a user