update FabricUIManager to call the right JS object
Reviewed By: sebmarkbage Differential Revision: D7037275 fbshipit-source-id: 6a1d13227910d0cdb99dde4b6c98ed7a20ef9911
This commit is contained in:
parent
25b0c374b3
commit
486ac9dc82
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @providesModule FabricView
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* This is a temporary fork of View.js for Fabric purpose.
|
||||
* Do not use outside of Fabric tree.
|
||||
*/
|
||||
|
||||
const Platform = require('Platform');
|
||||
const React = require('React');
|
||||
const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
|
||||
const ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
const ViewPropTypes = require('ViewPropTypes');
|
||||
const {NativeMethodsMixin} = require('ReactFabricInternals');
|
||||
const {ViewContextTypes} = require('ViewContext');
|
||||
|
||||
const createReactClass = require('create-react-class');
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
const requireFabricComponent = require('requireFabricComponent');
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type {ViewChildContext} from 'ViewContext';
|
||||
|
||||
export type Props = ViewProps;
|
||||
|
||||
/**
|
||||
* The most fundamental component for building a UI.
|
||||
*
|
||||
* See http://facebook.github.io/react-native/docs/view.html
|
||||
*/
|
||||
const View = createReactClass({
|
||||
displayName: 'View',
|
||||
// TODO: We should probably expose the mixins, viewConfig, and statics publicly. For example,
|
||||
// one of the props is of type AccessibilityComponentType. That is defined as a const[] above,
|
||||
// but it is not rendered by the docs, since `statics` below is not rendered. So its Possible
|
||||
// values had to be hardcoded.
|
||||
mixins: [NativeMethodsMixin],
|
||||
|
||||
// `propTypes` should not be accessed directly on View since this wrapper only
|
||||
// exists for DEV mode. However it's important for them to be declared.
|
||||
// If the object passed to `createClass` specifies `propTypes`, Flow will
|
||||
// create a static type from it.
|
||||
propTypes: ViewPropTypes,
|
||||
|
||||
/**
|
||||
* `NativeMethodsMixin` will look for this when invoking `setNativeProps`. We
|
||||
* make `this` look like an actual native component class.
|
||||
*/
|
||||
viewConfig: {
|
||||
uiViewClassName: 'RCTView',
|
||||
validAttributes: ReactNativeViewAttributes.RCTView,
|
||||
},
|
||||
|
||||
childContextTypes: ViewContextTypes,
|
||||
|
||||
getChildContext(): ViewChildContext {
|
||||
return {
|
||||
isInAParentText: false,
|
||||
};
|
||||
},
|
||||
|
||||
render() {
|
||||
invariant(
|
||||
!(this.context.isInAParentText && Platform.OS === 'android'),
|
||||
'Nesting of <View> within <Text> is not supported on Android.',
|
||||
);
|
||||
|
||||
// WARNING: This method will not be used in production mode as in that mode we
|
||||
// replace wrapper component View with generated native wrapper RCTView. Avoid
|
||||
// adding functionality this component that you'd want to be available in both
|
||||
// dev and prod modes.
|
||||
return <RCTView {...this.props} />;
|
||||
},
|
||||
});
|
||||
|
||||
const RCTView = requireFabricComponent('RCTView', View, {
|
||||
nativeOnly: {
|
||||
nativeBackgroundAndroid: true,
|
||||
nativeForegroundAndroid: true,
|
||||
},
|
||||
fabric: true,
|
||||
});
|
||||
|
||||
if (__DEV__) {
|
||||
const UIManager = require('UIManager');
|
||||
const viewConfig =
|
||||
(UIManager.viewConfigs && UIManager.viewConfigs.RCTView) || {};
|
||||
for (const prop in viewConfig.nativeProps) {
|
||||
const viewAny: any = View; // Appease flow
|
||||
if (!viewAny.propTypes[prop] && !ReactNativeStyleAttributes[prop]) {
|
||||
throw new Error(
|
||||
'View is missing propType for native prop `' + prop + '`',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let ViewToExport = RCTView;
|
||||
if (__DEV__) {
|
||||
ViewToExport = View;
|
||||
}
|
||||
|
||||
// No one should depend on the DEV-mode createClass View wrapper.
|
||||
module.exports = ((ViewToExport: any): typeof RCTView);
|
|
@ -27,6 +27,7 @@ type Props = {|
|
|||
* suppresses an error when upgrading Flow's support for React. To see the
|
||||
* error delete this comment and run Flow. */
|
||||
children?: React.Children,
|
||||
fabric?: boolean,
|
||||
rootTag: number,
|
||||
WrapperComponent?: ?React.ComponentType<*>,
|
||||
|};
|
||||
|
@ -90,7 +91,8 @@ class AppContainer extends React.Component<Props, State> {
|
|||
render(): React.Node {
|
||||
let yellowBox = null;
|
||||
if (__DEV__) {
|
||||
if (!global.__RCTProfileIsProfiling) {
|
||||
if (!global.__RCTProfileIsProfiling && !this.props.fabric) {
|
||||
// TODO: Fabric doesn't support YellowBox.
|
||||
const YellowBox = require('YellowBox');
|
||||
yellowBox = <YellowBox />;
|
||||
}
|
||||
|
|
|
@ -10,53 +10,29 @@
|
|||
*/
|
||||
'use strict';
|
||||
|
||||
// TODO: fix the types
|
||||
type Node = number;
|
||||
type NodeSet = number;
|
||||
// TODO: type these properly.
|
||||
type Node = {};
|
||||
type NodeSet = Array<Node>;
|
||||
type NodeProps = {};
|
||||
type InstanceHandle = {};
|
||||
type Spec = {|
|
||||
+createNode: (
|
||||
reactTag: number,
|
||||
viewName: string,
|
||||
rootTag: number,
|
||||
props: NodeProps,
|
||||
instanceHandle: number,
|
||||
instanceHandle: InstanceHandle,
|
||||
) => Node,
|
||||
+cloneNode: (node: Node) => Node,
|
||||
+cloneNodeWithNewChildren: (node: Node) => Node,
|
||||
+cloneNodeWithNewProps: (node: Node, newProps: NodeProps) => Node,
|
||||
+cloneNodeWithNewChildrenAndProps: (node: Node, newProps: NodeProps) => Node,
|
||||
+createChildSet: (rootTag: number) => NodeSet,
|
||||
+appendChild: (parentNode: Node, child: Node) => Node,
|
||||
+appendChildToSet: (childSet: NodeSet, child: Node) => void,
|
||||
+completeRoot: (rootTag: number, childSet: NodeSet) => void,
|
||||
|};
|
||||
|
||||
const NativeFabricUIManager: Spec = require('NativeModules').FabricUIManager;
|
||||
|
||||
const FabricUIManager: Spec = {
|
||||
createNode(
|
||||
reactTag: number,
|
||||
viewName: string,
|
||||
rootTag: number,
|
||||
props: NodeProps,
|
||||
instanceHandle: number,
|
||||
): number {
|
||||
return NativeFabricUIManager.createNode(
|
||||
reactTag,
|
||||
viewName,
|
||||
rootTag,
|
||||
props,
|
||||
0, // TODO: instanceHandle is cannot be JSON serialized.
|
||||
);
|
||||
},
|
||||
cloneNode: NativeFabricUIManager.cloneNode,
|
||||
cloneNodeWithNewChildren: NativeFabricUIManager.cloneNodeWithNewChildren,
|
||||
cloneNodeWithNewProps: NativeFabricUIManager.cloneNodeWithNewProps,
|
||||
cloneNodeWithNewChildrenAndProps:
|
||||
NativeFabricUIManager.cloneNodeWithNewChildrenAndProps,
|
||||
appendChild: NativeFabricUIManager.appendChild,
|
||||
appendChildToSet: NativeFabricUIManager.appendChildToSet,
|
||||
completeRoot: NativeFabricUIManager.completeRoot,
|
||||
};
|
||||
const FabricUIManager: ?Spec = global.nativeFabricUIManager;
|
||||
|
||||
module.exports = FabricUIManager;
|
||||
|
|
|
@ -30,7 +30,10 @@ function renderFabricSurface<Props: Object>(
|
|||
invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag);
|
||||
|
||||
let renderable = (
|
||||
<AppContainer rootTag={rootTag} WrapperComponent={WrapperComponent}>
|
||||
<AppContainer
|
||||
fabric={true}
|
||||
rootTag={rootTag}
|
||||
WrapperComponent={WrapperComponent}>
|
||||
<RootComponent {...initialProps} rootTag={rootTag} />
|
||||
</AppContainer>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @providesModule requireFabricComponent
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const Platform = require('Platform');
|
||||
const {
|
||||
ReactNativeBridgeEventPlugin,
|
||||
createReactNativeComponentClass,
|
||||
} = require('ReactFabricInternals');
|
||||
const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
|
||||
const UIManager = require('UIManager');
|
||||
|
||||
const insetsDiffer = require('insetsDiffer');
|
||||
const matricesDiffer = require('matricesDiffer');
|
||||
const pointsDiffer = require('pointsDiffer');
|
||||
const processColor = require('processColor');
|
||||
const resolveAssetSource = require('resolveAssetSource');
|
||||
const sizesDiffer = require('sizesDiffer');
|
||||
const verifyPropTypes = require('verifyPropTypes');
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
const warning = require('fbjs/lib/warning');
|
||||
|
||||
/**
|
||||
* Used to create React components that directly wrap native component
|
||||
* implementations. Config information is extracted from data exported from the
|
||||
* UIManager module. You should also wrap the native component in a
|
||||
* hand-written component with full propTypes definitions and other
|
||||
* documentation - pass the hand-written component in as `componentInterface` to
|
||||
* verify all the native props are documented via `propTypes`.
|
||||
*
|
||||
* If some native props shouldn't be exposed in the wrapper interface, you can
|
||||
* pass null for `componentInterface` and call `verifyPropTypes` directly
|
||||
* with `nativePropsToIgnore`;
|
||||
*
|
||||
* Common types are lined up with the appropriate prop differs with
|
||||
* `TypeToDifferMap`. Non-scalar types not in the map default to `deepDiffer`.
|
||||
*/
|
||||
import type {ComponentInterface} from 'verifyPropTypes';
|
||||
|
||||
let hasAttachedDefaultEventTypes: boolean = false;
|
||||
|
||||
function requireNativeComponent(
|
||||
viewName: string,
|
||||
componentInterface?: ?ComponentInterface,
|
||||
extraConfig?: ?{nativeOnly?: Object},
|
||||
): React$ComponentType<any> | string {
|
||||
function attachDefaultEventTypes(viewConfig: any) {
|
||||
if (Platform.OS === 'android') {
|
||||
// This is supported on Android platform only,
|
||||
// as lazy view managers discovery is Android-specific.
|
||||
if (UIManager.ViewManagerNames) {
|
||||
// Lazy view managers enabled.
|
||||
viewConfig = merge(viewConfig, UIManager.getDefaultEventTypes());
|
||||
} else {
|
||||
viewConfig.bubblingEventTypes = merge(
|
||||
viewConfig.bubblingEventTypes,
|
||||
UIManager.genericBubblingEventTypes,
|
||||
);
|
||||
viewConfig.directEventTypes = merge(
|
||||
viewConfig.directEventTypes,
|
||||
UIManager.genericDirectEventTypes,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function merge(destination: ?Object, source: ?Object): ?Object {
|
||||
if (!source) {
|
||||
return destination;
|
||||
}
|
||||
if (!destination) {
|
||||
return source;
|
||||
}
|
||||
|
||||
for (const key in source) {
|
||||
if (!source.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var sourceValue = source[key];
|
||||
if (destination.hasOwnProperty(key)) {
|
||||
const destinationValue = destination[key];
|
||||
if (
|
||||
typeof sourceValue === 'object' &&
|
||||
typeof destinationValue === 'object'
|
||||
) {
|
||||
sourceValue = merge(destinationValue, sourceValue);
|
||||
}
|
||||
}
|
||||
destination[key] = sourceValue;
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
// Don't load the ViewConfig from UIManager until it's needed for rendering.
|
||||
// Lazy-loading this can help avoid Prepack deopts.
|
||||
function getViewConfig() {
|
||||
const viewConfig = UIManager[viewName];
|
||||
|
||||
invariant(
|
||||
viewConfig != null && !viewConfig.NativeProps != null,
|
||||
'Native component for "%s" does not exist',
|
||||
viewName,
|
||||
);
|
||||
|
||||
viewConfig.uiViewClassName = viewName;
|
||||
viewConfig.validAttributes = {};
|
||||
|
||||
// ReactNative `View.propTypes` have been deprecated in favor of
|
||||
// `ViewPropTypes`. In their place a temporary getter has been added with a
|
||||
// deprecated warning message. Avoid triggering that warning here by using
|
||||
// temporary workaround, __propTypesSecretDontUseThesePlease.
|
||||
// TODO (bvaughn) Revert this particular change any time after April 1
|
||||
if (componentInterface) {
|
||||
viewConfig.propTypes =
|
||||
typeof componentInterface.__propTypesSecretDontUseThesePlease ===
|
||||
'object'
|
||||
? componentInterface.__propTypesSecretDontUseThesePlease
|
||||
: componentInterface.propTypes;
|
||||
} else {
|
||||
viewConfig.propTypes = null;
|
||||
}
|
||||
|
||||
let baseModuleName = viewConfig.baseModuleName;
|
||||
let bubblingEventTypes = viewConfig.bubblingEventTypes;
|
||||
let directEventTypes = viewConfig.directEventTypes;
|
||||
let nativeProps = viewConfig.NativeProps;
|
||||
while (baseModuleName) {
|
||||
const baseModule = UIManager[baseModuleName];
|
||||
if (!baseModule) {
|
||||
warning(false, 'Base module "%s" does not exist', baseModuleName);
|
||||
baseModuleName = null;
|
||||
} else {
|
||||
bubblingEventTypes = {
|
||||
...baseModule.bubblingEventTypes,
|
||||
...bubblingEventTypes,
|
||||
};
|
||||
directEventTypes = {
|
||||
...baseModule.directEventTypes,
|
||||
...directEventTypes,
|
||||
};
|
||||
nativeProps = {
|
||||
...baseModule.NativeProps,
|
||||
...nativeProps,
|
||||
};
|
||||
baseModuleName = baseModule.baseModuleName;
|
||||
}
|
||||
}
|
||||
|
||||
viewConfig.bubblingEventTypes = bubblingEventTypes;
|
||||
viewConfig.directEventTypes = directEventTypes;
|
||||
|
||||
for (const key in nativeProps) {
|
||||
let useAttribute = false;
|
||||
const attribute = {};
|
||||
|
||||
const differ = TypeToDifferMap[nativeProps[key]];
|
||||
if (differ) {
|
||||
attribute.diff = differ;
|
||||
useAttribute = true;
|
||||
}
|
||||
|
||||
const processor = TypeToProcessorMap[nativeProps[key]];
|
||||
if (processor) {
|
||||
attribute.process = processor;
|
||||
useAttribute = true;
|
||||
}
|
||||
|
||||
viewConfig.validAttributes[key] = useAttribute ? attribute : true;
|
||||
}
|
||||
|
||||
// Unfortunately, the current set up puts the style properties on the top
|
||||
// level props object. We also need to add the nested form for API
|
||||
// compatibility. This allows these props on both the top level and the
|
||||
// nested style level. TODO: Move these to nested declarations on the
|
||||
// native side.
|
||||
viewConfig.validAttributes.style = ReactNativeStyleAttributes;
|
||||
|
||||
if (__DEV__) {
|
||||
componentInterface &&
|
||||
verifyPropTypes(
|
||||
componentInterface,
|
||||
viewConfig,
|
||||
extraConfig && extraConfig.nativeOnly,
|
||||
);
|
||||
}
|
||||
|
||||
if (!hasAttachedDefaultEventTypes) {
|
||||
attachDefaultEventTypes(viewConfig);
|
||||
hasAttachedDefaultEventTypes = true;
|
||||
}
|
||||
|
||||
// Register this view's event types with the ReactNative renderer.
|
||||
// This enables view managers to be initialized lazily, improving perf,
|
||||
// While also enabling 3rd party components to define custom event types.
|
||||
ReactNativeBridgeEventPlugin.processEventTypes(viewConfig);
|
||||
|
||||
return viewConfig;
|
||||
}
|
||||
|
||||
return createReactNativeComponentClass(viewName, getViewConfig);
|
||||
}
|
||||
|
||||
const TypeToDifferMap = {
|
||||
// iOS Types
|
||||
CATransform3D: matricesDiffer,
|
||||
CGPoint: pointsDiffer,
|
||||
CGSize: sizesDiffer,
|
||||
UIEdgeInsets: insetsDiffer,
|
||||
// Android Types
|
||||
// (not yet implemented)
|
||||
};
|
||||
|
||||
function processColorArray(colors: ?Array<any>): ?Array<?number> {
|
||||
return colors && colors.map(processColor);
|
||||
}
|
||||
|
||||
const TypeToProcessorMap = {
|
||||
// iOS Types
|
||||
CGColor: processColor,
|
||||
CGColorArray: processColorArray,
|
||||
UIColor: processColor,
|
||||
UIColorArray: processColorArray,
|
||||
CGImage: resolveAssetSource,
|
||||
UIImage: resolveAssetSource,
|
||||
RCTImageSource: resolveAssetSource,
|
||||
// Android Types
|
||||
Color: processColor,
|
||||
ColorArray: processColorArray,
|
||||
};
|
||||
|
||||
module.exports = requireNativeComponent;
|
|
@ -2760,7 +2760,8 @@ var ReactNativeGlobalResponderHandler = {
|
|||
/**
|
||||
* Register the event emitter with the native bridge
|
||||
*/
|
||||
RCTEventEmitter.register(ReactNativeEventEmitter);
|
||||
// TODO: This event emitter is interfering with the existing ReactNative renderer.
|
||||
// RCTEventEmitter.register(ReactNativeEventEmitter);
|
||||
|
||||
/**
|
||||
* Inject module for resolving DOM hierarchy and plugin ordering.
|
||||
|
|
|
@ -1140,7 +1140,8 @@ var ReactNativeEventEmitter = Object.freeze({
|
|||
}
|
||||
}
|
||||
});
|
||||
RCTEventEmitter.register(ReactNativeEventEmitter);
|
||||
// TODO: This event emitter is interfering with the existing ReactNative renderer.
|
||||
// RCTEventEmitter.register(ReactNativeEventEmitter);
|
||||
injection.injectEventPluginOrder([
|
||||
"ResponderEventPlugin",
|
||||
"ReactNativeBridgeEventPlugin"
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @providesModule ReactFabricInternals
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
|
||||
} = require('ReactFabric');
|
||||
|
||||
import type {NativeMethodsMixinType} from 'ReactNativeTypes';
|
||||
|
||||
const {
|
||||
NativeMethodsMixin,
|
||||
ReactNativeBridgeEventPlugin,
|
||||
createReactNativeComponentClass,
|
||||
} = __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
|
||||
|
||||
module.exports = {
|
||||
NativeMethodsMixin: ((NativeMethodsMixin: any): $Exact<
|
||||
NativeMethodsMixinType,
|
||||
>),
|
||||
ReactNativeBridgeEventPlugin,
|
||||
createReactNativeComponentClass,
|
||||
};
|
|
@ -60,6 +60,11 @@
|
|||
- (void)appendChildToSet:(NSMutableArray<RCTShadowView *> *)childSet
|
||||
childNode:(RCTShadowView *)childNode
|
||||
{
|
||||
if (!childNode) {
|
||||
// TODO: until this class is fully implemented, we may get nil from JS.
|
||||
return;
|
||||
}
|
||||
|
||||
[childSet addObject:childNode];
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue