diff --git a/.flowconfig b/.flowconfig index c6407f6b79e..bbbdb976925 100644 --- a/.flowconfig +++ b/.flowconfig @@ -98,7 +98,11 @@ untyped-import untyped-type-import [version] +<<<<<<< HEAD ^0.85.0 [untyped] .*/node_modules/metro/.* +======= +^0.86.0 +>>>>>>> parent of b864e7e63e... Revert "Merge branch 'master' into 0.58-stable" diff --git a/.flowconfig.android b/.flowconfig.android index 23082b1ffc4..48c6c713312 100644 --- a/.flowconfig.android +++ b/.flowconfig.android @@ -98,7 +98,11 @@ untyped-import untyped-type-import [version] +<<<<<<< HEAD ^0.85.0 [untyped] .*/node_modules/metro/.* +======= +^0.86.0 +>>>>>>> parent of b864e7e63e... Revert "Merge branch 'master' into 0.58-stable" diff --git a/Libraries/Animated/src/nodes/AnimatedInterpolation.js b/Libraries/Animated/src/nodes/AnimatedInterpolation.js index d314e078063..cc73ead399b 100644 --- a/Libraries/Animated/src/nodes/AnimatedInterpolation.js +++ b/Libraries/Animated/src/nodes/AnimatedInterpolation.js @@ -349,9 +349,6 @@ class AnimatedInterpolation extends AnimatedWithChildren { __transformDataType(range: Array) { // Change the string array type to number array // So we can reuse the same logic in iOS and Android platform - /* $FlowFixMe(>=0.70.0 site=react_native_fb) This comment suppresses an - * error found when Flow v0.70 was deployed. To see the error delete this - * comment and run Flow. */ return range.map(function(value) { if (typeof value !== 'string') { return value; diff --git a/Libraries/CameraRoll/RCTImagePickerManager.m b/Libraries/CameraRoll/RCTImagePickerManager.m index 96932c473f3..b8e570cfcd7 100644 --- a/Libraries/CameraRoll/RCTImagePickerManager.m +++ b/Libraries/CameraRoll/RCTImagePickerManager.m @@ -16,6 +16,16 @@ #import #import +@interface RCTImagePickerController : UIImagePickerController + +@property (nonatomic, assign) BOOL unmirrorFrontFacingCamera; + +@end + +@implementation RCTImagePickerController + +@end + @interface RCTImagePickerManager () @end @@ -31,6 +41,22 @@ RCT_EXPORT_MODULE(ImagePickerIOS); @synthesize bridge = _bridge; +- (id)init +{ + if (self = [super init]) { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(cameraChanged:) + name:@"AVCaptureDeviceDidStartRunningNotification" + object:nil]; + } + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self name:@"AVCaptureDeviceDidStartRunningNotification" object:nil]; +} + - (dispatch_queue_t)methodQueue { return dispatch_get_main_queue(); @@ -56,9 +82,10 @@ RCT_EXPORT_METHOD(openCameraDialog:(NSDictionary *)config return; } - UIImagePickerController *imagePicker = [UIImagePickerController new]; + RCTImagePickerController *imagePicker = [RCTImagePickerController new]; imagePicker.delegate = self; imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; + imagePicker.unmirrorFrontFacingCamera = [RCTConvert BOOL:config[@"unmirrorFrontFacingCamera"]]; if ([RCTConvert BOOL:config[@"videoMode"]]) { imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo; @@ -175,4 +202,17 @@ didFinishPickingMediaWithInfo:(NSDictionary *)info } } +- (void)cameraChanged:(NSNotification *)notification +{ + for (UIImagePickerController *picker in _pickers) { + if ([picker isKindOfClass:[RCTImagePickerController class]] + && ((RCTImagePickerController *)picker).unmirrorFrontFacingCamera + && picker.cameraDevice == UIImagePickerControllerCameraDeviceFront) { + picker.cameraViewTransform = CGAffineTransformScale(CGAffineTransformIdentity, -1, 1); + } else { + picker.cameraViewTransform = CGAffineTransformIdentity; + } + } +} + @end diff --git a/Libraries/Components/AppleTV/TVViewPropTypes.js b/Libraries/Components/AppleTV/TVViewPropTypes.js index 607034027f0..d7492967bc1 100644 --- a/Libraries/Components/AppleTV/TVViewPropTypes.js +++ b/Libraries/Components/AppleTV/TVViewPropTypes.js @@ -14,27 +14,42 @@ export type TVParallaxPropertiesType = $ReadOnly<{| /** * If true, parallax effects are enabled. Defaults to true. */ - enabled: boolean, + enabled?: boolean, /** * Defaults to 2.0. */ - shiftDistanceX: number, + shiftDistanceX?: number, /** * Defaults to 2.0. */ - shiftDistanceY: number, + shiftDistanceY?: number, /** * Defaults to 0.05. */ - tiltAngle: number, + tiltAngle?: number, /** * Defaults to 1.0 */ - magnification: number, + magnification?: number, + + /** + * Defaults to 1.0 + */ + pressMagnification?: number, + + /** + * Defaults to 0.3 + */ + pressDuration?: number, + + /** + * Defaults to 0.3 + */ + pressDelay?: number, |}>; /** diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index a9b00611591..e41c4e5cc4d 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -4,35 +4,150 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow * @format */ 'use strict'; -const DeprecatedColorPropType = require('DeprecatedColorPropType'); -const DeprecatedViewPropTypes = require('DeprecatedViewPropTypes'); -const NativeMethodsMixin = require('NativeMethodsMixin'); const Platform = require('Platform'); -const PropTypes = require('prop-types'); const React = require('React'); const ReactNative = require('ReactNative'); const StatusBar = require('StatusBar'); const StyleSheet = require('StyleSheet'); const UIManager = require('UIManager'); const View = require('View'); +const nullthrows = require('nullthrows'); const DrawerConsts = UIManager.getViewManagerConfig('AndroidDrawerLayout') .Constants; -const createReactClass = require('create-react-class'); const dismissKeyboard = require('dismissKeyboard'); const requireNativeComponent = require('requireNativeComponent'); -const RK_DRAWER_REF = 'drawerlayout'; -const INNERVIEW_REF = 'innerView'; - const DRAWER_STATES = ['Idle', 'Dragging', 'Settling']; +import type {ViewStyleProp} from 'StyleSheet'; +import type {ColorValue} from 'StyleSheetTypes'; +import type {SyntheticEvent} from 'CoreEventTypes'; +import type { + MeasureOnSuccessCallback, + MeasureInWindowOnSuccessCallback, + MeasureLayoutOnSuccessCallback, +} from 'ReactNativeTypes'; + +type DrawerStates = 'Idle' | 'Dragging' | 'Settling'; + +type DrawerStateEvent = SyntheticEvent< + $ReadOnly<{| + drawerState: number, + |}>, +>; + +type DrawerSlideEvent = SyntheticEvent< + $ReadOnly<{| + offset: number, + |}>, +>; + +type Props = $ReadOnly<{| + /** + * Determines whether the keyboard gets dismissed in response to a drag. + * - 'none' (the default), drags do not dismiss the keyboard. + * - 'on-drag', the keyboard is dismissed when a drag begins. + */ + keyboardDismissMode?: ?('none' | 'on-drag'), + + /** + * Specifies the background color of the drawer. The default value is white. + * If you want to set the opacity of the drawer, use rgba. Example: + * + * ``` + * return ( + * + * + * ); + * ``` + */ + drawerBackgroundColor: ColorValue, + + /** + * Specifies the side of the screen from which the drawer will slide in. + */ + drawerPosition: ?number, + + /** + * Specifies the width of the drawer, more precisely the width of the view that be pulled in + * from the edge of the window. + */ + drawerWidth?: ?number, + + /** + * Specifies the lock mode of the drawer. The drawer can be locked in 3 states: + * - unlocked (default), meaning that the drawer will respond (open/close) to touch gestures. + * - locked-closed, meaning that the drawer will stay closed and not respond to gestures. + * - locked-open, meaning that the drawer will stay opened and not respond to gestures. + * The drawer may still be opened and closed programmatically (`openDrawer`/`closeDrawer`). + */ + drawerLockMode?: ?('unlocked' | 'locked-closed' | 'locked-open'), + + /** + * Function called whenever there is an interaction with the navigation view. + */ + onDrawerSlide?: ?(event: DrawerSlideEvent) => mixed, + + /** + * Function called when the drawer state has changed. The drawer can be in 3 states: + * - Idle, meaning there is no interaction with the navigation view happening at the time + * - Dragging, meaning there is currently an interaction with the navigation view + * - Settling, meaning that there was an interaction with the navigation view, and the + * navigation view is now finishing its closing or opening animation + */ + onDrawerStateChanged?: ?(state: DrawerStates) => mixed, + + /** + * Function called whenever the navigation view has been opened. + */ + onDrawerOpen?: ?() => mixed, + + /** + * Function called whenever the navigation view has been closed. + */ + onDrawerClose?: ?() => mixed, + + /** + * The navigation view that will be rendered to the side of the screen and can be pulled in. + */ + renderNavigationView: () => React.Element, + + /** + * Make the drawer take the entire screen and draw the background of the + * status bar to allow it to open over the status bar. It will only have an + * effect on API 21+. + */ + statusBarBackgroundColor?: ?ColorValue, + + children?: React.Node, + style?: ?ViewStyleProp, +|}>; + +type NativeProps = $ReadOnly<{| + ...$Diff< + Props, + $ReadOnly<{onDrawerStateChanged?: ?(state: DrawerStates) => mixed}>, + >, + onDrawerStateChanged?: ?(state: DrawerStateEvent) => mixed, +|}>; + +type State = {| + statusBarBackgroundColor: ColorValue, +|}; + +// The View that contains both the actual drawer and the main view +const AndroidDrawerLayout = ((requireNativeComponent( + 'AndroidDrawerLayout', +): any): Class>); + /** * React component that wraps the platform `DrawerLayout` (Android only). The * Drawer (typically used for navigation) is rendered with `renderNavigationView` @@ -64,109 +179,20 @@ const DRAWER_STATES = ['Idle', 'Dragging', 'Settling']; * }, * ``` */ -const DrawerLayoutAndroid = createReactClass({ - displayName: 'DrawerLayoutAndroid', - statics: { - positions: DrawerConsts.DrawerPosition, - }, +class DrawerLayoutAndroid extends React.Component { + static positions = DrawerConsts.DrawerPosition; + static defaultProps = { + drawerBackgroundColor: 'white', + }; - propTypes: { - ...DeprecatedViewPropTypes, - /** - * Determines whether the keyboard gets dismissed in response to a drag. - * - 'none' (the default), drags do not dismiss the keyboard. - * - 'on-drag', the keyboard is dismissed when a drag begins. - */ - keyboardDismissMode: PropTypes.oneOf([ - 'none', // default - 'on-drag', - ]), - /** - * Specifies the background color of the drawer. The default value is white. - * If you want to set the opacity of the drawer, use rgba. Example: - * - * ``` - * return ( - * - * - * ); - * ``` - */ - drawerBackgroundColor: DeprecatedColorPropType, - /** - * Specifies the side of the screen from which the drawer will slide in. - */ - drawerPosition: PropTypes.oneOf([ - DrawerConsts.DrawerPosition.Left, - DrawerConsts.DrawerPosition.Right, - ]), - /** - * Specifies the width of the drawer, more precisely the width of the view that be pulled in - * from the edge of the window. - */ - drawerWidth: PropTypes.number, - /** - * Specifies the lock mode of the drawer. The drawer can be locked in 3 states: - * - unlocked (default), meaning that the drawer will respond (open/close) to touch gestures. - * - locked-closed, meaning that the drawer will stay closed and not respond to gestures. - * - locked-open, meaning that the drawer will stay opened and not respond to gestures. - * The drawer may still be opened and closed programmatically (`openDrawer`/`closeDrawer`). - */ - drawerLockMode: PropTypes.oneOf([ - 'unlocked', - 'locked-closed', - 'locked-open', - ]), - /** - * Function called whenever there is an interaction with the navigation view. - */ - onDrawerSlide: PropTypes.func, - /** - * Function called when the drawer state has changed. The drawer can be in 3 states: - * - idle, meaning there is no interaction with the navigation view happening at the time - * - dragging, meaning there is currently an interaction with the navigation view - * - settling, meaning that there was an interaction with the navigation view, and the - * navigation view is now finishing its closing or opening animation - */ - onDrawerStateChanged: PropTypes.func, - /** - * Function called whenever the navigation view has been opened. - */ - onDrawerOpen: PropTypes.func, - /** - * Function called whenever the navigation view has been closed. - */ - onDrawerClose: PropTypes.func, - /** - * The navigation view that will be rendered to the side of the screen and can be pulled in. - */ - renderNavigationView: PropTypes.func.isRequired, + _nativeRef = React.createRef< + Class>, + >(); - /** - * Make the drawer take the entire screen and draw the background of the - * status bar to allow it to open over the status bar. It will only have an - * effect on API 21+. - */ - statusBarBackgroundColor: DeprecatedColorPropType, - }, + state = {statusBarBackgroundColor: null}; - mixins: [NativeMethodsMixin], - - getDefaultProps: function(): {drawerBackgroundColor: string} { - return { - drawerBackgroundColor: 'white', - }; - }, - - getInitialState: function() { - return {statusBarBackgroundColor: undefined}; - }, - - getInnerViewNode: function() { - return this.refs[INNERVIEW_REF].getInnerViewNode(); - }, - - render: function() { + render() { + const {onDrawerStateChanged, ...props} = this.props; const drawStatusBar = Platform.Version >= 21 && this.props.statusBarBackgroundColor; const drawerViewWrapper = ( @@ -184,7 +210,7 @@ const DrawerLayoutAndroid = createReactClass({ ); const childrenWrapper = ( - + {drawStatusBar && ( ); - }, + } - _onDrawerSlide: function(event) { + _onDrawerSlide = (event: DrawerSlideEvent) => { if (this.props.onDrawerSlide) { this.props.onDrawerSlide(event); } if (this.props.keyboardDismissMode === 'on-drag') { dismissKeyboard(); } - }, + }; - _onDrawerOpen: function() { + _onDrawerOpen = () => { if (this.props.onDrawerOpen) { this.props.onDrawerOpen(); } - }, + }; - _onDrawerClose: function() { + _onDrawerClose = () => { if (this.props.onDrawerClose) { this.props.onDrawerClose(); } - }, + }; - _onDrawerStateChanged: function(event) { + _onDrawerStateChanged = (event: DrawerStateEvent) => { if (this.props.onDrawerStateChanged) { this.props.onDrawerStateChanged( DRAWER_STATES[event.nativeEvent.drawerState], ); } - }, + }; /** * Opens the drawer. */ - openDrawer: function() { + openDrawer() { UIManager.dispatchViewManagerCommand( this._getDrawerLayoutHandle(), UIManager.getViewManagerConfig('AndroidDrawerLayout').Commands.openDrawer, null, ); - }, + } /** * Closes the drawer. */ - closeDrawer: function() { + closeDrawer() { UIManager.dispatchViewManagerCommand( this._getDrawerLayoutHandle(), UIManager.getViewManagerConfig('AndroidDrawerLayout').Commands .closeDrawer, null, ); - }, + } + /** * Closing and opening example * Note: To access the drawer you have to give it a ref. Refs do not work on stateless components @@ -287,10 +314,45 @@ const DrawerLayoutAndroid = createReactClass({ * ) * } */ - _getDrawerLayoutHandle: function() { - return ReactNative.findNodeHandle(this.refs[RK_DRAWER_REF]); - }, -}); + _getDrawerLayoutHandle() { + return ReactNative.findNodeHandle(this._nativeRef.current); + } + + /** + * Native methods + */ + blur() { + nullthrows(this._nativeRef.current).blur(); + } + + focus() { + nullthrows(this._nativeRef.current).focus(); + } + + measure(callback: MeasureOnSuccessCallback) { + nullthrows(this._nativeRef.current).measure(callback); + } + + measureInWindow(callback: MeasureInWindowOnSuccessCallback) { + nullthrows(this._nativeRef.current).measureInWindow(callback); + } + + measureLayout( + relativeToNativeNode: number, + onSuccess: MeasureLayoutOnSuccessCallback, + onFail?: () => void, + ) { + nullthrows(this._nativeRef.current).measureLayout( + relativeToNativeNode, + onSuccess, + onFail, + ); + } + + setNativeProps(nativeProps: Object) { + nullthrows(this._nativeRef.current).setNativeProps(nativeProps); + } +} const styles = StyleSheet.create({ base: { @@ -322,7 +384,4 @@ const styles = StyleSheet.create({ }, }); -// The View that contains both the actual drawer and the main view -const AndroidDrawerLayout = requireNativeComponent('AndroidDrawerLayout'); - module.exports = DrawerLayoutAndroid; diff --git a/Libraries/Components/ScrollResponder.js b/Libraries/Components/ScrollResponder.js index 42079dec32a..46fe2a7f566 100644 --- a/Libraries/Components/ScrollResponder.js +++ b/Libraries/Components/ScrollResponder.js @@ -24,6 +24,8 @@ const warning = require('fbjs/lib/warning'); const {ScrollViewManager} = require('NativeModules'); +import type {PressEvent, ScrollEvent} from 'CoreEventTypes'; +import type {KeyboardEvent} from 'Keyboard'; import type EmitterSubscription from 'EmitterSubscription'; /** @@ -113,7 +115,6 @@ type State = { observedScrollSinceBecomingResponder: boolean, becameResponderWhileAnimating: boolean, }; -type Event = Object; const ScrollResponderMixin = { _subscriptionKeyboardWillShow: (null: ?EmitterSubscription), @@ -168,7 +169,9 @@ const ScrollResponderMixin = { * true. * */ - scrollResponderHandleStartShouldSetResponder: function(e: Event): boolean { + scrollResponderHandleStartShouldSetResponder: function( + e: PressEvent, + ): boolean { const currentlyFocusedTextInput = TextInputState.currentlyFocusedField(); if ( @@ -193,7 +196,7 @@ const ScrollResponderMixin = { * Invoke this from an `onStartShouldSetResponderCapture` event. */ scrollResponderHandleStartShouldSetResponderCapture: function( - e: Event, + e: PressEvent, ): boolean { // The scroll view should receive taps instead of its descendants if: // * it is already animating/decelerating @@ -212,6 +215,7 @@ const ScrollResponderMixin = { if ( keyboardNeverPersistTaps && currentlyFocusedTextInput != null && + e.target && !TextInputState.isTextInput(e.target) ) { return true; @@ -254,9 +258,9 @@ const ScrollResponderMixin = { /** * Invoke this from an `onTouchEnd` event. * - * @param {SyntheticEvent} e Event. + * @param {PressEvent} e Event. */ - scrollResponderHandleTouchEnd: function(e: Event) { + scrollResponderHandleTouchEnd: function(e: PressEvent) { const nativeEvent = e.nativeEvent; this.state.isTouching = nativeEvent.touches.length !== 0; this.props.onTouchEnd && this.props.onTouchEnd(e); @@ -265,9 +269,9 @@ const ScrollResponderMixin = { /** * Invoke this from an `onTouchCancel` event. * - * @param {SyntheticEvent} e Event. + * @param {PressEvent} e Event. */ - scrollResponderHandleTouchCancel: function(e: Event) { + scrollResponderHandleTouchCancel: function(e: PressEvent) { this.state.isTouching = false; this.props.onTouchCancel && this.props.onTouchCancel(e); }, @@ -275,7 +279,7 @@ const ScrollResponderMixin = { /** * Invoke this from an `onResponderRelease` event. */ - scrollResponderHandleResponderRelease: function(e: Event) { + scrollResponderHandleResponderRelease: function(e: PressEvent) { this.props.onResponderRelease && this.props.onResponderRelease(e); // By default scroll views will unfocus a textField @@ -295,7 +299,7 @@ const ScrollResponderMixin = { } }, - scrollResponderHandleScroll: function(e: Event) { + scrollResponderHandleScroll: function(e: ScrollEvent) { this.state.observedScrollSinceBecomingResponder = true; this.props.onScroll && this.props.onScroll(e); }, @@ -303,7 +307,7 @@ const ScrollResponderMixin = { /** * Invoke this from an `onResponderGrant` event. */ - scrollResponderHandleResponderGrant: function(e: Event) { + scrollResponderHandleResponderGrant: function(e: ScrollEvent) { this.state.observedScrollSinceBecomingResponder = false; this.props.onResponderGrant && this.props.onResponderGrant(e); this.state.becameResponderWhileAnimating = this.scrollResponderIsAnimating(); @@ -316,7 +320,7 @@ const ScrollResponderMixin = { * * Invoke this from an `onScrollBeginDrag` event. */ - scrollResponderHandleScrollBeginDrag: function(e: Event) { + scrollResponderHandleScrollBeginDrag: function(e: ScrollEvent) { FrameRateLogger.beginScroll(); // TODO: track all scrolls after implementing onScrollEndAnimation this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e); }, @@ -324,7 +328,7 @@ const ScrollResponderMixin = { /** * Invoke this from an `onScrollEndDrag` event. */ - scrollResponderHandleScrollEndDrag: function(e: Event) { + scrollResponderHandleScrollEndDrag: function(e: ScrollEvent) { const {velocity} = e.nativeEvent; // - If we are animating, then this is a "drag" that is stopping the scrollview and momentum end // will fire. @@ -343,7 +347,7 @@ const ScrollResponderMixin = { /** * Invoke this from an `onMomentumScrollBegin` event. */ - scrollResponderHandleMomentumScrollBegin: function(e: Event) { + scrollResponderHandleMomentumScrollBegin: function(e: ScrollEvent) { this.state.lastMomentumScrollBeginTime = performanceNow(); this.props.onMomentumScrollBegin && this.props.onMomentumScrollBegin(e); }, @@ -351,7 +355,7 @@ const ScrollResponderMixin = { /** * Invoke this from an `onMomentumScrollEnd` event. */ - scrollResponderHandleMomentumScrollEnd: function(e: Event) { + scrollResponderHandleMomentumScrollEnd: function(e: ScrollEvent) { FrameRateLogger.endScroll(); this.state.lastMomentumScrollEndTime = performanceNow(); this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd(e); @@ -366,9 +370,9 @@ const ScrollResponderMixin = { * responder). The `onResponderReject` won't fire in that case - it only * fires when a *current* responder rejects our request. * - * @param {SyntheticEvent} e Touch Start event. + * @param {PressEvent} e Touch Start event. */ - scrollResponderHandleTouchStart: function(e: Event) { + scrollResponderHandleTouchStart: function(e: PressEvent) { this.state.isTouching = true; this.props.onTouchStart && this.props.onTouchStart(e); }, @@ -382,9 +386,9 @@ const ScrollResponderMixin = { * responder). The `onResponderReject` won't fire in that case - it only * fires when a *current* responder rejects our request. * - * @param {SyntheticEvent} e Touch Start event. + * @param {PressEvent} e Touch Start event. */ - scrollResponderHandleTouchMove: function(e: Event) { + scrollResponderHandleTouchMove: function(e: PressEvent) { this.props.onTouchMove && this.props.onTouchMove(e); }, @@ -409,7 +413,7 @@ const ScrollResponderMixin = { * Components can pass what node to use by defining a `getScrollableNode` * function otherwise `this` is used. */ - scrollResponderGetScrollableNode: function(): any { + scrollResponderGetScrollableNode: function(): ?number { return this.getScrollableNode ? this.getScrollableNode() : ReactNative.findNodeHandle(this); @@ -527,14 +531,14 @@ const ScrollResponderMixin = { * This method should be used as the callback to onFocus in a TextInputs' * parent view. Note that any module using this mixin needs to return * the parent view's ref in getScrollViewRef() in order to use this method. - * @param {any} nodeHandle The TextInput node handle + * @param {number} nodeHandle The TextInput node handle * @param {number} additionalOffset The scroll view's bottom "contentInset". * Default is 0. * @param {bool} preventNegativeScrolling Whether to allow pulling the content * down to make it meet the keyboard's top. Default is false. */ scrollResponderScrollNativeHandleToKeyboard: function( - nodeHandle: any, + nodeHandle: number, additionalOffset?: number, preventNegativeScrollOffset?: boolean, ) { @@ -584,8 +588,8 @@ const ScrollResponderMixin = { this.preventNegativeScrollOffset = false; }, - scrollResponderTextInputFocusError: function(e: Event) { - console.error('Error measuring text field: ', e); + scrollResponderTextInputFocusError: function(msg: string) { + console.error('Error measuring text field: ', msg); }, /** @@ -667,17 +671,17 @@ const ScrollResponderMixin = { * relevant to you. (For example, only if you receive these callbacks after * you had explicitly focused a node etc). */ - scrollResponderKeyboardWillShow: function(e: Event) { + scrollResponderKeyboardWillShow: function(e: KeyboardEvent) { this.keyboardWillOpenTo = e; this.props.onKeyboardWillShow && this.props.onKeyboardWillShow(e); }, - scrollResponderKeyboardWillHide: function(e: Event) { + scrollResponderKeyboardWillHide: function(e: KeyboardEvent) { this.keyboardWillOpenTo = null; this.props.onKeyboardWillHide && this.props.onKeyboardWillHide(e); }, - scrollResponderKeyboardDidShow: function(e: Event) { + scrollResponderKeyboardDidShow: function(e: KeyboardEvent) { // TODO(7693961): The event for DidShow is not available on iOS yet. // Use the one from WillShow and do not assign. if (e) { @@ -686,7 +690,7 @@ const ScrollResponderMixin = { this.props.onKeyboardDidShow && this.props.onKeyboardDidShow(e); }, - scrollResponderKeyboardDidHide: function(e: Event) { + scrollResponderKeyboardDidHide: function(e: KeyboardEvent) { this.keyboardWillOpenTo = null; this.props.onKeyboardDidHide && this.props.onKeyboardDidHide(e); }, diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index fd0986f0f15..f1c2225261a 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -396,8 +396,8 @@ export type Props = $ReadOnly<{| * - `false`, deprecated, use 'never' instead * - `true`, deprecated, use 'always' instead */ - /* $FlowFixMe(>=0.85.0 site=react_native_fb) This comment suppresses an error - * found when Flow v0.85 was deployed. To see the error, delete this comment + /* $FlowFixMe(>=0.86.0 site=react_native_fb) This comment suppresses an error + * found when Flow v0.86 was deployed. To see the error, delete this comment * and run Flow. */ keyboardShouldPersistTaps?: ?('always' | 'never' | 'handled' | false | true), /** diff --git a/Libraries/Components/StatusBar/StatusBar.js b/Libraries/Components/StatusBar/StatusBar.js index 52e6a764d2c..f6dd6884a5f 100644 --- a/Libraries/Components/StatusBar/StatusBar.js +++ b/Libraries/Components/StatusBar/StatusBar.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; @@ -103,13 +103,56 @@ type Props = $ReadOnly<{| barStyle?: ?('default' | 'light-content' | 'dark-content'), |}>; +type StackEntryProps = {| + /** + * The background color of the status bar. + * + * @platform android + */ + backgroundColor: {| + value: ?string, + animated: ?boolean, + |}, + /** + * Sets the color of the status bar text. + */ + barStyle: {| + value: ?string, + animated: ?boolean, + |}, + /** + * If the status bar is translucent. + * When translucent is set to true, the app will draw under the status bar. + * This is useful when using a semi transparent status bar color. + */ + translucent: ?boolean, + /** + * + */ + hidden: {| + value: ?boolean, + animated: boolean, + transition: ?('slide' | 'fade'), + |}, + /** + * If the network activity indicator should be visible. + * + * @platform ios + */ + networkActivityIndicatorVisible: ?boolean, +|}; + /** * Merges the prop stack with the default values. */ function mergePropsStack( - propsStack: Array, - defaultValues: Object, -): Object { + propsStack: $ReadOnlyArray, + defaultValues: StackEntryProps, +): StackEntryProps { + const init: StackEntryProps = { + ...defaultValues, + }; + return propsStack.reduce((prev, cur) => { for (const prop in cur) { if (cur[prop] != null) { @@ -117,39 +160,31 @@ function mergePropsStack( } } return prev; - }, Object.assign({}, defaultValues)); + }, init); } /** * Returns an object to insert in the props stack from the props * and the transition/animation info. */ -function createStackEntry(props: any): any { +function createStackEntry(props: Props): StackEntryProps { return { - backgroundColor: - props.backgroundColor != null - ? { - value: props.backgroundColor, - animated: props.animated, - } - : null, - barStyle: - props.barStyle != null - ? { - value: props.barStyle, - animated: props.animated, - } - : null, - translucent: props.translucent, - hidden: - props.hidden != null - ? { - value: props.hidden, - animated: props.animated, - transition: props.showHideTransition, - } - : null, - networkActivityIndicatorVisible: props.networkActivityIndicatorVisible, + backgroundColor: { + value: props.backgroundColor, + animated: props.animated, + }, + barStyle: { + value: props.barStyle, + animated: props.animated, + }, + translucent: props.translucent || false, + hidden: { + value: props.hidden, + animated: props.animated || false, + transition: props.showHideTransition, + }, + networkActivityIndicatorVisible: + props.networkActivityIndicatorVisible || false, }; } @@ -193,9 +228,9 @@ function createStackEntry(props: any): any { * `currentHeight` (Android only) The height of the status bar. */ class StatusBar extends React.Component { - static _propsStack = []; + static _propsStack: Array = []; - static _defaultProps = createStackEntry({ + static _defaultProps: StackEntryProps = createStackEntry({ animated: false, showHideTransition: 'fade', backgroundColor: 'black', @@ -230,10 +265,9 @@ class StatusBar extends React.Component { * changing the status bar hidden property. */ static setHidden(hidden: boolean, animation?: StatusBarAnimation) { - animation = animation || 'none'; StatusBar._defaultProps.hidden.value = hidden; if (Platform.OS === 'ios') { - StatusBarManager.setHidden(hidden, animation); + StatusBarManager.setHidden(hidden, animation || 'none'); } else if (Platform.OS === 'android') { StatusBarManager.setHidden(hidden); } @@ -245,10 +279,9 @@ class StatusBar extends React.Component { * @param animated Animate the style change. */ static setBarStyle(style: StatusBarStyle, animated?: boolean) { - animated = animated || false; StatusBar._defaultProps.barStyle.value = style; if (Platform.OS === 'ios') { - StatusBarManager.setStyle(style, animated); + StatusBarManager.setStyle(style, animated || false); } else if (Platform.OS === 'android') { StatusBarManager.setStyle(style); } @@ -279,9 +312,8 @@ class StatusBar extends React.Component { console.warn('`setBackgroundColor` is only available on Android'); return; } - animated = animated || false; StatusBar._defaultProps.backgroundColor.value = color; - StatusBarManager.setColor(processColor(color), animated); + StatusBarManager.setColor(processColor(color), animated || false); } /** diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index f5551cb0f7c..038fff419d1 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -34,6 +34,8 @@ const warning = require('fbjs/lib/warning'); import type {TextStyleProp, ViewStyleProp} from 'StyleSheet'; import type {ColorValue} from 'StyleSheetTypes'; import type {ViewProps} from 'ViewPropTypes'; +import type {SyntheticEvent, ScrollEvent} from 'CoreEventTypes'; +import type {PressEvent} from 'CoreEventTypes'; let AndroidTextInput; let RCTMultilineTextInputView; @@ -55,11 +57,73 @@ const onlyMultiline = { children: true, }; -type Event = Object; -type Selection = { +export type ChangeEvent = SyntheticEvent< + $ReadOnly<{| + eventCount: number, + target: number, + text: string, + |}>, +>; + +export type TextInputEvent = SyntheticEvent< + $ReadOnly<{| + eventCount: number, + previousText: string, + range: $ReadOnly<{| + start: number, + end: number, + |}>, + target: number, + text: string, + |}>, +>; + +export type ContentSizeChangeEvent = SyntheticEvent< + $ReadOnly<{| + target: number, + contentSize: $ReadOnly<{| + width: number, + height: number, + |}>, + |}>, +>; + +type TargetEvent = SyntheticEvent< + $ReadOnly<{| + target: number, + |}>, +>; + +export type BlurEvent = TargetEvent; +export type FocusEvent = TargetEvent; + +type Selection = $ReadOnly<{| start: number, - end?: number, -}; + end: number, +|}>; + +export type SelectionChangeEvent = SyntheticEvent< + $ReadOnly<{| + selection: Selection, + target: number, + |}>, +>; + +export type KeyPressEvent = SyntheticEvent< + $ReadOnly<{| + key: string, + target?: ?number, + eventCount?: ?number, + |}>, +>; + +export type EditingEvent = SyntheticEvent< + $ReadOnly<{| + eventCount: number, + text: string, + target: number, + |}>, +>; const DataDetectorTypes = [ 'phoneNumber', @@ -184,17 +248,17 @@ type Props = $ReadOnly<{| returnKeyType?: ?ReturnKeyType, maxLength?: ?number, multiline?: ?boolean, - onBlur?: ?Function, - onFocus?: ?Function, - onChange?: ?Function, - onChangeText?: ?Function, - onContentSizeChange?: ?Function, - onTextInput?: ?Function, - onEndEditing?: ?Function, - onSelectionChange?: ?Function, - onSubmitEditing?: ?Function, - onKeyPress?: ?Function, - onScroll?: ?Function, + onBlur?: ?(e: BlurEvent) => void, + onFocus?: ?(e: FocusEvent) => void, + onChange?: ?(e: ChangeEvent) => void, + onChangeText?: ?(text: string) => void, + onContentSizeChange?: ?(e: ContentSizeChangeEvent) => void, + onTextInput?: ?(e: TextInputEvent) => void, + onEndEditing?: ?(e: EditingEvent) => void, + onSelectionChange?: ?(e: SelectionChangeEvent) => void, + onSubmitEditing?: ?(e: EditingEvent) => void, + onKeyPress?: ?(e: KeyPressEvent) => void, + onScroll?: ?(e: ScrollEvent) => void, placeholder?: ?Stringish, placeholderTextColor?: ?ColorValue, secureTextEntry?: ?boolean, @@ -792,7 +856,7 @@ const TextInput = createReactClass({ 'oneTimeCode', ]), }, - getDefaultProps(): Object { + getDefaultProps() { return { allowFontScaling: true, underlineColorAndroid: 'transparent', @@ -1108,7 +1172,7 @@ const TextInput = createReactClass({ ); }, - _onFocus: function(event: Event) { + _onFocus: function(event: FocusEvent) { if (this.props.onFocus) { this.props.onFocus(event); } @@ -1118,16 +1182,16 @@ const TextInput = createReactClass({ } }, - _onPress: function(event: Event) { + _onPress: function(event: PressEvent) { if (this.props.editable || this.props.editable === undefined) { this.focus(); } }, - _onChange: function(event: Event) { + _onChange: function(event: ChangeEvent) { // Make sure to fire the mostRecentEventCount first so it is already set on // native when the text value is set. - if (this._inputRef) { + if (this._inputRef && this._inputRef.setNativeProps) { this._inputRef.setNativeProps({ mostRecentEventCount: event.nativeEvent.eventCount, }); @@ -1147,7 +1211,7 @@ const TextInput = createReactClass({ this.forceUpdate(); }, - _onSelectionChange: function(event: Event) { + _onSelectionChange: function(event: SelectionChangeEvent) { this.props.onSelectionChange && this.props.onSelectionChange(event); if (!this._inputRef) { @@ -1188,7 +1252,11 @@ const TextInput = createReactClass({ nativeProps.selection = this.props.selection; } - if (Object.keys(nativeProps).length > 0 && this._inputRef) { + if ( + Object.keys(nativeProps).length > 0 && + this._inputRef && + this._inputRef.setNativeProps + ) { this._inputRef.setNativeProps(nativeProps); } @@ -1211,11 +1279,11 @@ const TextInput = createReactClass({ } }, - _onTextInput: function(event: Event) { + _onTextInput: function(event: TextInputEvent) { this.props.onTextInput && this.props.onTextInput(event); }, - _onScroll: function(event: Event) { + _onScroll: function(event: ScrollEvent) { this.props.onScroll && this.props.onScroll(event); }, }); diff --git a/Libraries/Components/TextInput/__tests__/TextInput-test.js b/Libraries/Components/TextInput/__tests__/TextInput-test.js new file mode 100644 index 00000000000..78d6884db03 --- /dev/null +++ b/Libraries/Components/TextInput/__tests__/TextInput-test.js @@ -0,0 +1,70 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails oncall+react_native + * @format + * @flow-strict + */ + +'use strict'; + +const React = require('React'); +const ReactTestRenderer = require('react-test-renderer'); +const TextInput = require('TextInput'); + +import Component from '@reactions/component'; + +const {enter} = require('ReactNativeTestTools'); + +jest.unmock('TextInput'); + +describe('TextInput tests', () => { + let input; + let onChangeListener; + let onChangeTextListener; + const initialValue = 'initialValue'; + beforeEach(() => { + onChangeListener = jest.fn(); + onChangeTextListener = jest.fn(); + const renderTree = ReactTestRenderer.create( + + {({setState, state}) => ( + { + onChangeTextListener(text); + setState({text}); + }} + onChange={event => { + onChangeListener(event); + }} + /> + )} + , + ); + input = renderTree.root.findByType(TextInput); + }); + it('has expected instance functions', () => { + expect(input.instance.isFocused).toBeInstanceOf(Function); // Would have prevented S168585 + expect(input.instance.clear).toBeInstanceOf(Function); + expect(input.instance.focus).toBeInstanceOf(Function); + expect(input.instance.blur).toBeInstanceOf(Function); + expect(input.instance.setNativeProps).toBeInstanceOf(Function); + expect(input.instance.measure).toBeInstanceOf(Function); + expect(input.instance.measureInWindow).toBeInstanceOf(Function); + expect(input.instance.measureLayout).toBeInstanceOf(Function); + }); + it('calls onChange callbacks', () => { + expect(input.props.value).toBe(initialValue); + const message = 'This is a test message'; + enter(input, message); + expect(input.props.value).toBe(message); + expect(onChangeTextListener).toHaveBeenCalledWith(message); + expect(onChangeListener).toHaveBeenCalledWith({ + nativeEvent: {text: message}, + }); + }); +}); diff --git a/Libraries/Components/TimePickerAndroid/TimePickerAndroid.android.js b/Libraries/Components/TimePickerAndroid/TimePickerAndroid.android.js index bdb29421f89..87c44621dc0 100644 --- a/Libraries/Components/TimePickerAndroid/TimePickerAndroid.android.js +++ b/Libraries/Components/TimePickerAndroid/TimePickerAndroid.android.js @@ -5,13 +5,18 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; const TimePickerModule = require('NativeModules').TimePickerAndroid; +import type { + TimePickerOptions, + TimePickerResult, +} from './TimePickerAndroidTypes'; + /** * Opens the standard Android time picker dialog. * @@ -52,22 +57,18 @@ class TimePickerAndroid { * still be resolved with action being `TimePickerAndroid.dismissedAction` and all the other keys * being undefined. **Always** check whether the `action` before reading the values. */ - static async open(options: Object): Promise { + static async open(options: TimePickerOptions): Promise { return TimePickerModule.open(options); } /** * A time has been selected. */ - static get timeSetAction() { - return 'timeSetAction'; - } + static +timeSetAction: 'timeSetAction' = 'timeSetAction'; /** * The dialog has been dismissed. */ - static get dismissedAction() { - return 'dismissedAction'; - } + static +dismissedAction: 'dismissedAction' = 'dismissedAction'; } module.exports = TimePickerAndroid; diff --git a/Libraries/Components/TimePickerAndroid/TimePickerAndroidTypes.js b/Libraries/Components/TimePickerAndroid/TimePickerAndroidTypes.js new file mode 100644 index 00000000000..aafa572be6c --- /dev/null +++ b/Libraries/Components/TimePickerAndroid/TimePickerAndroidTypes.js @@ -0,0 +1,24 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow strict-local + */ + +'use strict'; + +export type TimePickerOptions = {| + hour?: number, + minute?: number, + is24Hour?: boolean, + mode?: 'clock' | 'spinner' | 'default', +|}; + +export type TimePickerResult = $ReadOnly<{| + action: string, + hour: number, + minute: number, +|}>; diff --git a/Libraries/Components/Touchable/Touchable.js b/Libraries/Components/Touchable/Touchable.js index e6b8fb19cc0..5383de2da4e 100644 --- a/Libraries/Components/Touchable/Touchable.js +++ b/Libraries/Components/Touchable/Touchable.js @@ -4,6 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow * @format */ @@ -23,6 +24,9 @@ const View = require('View'); const keyMirror = require('fbjs/lib/keyMirror'); const normalizeColor = require('normalizeColor'); +import type {PressEvent} from 'CoreEventTypes'; +import type {EdgeInsetsProp} from 'EdgeInsetsPropType'; + /** * `Touchable`: Taps done right. * @@ -111,6 +115,7 @@ const normalizeColor = require('normalizeColor'); /** * Touchable states. */ + const States = keyMirror({ NOT_RESPONDER: null, // Not the responder RESPONDER_INACTIVE_PRESS_IN: null, // Responder, inactive, in the `PressRect` @@ -122,10 +127,33 @@ const States = keyMirror({ ERROR: null, }); -/** +type State = + | typeof States.NOT_RESPONDER + | typeof States.RESPONDER_INACTIVE_PRESS_IN + | typeof States.RESPONDER_INACTIVE_PRESS_OUT + | typeof States.RESPONDER_ACTIVE_PRESS_IN + | typeof States.RESPONDER_ACTIVE_PRESS_OUT + | typeof States.RESPONDER_ACTIVE_LONG_PRESS_IN + | typeof States.RESPONDER_ACTIVE_LONG_PRESS_OUT + | typeof States.ERROR; + +/* * Quick lookup map for states that are considered to be "active" */ + +const baseStatesConditions = { + NOT_RESPONDER: false, + RESPONDER_INACTIVE_PRESS_IN: false, + RESPONDER_INACTIVE_PRESS_OUT: false, + RESPONDER_ACTIVE_PRESS_IN: false, + RESPONDER_ACTIVE_PRESS_OUT: false, + RESPONDER_ACTIVE_LONG_PRESS_IN: false, + RESPONDER_ACTIVE_LONG_PRESS_OUT: false, + ERROR: false, +}; + const IsActive = { + ...baseStatesConditions, RESPONDER_ACTIVE_PRESS_OUT: true, RESPONDER_ACTIVE_PRESS_IN: true, }; @@ -135,12 +163,14 @@ const IsActive = { * therefore eligible to result in a "selection" if the press stops. */ const IsPressingIn = { + ...baseStatesConditions, RESPONDER_INACTIVE_PRESS_IN: true, RESPONDER_ACTIVE_PRESS_IN: true, RESPONDER_ACTIVE_LONG_PRESS_IN: true, }; const IsLongPressingIn = { + ...baseStatesConditions, RESPONDER_ACTIVE_LONG_PRESS_IN: true, }; @@ -157,6 +187,15 @@ const Signals = keyMirror({ LONG_PRESS_DETECTED: null, }); +type Signal = + | typeof Signals.DELAY + | typeof Signals.RESPONDER_GRANT + | typeof Signals.RESPONDER_RELEASE + | typeof Signals.RESPONDER_TERMINATED + | typeof Signals.ENTER_PRESS_RECT + | typeof Signals.LEAVE_PRESS_RECT + | typeof Signals.LONG_PRESS_DETECTED; + /** * Mapping from States x Signals => States */ @@ -391,7 +430,7 @@ const TouchableMixin = { * @param {SyntheticEvent} e Synthetic event from event system. * */ - touchableHandleResponderGrant: function(e) { + touchableHandleResponderGrant: function(e: PressEvent) { const dispatchID = e.currentTarget; // Since e is used in a callback invoked on another event loop // (as in setTimeout etc), we need to call e.persist() on the @@ -432,21 +471,21 @@ const TouchableMixin = { /** * Place as callback for a DOM element's `onResponderRelease` event. */ - touchableHandleResponderRelease: function(e) { + touchableHandleResponderRelease: function(e: PressEvent) { this._receiveSignal(Signals.RESPONDER_RELEASE, e); }, /** * Place as callback for a DOM element's `onResponderTerminate` event. */ - touchableHandleResponderTerminate: function(e) { + touchableHandleResponderTerminate: function(e: PressEvent) { this._receiveSignal(Signals.RESPONDER_TERMINATED, e); }, /** * Place as callback for a DOM element's `onResponderMove` event. */ - touchableHandleResponderMove: function(e) { + touchableHandleResponderMove: function(e: PressEvent) { // Not enough time elapsed yet, wait for highlight - // this is just a perf optimization. if ( @@ -633,7 +672,14 @@ const TouchableMixin = { UIManager.measure(tag, this._handleQueryLayout); }, - _handleQueryLayout: function(l, t, w, h, globalX, globalY) { + _handleQueryLayout: function( + l: number, + t: number, + w: number, + h: number, + globalX: number, + globalY: number, + ) { //don't do anything UIManager failed to measure node if (!l && !t && !w && !h && !globalX && !globalY) { return; @@ -652,12 +698,12 @@ const TouchableMixin = { ); }, - _handleDelay: function(e) { + _handleDelay: function(e: PressEvent) { this.touchableDelayTimeout = null; this._receiveSignal(Signals.DELAY, e); }, - _handleLongDelay: function(e) { + _handleLongDelay: function(e: PressEvent) { this.longPressDelayTimeout = null; const curState = this.state.touchable.touchState; if ( @@ -685,7 +731,7 @@ const TouchableMixin = { * @throws Error if invalid state transition or unrecognized signal. * @sideeffects */ - _receiveSignal: function(signal, e) { + _receiveSignal: function(signal: Signal, e: PressEvent) { const responderID = this.state.touchable.responderID; const curState = this.state.touchable.touchState; const nextState = Transitions[curState] && Transitions[curState][signal]; @@ -725,14 +771,14 @@ const TouchableMixin = { this.longPressDelayTimeout = null; }, - _isHighlight: function(state) { + _isHighlight: function(state: State) { return ( state === States.RESPONDER_ACTIVE_PRESS_IN || state === States.RESPONDER_ACTIVE_LONG_PRESS_IN ); }, - _savePressInLocation: function(e) { + _savePressInLocation: function(e: PressEvent) { const touch = TouchEventUtils.extractSingleTouch(e.nativeEvent); const pageX = touch && touch.pageX; const pageY = touch && touch.pageY; @@ -741,7 +787,12 @@ const TouchableMixin = { this.pressInLocation = {pageX, pageY, locationX, locationY}; }, - _getDistanceBetweenPoints: function(aX, aY, bX, bY) { + _getDistanceBetweenPoints: function( + aX: number, + aY: number, + bX: number, + bY: number, + ) { const deltaX = aX - bX; const deltaY = aY - bY; return Math.sqrt(deltaX * deltaX + deltaY * deltaY); @@ -758,7 +809,12 @@ const TouchableMixin = { * @param {Event} e Native event. * @sideeffects */ - _performSideEffectsForTransition: function(curState, nextState, signal, e) { + _performSideEffectsForTransition: function( + curState: State, + nextState: State, + signal: Signal, + e: PressEvent, + ) { const curIsHighlight = this._isHighlight(curState); const newIsHighlight = this._isHighlight(nextState); @@ -813,12 +869,12 @@ const TouchableMixin = { UIManager.playTouchSound(); }, - _startHighlight: function(e) { + _startHighlight: function(e: PressEvent) { this._savePressInLocation(e); this.touchableHandleActivePressIn && this.touchableHandleActivePressIn(e); }, - _endHighlight: function(e) { + _endHighlight: function(e: PressEvent) { if (this.touchableHandleActivePressOut) { if ( this.touchableGetPressOutDelayMS && @@ -840,7 +896,13 @@ const Touchable = { /** * Renders a debugging overlay to visualize touch target with hitSlop (might not work on Android). */ - renderDebugView: ({color, hitSlop}) => { + renderDebugView: ({ + color, + hitSlop, + }: { + color: string | number, + hitSlop: EdgeInsetsProp, + }) => { if (!Touchable.TOUCH_TARGET_DEBUG) { return null; } @@ -854,8 +916,12 @@ const Touchable = { for (const key in hitSlop) { debugHitSlopStyle[key] = -hitSlop[key]; } + const normalizedColor = normalizeColor(color); + if (typeof normalizedColor !== 'number') { + return null; + } const hexColor = - '#' + ('00000000' + normalizeColor(color).toString(16)).substr(-8); + '#' + ('00000000' + normalizedColor.toString(16)).substr(-8); return ( void) => void, + onPressAnimationComplete?: ?() => void, pressRetentionOffset?: ?EdgeInsetsProp, releaseVelocity?: ?number, releaseBounciness?: ?number, @@ -95,7 +94,7 @@ const TouchableBounce = ((createReactClass({ value: number, velocity: number, bounciness: number, - callback?: ?Function, + callback?: ?() => void, ) { Animated.spring(this.state.scale, { toValue: value, @@ -105,21 +104,28 @@ const TouchableBounce = ((createReactClass({ }).start(callback); }, + /** + * Triggers a bounce animation without invoking any callbacks. + */ + bounce: function() { + this.bounceTo(0.93, 0.1, 0, () => this.bounceTo(1, 0.4, 0)); + }, + /** * `Touchable.Mixin` self callbacks. The mixin will invoke these if they are * defined on your component. */ - touchableHandleActivePressIn: function(e: Event) { + touchableHandleActivePressIn: function(e: PressEvent) { this.bounceTo(0.93, 0.1, 0); this.props.onPressIn && this.props.onPressIn(e); }, - touchableHandleActivePressOut: function(e: Event) { + touchableHandleActivePressOut: function(e: PressEvent) { this.bounceTo(1, 0.4, 0); this.props.onPressOut && this.props.onPressOut(e); }, - touchableHandlePress: function(e: Event) { + touchableHandlePress: function(e: PressEvent) { const onPressWithCompletion = this.props.onPressWithCompletion; if (onPressWithCompletion) { onPressWithCompletion(() => { @@ -147,7 +153,7 @@ const TouchableBounce = ((createReactClass({ return this.props.pressRetentionOffset || PRESS_RETENTION_OFFSET; }, - touchableGetHitSlop: function(): ?Object { + touchableGetHitSlop: function(): ?EdgeInsetsProp { return this.props.hitSlop; }, diff --git a/Libraries/Components/Touchable/TouchableHighlight.js b/Libraries/Components/Touchable/TouchableHighlight.js index f4e81f37485..03e7cd8b8af 100644 --- a/Libraries/Components/Touchable/TouchableHighlight.js +++ b/Libraries/Components/Touchable/TouchableHighlight.js @@ -28,6 +28,7 @@ import type {PressEvent} from 'CoreEventTypes'; import type {ViewStyleProp} from 'StyleSheet'; import type {ColorValue} from 'StyleSheetTypes'; import type {Props as TouchableWithoutFeedbackProps} from 'TouchableWithoutFeedback'; +import type {TVParallaxPropertiesType} from 'TVViewPropTypes'; const DEFAULT_PROPS = { activeOpacity: 0.85, @@ -39,7 +40,7 @@ const PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; type IOSProps = $ReadOnly<{| hasTVPreferredFocus?: ?boolean, - tvParallaxProperties?: ?Object, + tvParallaxProperties?: ?TVParallaxPropertiesType, |}>; type Props = $ReadOnly<{| @@ -49,8 +50,8 @@ type Props = $ReadOnly<{| activeOpacity?: ?number, underlayColor?: ?ColorValue, style?: ?ViewStyleProp, - onShowUnderlay?: ?Function, - onHideUnderlay?: ?Function, + onShowUnderlay?: ?() => void, + onHideUnderlay?: ?() => void, testOnly_pressed?: ?boolean, |}>; @@ -185,18 +186,7 @@ const TouchableHighlight = ((createReactClass({ */ hasTVPreferredFocus: PropTypes.bool, /** - * *(Apple TV only)* Object with properties to control Apple TV parallax effects. - * - * enabled: If true, parallax effects are enabled. Defaults to true. - * shiftDistanceX: Defaults to 2.0. - * shiftDistanceY: Defaults to 2.0. - * tiltAngle: Defaults to 0.05. - * magnification: Defaults to 1.0. - * pressMagnification: Defaults to 1.0. - * pressDuration: Defaults to 0.3. - * pressDelay: Defaults to 0.0. - * - * @platform ios + * Apple TV parallax effects */ tvParallaxProperties: PropTypes.object, /** diff --git a/Libraries/Components/Touchable/TouchableNativeFeedback.android.js b/Libraries/Components/Touchable/TouchableNativeFeedback.android.js index 77e54347928..82031a4198a 100644 --- a/Libraries/Components/Touchable/TouchableNativeFeedback.android.js +++ b/Libraries/Components/Touchable/TouchableNativeFeedback.android.js @@ -4,6 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict-local * @format */ @@ -22,6 +23,8 @@ const createReactClass = require('create-react-class'); const ensurePositiveDelayProps = require('ensurePositiveDelayProps'); const processColor = require('processColor'); +import type {PressEvent} from 'CoreEventTypes'; + const rippleBackgroundPropType = PropTypes.shape({ type: PropTypes.oneOf(['RippleAndroid']), color: PropTypes.number, @@ -38,8 +41,6 @@ const backgroundPropType = PropTypes.oneOfType([ themeAttributeBackgroundPropType, ]); -type Event = Object; - const PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; /** @@ -167,7 +168,7 @@ const TouchableNativeFeedback = createReactClass({ * `Touchable.Mixin` self callbacks. The mixin will invoke these if they are * defined on your component. */ - touchableHandleActivePressIn: function(e: Event) { + touchableHandleActivePressIn: function(e: PressEvent) { this.props.onPressIn && this.props.onPressIn(e); this._dispatchPressedStateChange(true); if (this.pressInLocation) { @@ -178,16 +179,16 @@ const TouchableNativeFeedback = createReactClass({ } }, - touchableHandleActivePressOut: function(e: Event) { + touchableHandleActivePressOut: function(e: PressEvent) { this.props.onPressOut && this.props.onPressOut(e); this._dispatchPressedStateChange(false); }, - touchableHandlePress: function(e: Event) { + touchableHandlePress: function(e: PressEvent) { this.props.onPress && this.props.onPress(e); }, - touchableHandleLongPress: function(e: Event) { + touchableHandleLongPress: function(e: PressEvent) { this.props.onLongPress && this.props.onLongPress(e); }, diff --git a/Libraries/ReactNative/UIManagerStatTracker.js b/Libraries/ReactNative/UIManagerStatTracker.js index 78e3e0b149d..0543afdbdae 100644 --- a/Libraries/ReactNative/UIManagerStatTracker.js +++ b/Libraries/ReactNative/UIManagerStatTracker.js @@ -33,12 +33,18 @@ const UIManagerStatTracker = { const createViewOrig = UIManager.createView; UIManager.createView = function(tag, className, rootTag, props) { incStat('createView', 1); + /* $FlowFixMe(>=0.86.0 site=react_native_fb) This comment suppresses an + * error found when Flow v0.86 was deployed. To see the error, delete + * this comment and run Flow. */ incStat('setProp', Object.keys(props || []).length); createViewOrig(tag, className, rootTag, props); }; const updateViewOrig = UIManager.updateView; UIManager.updateView = function(tag, className, props) { incStat('updateView', 1); + /* $FlowFixMe(>=0.86.0 site=react_native_fb) This comment suppresses an + * error found when Flow v0.86 was deployed. To see the error, delete + * this comment and run Flow. */ incStat('setProp', Object.keys(props || []).length); updateViewOrig(tag, className, props); }; @@ -52,7 +58,13 @@ const UIManagerStatTracker = { remove, ) { incStat('manageChildren', 1); + /* $FlowFixMe(>=0.86.0 site=react_native_fb) This comment suppresses an + * error found when Flow v0.86 was deployed. To see the error, delete + * this comment and run Flow. */ incStat('move', Object.keys(moveFrom || []).length); + /* $FlowFixMe(>=0.86.0 site=react_native_fb) This comment suppresses an + * error found when Flow v0.86 was deployed. To see the error, delete + * this comment and run Flow. */ incStat('remove', Object.keys(remove || []).length); manageChildrenOrig(tag, moveFrom, moveTo, addTags, addIndices, remove); }; diff --git a/Libraries/ReactNative/renderApplication.js b/Libraries/ReactNative/renderApplication.js index 7be946ec8b4..33749fca179 100644 --- a/Libraries/ReactNative/renderApplication.js +++ b/Libraries/ReactNative/renderApplication.js @@ -49,8 +49,8 @@ function renderApplication( RootComponent.prototype.unstable_isAsyncReactComponent === true ) { // $FlowFixMe This is not yet part of the official public API - const AsyncMode = React.unstable_AsyncMode; - renderable = {renderable}; + const ConcurrentMode = React.unstable_ConcurrentMode; + renderable = {renderable}; } if (fabric) { diff --git a/Libraries/StyleSheet/StyleSheet.js b/Libraries/StyleSheet/StyleSheet.js index 554b786414b..6391c095370 100644 --- a/Libraries/StyleSheet/StyleSheet.js +++ b/Libraries/StyleSheet/StyleSheet.js @@ -339,7 +339,7 @@ module.exports = { ) { let value; - if (typeof ReactNativeStyleAttributes[property] === 'string') { + if (ReactNativeStyleAttributes[property] === true) { value = {}; } else if (typeof ReactNativeStyleAttributes[property] === 'object') { value = ReactNativeStyleAttributes[property]; diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 72c53b080d1..35df7249cad 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -27,10 +27,10 @@ import type {PressRetentionOffset, TextProps} from 'TextProps'; type ResponseHandlers = $ReadOnly<{| onStartShouldSetResponder: () => boolean, - onResponderGrant: (event: SyntheticEvent<>, dispatchID: string) => void, - onResponderMove: (event: SyntheticEvent<>) => void, - onResponderRelease: (event: SyntheticEvent<>) => void, - onResponderTerminate: (event: SyntheticEvent<>) => void, + onResponderGrant: (event: PressEvent, dispatchID: string) => void, + onResponderMove: (event: PressEvent) => void, + onResponderRelease: (event: PressEvent) => void, + onResponderTerminate: (event: PressEvent) => void, onResponderTerminationRequest: () => boolean, |}>; @@ -93,12 +93,12 @@ class TouchableText extends React.Component { touchableHandleLongPress: ?(event: PressEvent) => void; touchableHandlePress: ?(event: PressEvent) => void; touchableHandleResponderGrant: ?( - event: SyntheticEvent<>, + event: PressEvent, dispatchID: string, ) => void; - touchableHandleResponderMove: ?(event: SyntheticEvent<>) => void; - touchableHandleResponderRelease: ?(event: SyntheticEvent<>) => void; - touchableHandleResponderTerminate: ?(event: SyntheticEvent<>) => void; + touchableHandleResponderMove: ?(event: PressEvent) => void; + touchableHandleResponderRelease: ?(event: PressEvent) => void; + touchableHandleResponderTerminate: ?(event: PressEvent) => void; touchableHandleResponderTerminationRequest: ?() => boolean; state = { @@ -173,25 +173,25 @@ class TouchableText extends React.Component { } return shouldSetResponder; }, - onResponderGrant: (event: SyntheticEvent<>, dispatchID: string): void => { + onResponderGrant: (event: PressEvent, dispatchID: string): void => { nullthrows(this.touchableHandleResponderGrant)(event, dispatchID); if (this.props.onResponderGrant != null) { this.props.onResponderGrant.call(this, event, dispatchID); } }, - onResponderMove: (event: SyntheticEvent<>): void => { + onResponderMove: (event: PressEvent): void => { nullthrows(this.touchableHandleResponderMove)(event); if (this.props.onResponderMove != null) { this.props.onResponderMove.call(this, event); } }, - onResponderRelease: (event: SyntheticEvent<>): void => { + onResponderRelease: (event: PressEvent): void => { nullthrows(this.touchableHandleResponderRelease)(event); if (this.props.onResponderRelease != null) { this.props.onResponderRelease.call(this, event); } }, - onResponderTerminate: (event: SyntheticEvent<>): void => { + onResponderTerminate: (event: PressEvent): void => { nullthrows(this.touchableHandleResponderTerminate)(event); if (this.props.onResponderTerminate != null) { this.props.onResponderTerminate.call(this, event); diff --git a/Libraries/Text/Text/RCTTextShadowView.m b/Libraries/Text/Text/RCTTextShadowView.m index 850879aa4f9..d1baf9ccb15 100644 --- a/Libraries/Text/Text/RCTTextShadowView.m +++ b/Libraries/Text/Text/RCTTextShadowView.m @@ -290,6 +290,9 @@ RCTRoundPixelValue(attachmentSize.width), RCTRoundPixelValue(attachmentSize.height) }}; + + NSRange truncatedGlyphRange = [layoutManager truncatedGlyphRangeInLineFragmentForGlyphAtIndex:range.location]; + BOOL viewIsTruncated = NSIntersectionRange(range, truncatedGlyphRange).length != 0; RCTLayoutContext localLayoutContext = layoutContext; localLayoutContext.absolutePosition.x += frame.origin.x; @@ -300,9 +303,11 @@ layoutDirection:self.layoutMetrics.layoutDirection layoutContext:localLayoutContext]; - // Reinforcing a proper frame origin for the Shadow View. RCTLayoutMetrics localLayoutMetrics = shadowView.layoutMetrics; - localLayoutMetrics.frame.origin = frame.origin; + localLayoutMetrics.frame.origin = frame.origin; // Reinforcing a proper frame origin for the Shadow View. + if (viewIsTruncated) { + localLayoutMetrics.displayType = RCTDisplayTypeNone; + } [shadowView layoutWithMetrics:localLayoutMetrics layoutContext:localLayoutContext]; } ]; diff --git a/Libraries/Text/TextProps.js b/Libraries/Text/TextProps.js index 773125d56be..878e42bef6f 100644 --- a/Libraries/Text/TextProps.js +++ b/Libraries/Text/TextProps.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -106,12 +106,12 @@ export type TextProps = $ReadOnly<{ * See https://facebook.github.io/react-native/docs/text.html#onpress */ onPress?: ?(event: PressEvent) => mixed, - onResponderGrant?: ?Function, - onResponderMove?: ?Function, - onResponderRelease?: ?Function, - onResponderTerminate?: ?Function, - onResponderTerminationRequest?: ?Function, - onStartShouldSetResponder?: ?Function, + onResponderGrant?: ?(event: PressEvent, dispatchID: string) => void, + onResponderMove?: ?(event: PressEvent) => void, + onResponderRelease?: ?(event: PressEvent) => void, + onResponderTerminate?: ?(event: PressEvent) => void, + onResponderTerminationRequest?: ?() => boolean, + onStartShouldSetResponder?: ?() => boolean, onTextLayout?: ?(event: TextLayoutEvent) => mixed, /** diff --git a/Libraries/Utilities/Platform.android.js b/Libraries/Utilities/Platform.android.js index 714045b93c9..6a9feb13753 100644 --- a/Libraries/Utilities/Platform.android.js +++ b/Libraries/Utilities/Platform.android.js @@ -19,8 +19,11 @@ const Platform = { return constants && constants.Version; }, get isTesting(): boolean { - const constants = NativeModules.PlatformConstants; - return constants && constants.isTesting; + if (__DEV__) { + const constants = NativeModules.PlatformConstants; + return constants && constants.isTesting; + } + return false; }, get isTV(): boolean { const constants = NativeModules.PlatformConstants; diff --git a/Libraries/Utilities/Platform.ios.js b/Libraries/Utilities/Platform.ios.js index a2f97769cc8..87ee54692aa 100644 --- a/Libraries/Utilities/Platform.ios.js +++ b/Libraries/Utilities/Platform.ios.js @@ -33,8 +33,11 @@ const Platform = { return constants ? constants.interfaceIdiom === 'tv' : false; }, get isTesting(): boolean { - const constants = NativeModules.PlatformConstants; - return constants && constants.isTesting; + if (__DEV__) { + const constants = NativeModules.PlatformConstants; + return constants && constants.isTesting; + } + return false; }, select: (obj: Object) => ('ios' in obj ? obj.ios : obj.default), }; diff --git a/Libraries/Utilities/ReactNativeTestTools.js b/Libraries/Utilities/ReactNativeTestTools.js new file mode 100644 index 00000000000..bcab51684d2 --- /dev/null +++ b/Libraries/Utilities/ReactNativeTestTools.js @@ -0,0 +1,165 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +const React = require('React'); +const ReactTestRenderer = require('react-test-renderer'); + +const {Switch, Text, TextInput, VirtualizedList} = require('react-native'); + +import type { + ReactTestInstance, + ReactTestRendererNode, + Predicate, +} from 'react-test-renderer'; + +function byClickable(): Predicate { + return withMessage( + node => + // note: lazy-mounts press handlers after the first press, + // so this is a workaround for targeting text nodes. + (node.type === Text && + node.props && + typeof node.props.onPress === 'function') || + // note: Special casing since it doesn't use touchable + (node.type === Switch && node.props && node.props.disabled !== true) || + (node.instance && + typeof node.instance.touchableHandlePress === 'function'), + 'is clickable', + ); +} + +function byTestID(testID: string): Predicate { + return withMessage( + node => node.props && node.props.testID === testID, + `testID prop equals ${testID}`, + ); +} + +function byTextMatching(regex: RegExp): Predicate { + return withMessage( + node => node.props && regex.exec(node.props.children), + `text content matches ${regex.toString()}`, + ); +} + +function enter(instance: ReactTestInstance, text: string) { + const input = instance.findByType(TextInput); + input.instance._onChange({nativeEvent: {text}}); +} + +// Returns null if there is no error, otherwise returns an error message string. +function maximumDepthError( + tree: {toJSON: () => ReactTestRendererNode}, + maxDepthLimit: number, +): ?string { + const maxDepth = maximumDepthOfJSON(tree.toJSON()); + if (maxDepth > maxDepthLimit) { + return ( + `maximumDepth of ${maxDepth} exceeded limit of ${maxDepthLimit} - this is a proxy ` + + 'metric to protect against stack overflow errors:\n\n' + + 'https://fburl.com/rn-view-stack-overflow.\n\n' + + 'To fix, you need to remove native layers from your hierarchy, such as unnecessary View ' + + 'wrappers.' + ); + } else { + return null; + } +} + +function expectNoConsoleWarn() { + (jest: $FlowFixMe).spyOn(console, 'warn').mockImplementation((...args) => { + expect(args).toBeFalsy(); + }); +} + +function expectNoConsoleError() { + let hasNotFailed = true; + (jest: $FlowFixMe).spyOn(console, 'error').mockImplementation((...args) => { + if (hasNotFailed) { + hasNotFailed = false; // set false to prevent infinite recursion + expect(args).toBeFalsy(); + } + }); +} + +// Takes a node from toJSON() +function maximumDepthOfJSON(node: ReactTestRendererNode): number { + if (node == null) { + return 0; + } else if (typeof node === 'string' || node.children == null) { + return 1; + } else { + let maxDepth = 0; + node.children.forEach(child => { + maxDepth = Math.max(maximumDepthOfJSON(child) + 1, maxDepth); + }); + return maxDepth; + } +} + +function renderAndEnforceStrictMode(element: React.Node) { + expectNoConsoleError(); + return renderWithStrictMode(element); +} + +function renderWithStrictMode(element: React.Node) { + const WorkAroundBugWithStrictModeInTestRenderer = prps => prps.children; + const StrictMode = (React: $FlowFixMe).StrictMode; + return ReactTestRenderer.create( + + {element} + , + ); +} + +function tap(instance: ReactTestInstance) { + const touchable = instance.find(byClickable()); + if (touchable.type === Text && touchable.props && touchable.props.onPress) { + touchable.props.onPress(); + } else if (touchable.type === Switch && touchable.props) { + const value = !touchable.props.value; + const {onChange, onValueChange} = touchable.props; + onChange && onChange({nativeEvent: {value}}); + onValueChange && onValueChange(value); + } else { + // Only tap when props.disabled isn't set (or there aren't any props) + if (!touchable.props || !touchable.props.disabled) { + touchable.instance.touchableHandlePress({nativeEvent: {}}); + } + } +} + +function scrollToBottom(instance: ReactTestInstance) { + const list = instance.findByType(VirtualizedList); + list.props && list.props.onEndReached(); +} + +// To make error messages a little bit better, we attach a custom toString +// implementation to a predicate +function withMessage(fn: Predicate, message: string): Predicate { + (fn: any).toString = () => message; + return fn; +} + +export {byClickable}; +export {byTestID}; +export {byTextMatching}; +export {enter}; +export {expectNoConsoleWarn}; +export {expectNoConsoleError}; +export {maximumDepthError}; +export {maximumDepthOfJSON}; +export {renderAndEnforceStrictMode}; +export {renderWithStrictMode}; +export {scrollToBottom}; +export {tap}; +export {withMessage}; diff --git a/RNTester/js/AccessibilityIOSExample.js b/RNTester/js/AccessibilityIOSExample.js index fcae4284450..96ed8fc39fc 100644 --- a/RNTester/js/AccessibilityIOSExample.js +++ b/RNTester/js/AccessibilityIOSExample.js @@ -12,18 +12,22 @@ const React = require('react'); const ReactNative = require('react-native'); -const {AccessibilityInfo, Text, View, TouchableOpacity} = ReactNative; +const {AccessibilityInfo, Text, View, TouchableOpacity, Alert} = ReactNative; class AccessibilityIOSExample extends React.Component<{}> { render() { return ( alert('onAccessibilityTap success')} + onAccessibilityTap={() => + Alert.alert('Alert', 'onAccessibilityTap success') + } accessible={true}> Accessibility normal tap example - alert('onMagicTap success')} accessible={true}> + Alert.alert('Alert', 'onMagicTap success')} + accessible={true}> Accessibility magic tap example diff --git a/RNTester/js/ActionSheetIOSExample.js b/RNTester/js/ActionSheetIOSExample.js index 36e3d9e81da..1a524859613 100644 --- a/RNTester/js/ActionSheetIOSExample.js +++ b/RNTester/js/ActionSheetIOSExample.js @@ -12,7 +12,14 @@ const React = require('react'); const ReactNative = require('react-native'); -const {ActionSheetIOS, StyleSheet, takeSnapshot, Text, View} = ReactNative; +const { + ActionSheetIOS, + StyleSheet, + takeSnapshot, + Text, + View, + Alert, +} = ReactNative; const BUTTONS = ['Option 0', 'Option 1', 'Option 2', 'Delete', 'Cancel']; const DESTRUCTIVE_INDEX = 3; @@ -106,7 +113,7 @@ class ShareActionSheetExample extends React.Component< subject: 'a subject to go in the email heading', excludedActivityTypes: ['com.apple.UIKit.activity.PostToTwitter'], }, - error => alert(error), + error => Alert.alert('Error', error), (completed, method) => { let text; if (completed) { @@ -146,7 +153,7 @@ class ShareScreenshotExample extends React.Component<{}, $FlowFixMeState> { url: uri, excludedActivityTypes: ['com.apple.UIKit.activity.PostToTwitter'], }, - error => alert(error), + error => Alert.alert('Error', error), (completed, method) => { let text; if (completed) { @@ -158,7 +165,7 @@ class ShareScreenshotExample extends React.Component<{}, $FlowFixMeState> { }, ); }) - .catch(error => alert(error)); + .catch(error => Alert.alert('Error', error)); }; } diff --git a/RNTester/js/GeolocationExample.js b/RNTester/js/GeolocationExample.js index f659b7c4afc..8ed2182ecd9 100644 --- a/RNTester/js/GeolocationExample.js +++ b/RNTester/js/GeolocationExample.js @@ -12,7 +12,7 @@ const React = require('react'); const ReactNative = require('react-native'); -const {StyleSheet, Text, View} = ReactNative; +const {StyleSheet, Text, View, Alert} = ReactNative; exports.framework = 'React'; exports.title = 'Geolocation'; @@ -41,7 +41,7 @@ class GeolocationExample extends React.Component<{}, $FlowFixMeState> { const initialPosition = JSON.stringify(position); this.setState({initialPosition}); }, - error => alert(JSON.stringify(error)), + error => Alert.alert('Error', JSON.stringify(error)), {enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}, ); this.watchID = navigator.geolocation.watchPosition(position => { diff --git a/RNTester/js/MultiColumnExample.js b/RNTester/js/MultiColumnExample.js index 1266cf1b6f7..28f7804c5ef 100644 --- a/RNTester/js/MultiColumnExample.js +++ b/RNTester/js/MultiColumnExample.js @@ -12,7 +12,7 @@ const React = require('react'); const ReactNative = require('react-native'); -const {FlatList, StyleSheet, Text, View} = ReactNative; +const {FlatList, StyleSheet, Text, View, Alert} = ReactNative; const RNTesterPage = require('./RNTesterPage'); @@ -91,7 +91,9 @@ class MultiColumnExample extends React.PureComponent< data={filteredData} key={this.state.numColumns + (this.state.fixedHeight ? 'f' : 'v')} numColumns={this.state.numColumns || 1} - onRefresh={() => alert('onRefresh: nothing to refresh :P')} + onRefresh={() => + Alert.alert('Alert', 'onRefresh: nothing to refresh :P') + } refreshing={false} renderItem={this._renderItemComponent} disableVirtualization={!this.state.virtualized} diff --git a/RNTester/js/TextInputExample.android.js b/RNTester/js/TextInputExample.android.js index 6fc88f62583..7bed8d83f37 100644 --- a/RNTester/js/TextInputExample.android.js +++ b/RNTester/js/TextInputExample.android.js @@ -48,7 +48,8 @@ class TextEventsExample extends React.Component<{}, $FlowFixMeState> { } onContentSizeChange={event => this.updateText( - 'onContentSizeChange size: ' + event.nativeEvent.contentSize, + 'onContentSizeChange size: ' + + JSON.stringify(event.nativeEvent.contentSize), ) } onEndEditing={event => @@ -253,10 +254,10 @@ class ToggleDefaultPaddingExample extends React.Component< } type SelectionExampleState = { - selection: { + selection: $ReadOnly<{| start: number, - end: number, - }, + end?: number, + |}>, value: string, }; diff --git a/RNTester/js/TextInputExample.ios.js b/RNTester/js/TextInputExample.ios.js index 1240ba2d289..2077a911665 100644 --- a/RNTester/js/TextInputExample.ios.js +++ b/RNTester/js/TextInputExample.ios.js @@ -14,7 +14,7 @@ const Button = require('Button'); const InputAccessoryView = require('InputAccessoryView'); const React = require('react'); const ReactNative = require('react-native'); -const {Text, TextInput, View, StyleSheet, Slider, Switch} = ReactNative; +const {Text, TextInput, View, StyleSheet, Slider, Switch, Alert} = ReactNative; class WithLabel extends React.Component<$FlowFixMeProps> { render() { @@ -71,7 +71,7 @@ class TextEventsExample extends React.Component<{}, $FlowFixMeState> { 'onSelectionChange range: ' + event.nativeEvent.selection.start + ',' + - event.nativeEvent.selection.end, + (event.nativeEvent.selection.end || ''), ) } onKeyPress={event => { @@ -348,10 +348,10 @@ class BlurOnSubmitExample extends React.Component<{}> { } type SelectionExampleState = { - selection: {| + selection: $ReadOnly<{| start: number, end?: number, - |}, + |}>, value: string, }; @@ -862,7 +862,9 @@ exports.examples = [ returnKeyType="next" blurOnSubmit={true} multiline={true} - onSubmitEditing={event => alert(event.nativeEvent.text)} + onSubmitEditing={event => + Alert.alert('Alert', event.nativeEvent.text) + } /> ); diff --git a/RNTester/js/TransparentHitTestExample.js b/RNTester/js/TransparentHitTestExample.js index 34fa7387cc2..908183bf56f 100644 --- a/RNTester/js/TransparentHitTestExample.js +++ b/RNTester/js/TransparentHitTestExample.js @@ -12,13 +12,13 @@ const React = require('react'); const ReactNative = require('react-native'); -const {Text, View, TouchableOpacity} = ReactNative; +const {Text, View, TouchableOpacity, Alert} = ReactNative; class TransparentHitTestExample extends React.Component<{}> { render() { return ( - alert('Hi!')}> + Alert.alert('Alert', 'Hi!')}> HELLO! diff --git a/RNTester/js/XHRExampleFetch.js b/RNTester/js/XHRExampleFetch.js index cae80aa41d1..1377f18c34a 100644 --- a/RNTester/js/XHRExampleFetch.js +++ b/RNTester/js/XHRExampleFetch.js @@ -27,7 +27,7 @@ class XHRExampleFetch extends React.Component { this.responseHeaders = null; } - submit(uri: String) { + submit(uri: string) { fetch(uri) .then(response => { this.responseURL = response.url; diff --git a/RNTester/js/websocket_test_server.js b/RNTester/js/websocket_test_server.js index fee92917fd3..19e3a43167d 100755 --- a/RNTester/js/websocket_test_server.js +++ b/RNTester/js/websocket_test_server.js @@ -35,7 +35,7 @@ server.on('connection', ws => { console.log('Received message:', message); console.log('Cookie:', ws.upgradeReq.headers.cookie); if (respondWithBinary) { - message = new Buffer(message); + message = Buffer.from(message); } if (message === 'getImage') { message = fs.readFileSync(path.resolve(__dirname, 'flux@3x.png')); diff --git a/React/.clang-format b/React/.clang-format new file mode 100644 index 00000000000..e6371fc8bd6 --- /dev/null +++ b/React/.clang-format @@ -0,0 +1,87 @@ +--- +AccessModifierOffset: -1 +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: true +AlignOperands: false +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: WebKit +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ForEachMacros: [ FOR_EACH_RANGE, FOR_EACH, ] +IncludeCategories: + - Regex: '^<.*\.h(pp)?>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IndentCaseLabels: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 8 +UseTab: Never +... diff --git a/React/Base/RCTBridge.h b/React/Base/RCTBridge.h index 3af1a19767c..406a9376b77 100644 --- a/React/Base/RCTBridge.h +++ b/React/Base/RCTBridge.h @@ -97,8 +97,8 @@ RCT_EXTERN NSString *RCTBridgeModuleNameForClass(Class bridgeModuleClass); * Experimental. * Check/set if JSI-bound NativeModule is enabled. By default it's off. */ -RCT_EXTERN BOOL RCTJSINativeModuleEnabled(void); -RCT_EXTERN void RCTEnableJSINativeModule(BOOL enabled); +RCT_EXTERN BOOL RCTTurboModuleEnabled(void); +RCT_EXTERN void RCTEnableTurboModule(BOOL enabled); /** * Async batched bridge used to communicate with the JavaScript application. @@ -151,8 +151,12 @@ RCT_EXTERN void RCTEnableJSINativeModule(BOOL enabled); * lazily instantiated, so calling these methods for the first time with a given * module name/class may cause the class to be sychronously instantiated, * potentially blocking both the calling thread and main thread for a short time. + * + * Note: This method does NOT lazily load the particular module if it's not yet loaded. */ - (id)moduleForName:(NSString *)moduleName; +- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad; +// Note: This method lazily load the module as necessary. - (id)moduleForClass:(Class)moduleClass; /** diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index a8a79a9456c..98f4a497240 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -85,14 +85,14 @@ NSString *RCTBridgeModuleNameForClass(Class cls) return RCTDropReactPrefixes(name); } -static BOOL jsiNativeModuleEnabled = NO; -BOOL RCTJSINativeModuleEnabled(void) +static BOOL turboModuleEnabled = NO; +BOOL RCTTurboModuleEnabled(void) { - return jsiNativeModuleEnabled; + return turboModuleEnabled; } -void RCTEnableJSINativeModule(BOOL enabled) { - jsiNativeModuleEnabled = enabled; +void RCTEnableTurboModule(BOOL enabled) { + turboModuleEnabled = enabled; } #if RCT_DEBUG @@ -241,6 +241,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init) return [self.batchedBridge moduleForName:moduleName]; } +- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad +{ + return [self.batchedBridge moduleForName:moduleName lazilyLoadIfNecessary:lazilyLoad]; +} + - (id)moduleForClass:(Class)moduleClass { id module = [self.batchedBridge moduleForClass:moduleClass]; diff --git a/React/Base/RCTBridgeModule.h b/React/Base/RCTBridgeModule.h index 5b5357668c5..a01e4117aca 100644 --- a/React/Base/RCTBridgeModule.h +++ b/React/Base/RCTBridgeModule.h @@ -301,7 +301,7 @@ RCT_EXTERN void RCTRegisterModule(Class); \ * for the lifetime of the bridge, so it is not suitable for returning dynamic values, but may be used for long-lived * values such as session keys, that are regenerated only as part of a reload of the entire React application. * - * If you implement this method and do not implement `requiresMainThreadSetup`, you will trigger deprecated logic + * If you implement this method and do not implement `requiresMainQueueSetup`, you will trigger deprecated logic * that eagerly initializes your module on bridge startup. In the future, this behaviour will be changed to default * to initializing lazily, and even modules with constants will be initialized lazily. */ @@ -324,9 +324,9 @@ RCT_EXTERN void RCTRegisterModule(Class); \ /** * Experimental. - * A protocol to declare that a class supports JSI-bound NativeModule. + * A protocol to declare that a class supports TurboModule. * This may be removed in the future. */ -@protocol RCTJSINativeModule +@protocol RCTTurboModule @end diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index 9f42541df8f..74ec4ec0325 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -439,6 +439,30 @@ struct RCTInstanceCallback : public InstanceCallback { return _moduleDataByName[moduleName].instance; } +- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad +{ + if (!lazilyLoad) { + return [self moduleForName:moduleName]; + } + + RCTModuleData *moduleData = _moduleDataByName[moduleName]; + if (moduleData) { + return moduleData.instance; + } + + // Module may not be loaded yet, so attempt to force load it here. + const BOOL result = [self.delegate respondsToSelector:@selector(bridge:didNotFindModule:)] && + [self.delegate bridge:self didNotFindModule:moduleName]; + if (result) { + // Try again. + moduleData = _moduleDataByName[moduleName]; + } else { + RCTLogError(@"Unable to find module for %@", moduleName); + } + + return moduleData.instance; +} + - (BOOL)moduleIsInitialized:(Class)moduleClass { return _moduleDataByName[RCTBridgeModuleNameForClass(moduleClass)].hasInstance; @@ -446,17 +470,7 @@ struct RCTInstanceCallback : public InstanceCallback { - (id)moduleForClass:(Class)moduleClass { - NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass); - RCTModuleData *moduleData = _moduleDataByName[moduleName]; - if (moduleData) { - return moduleData.instance; - } - - // Module may not be loaded yet, so attempt to force load it here. - RCTAssert([moduleClass conformsToProtocol:@protocol(RCTBridgeModule)], @"Asking for a NativeModule that doesn't conform to RCTBridgeModule: %@", NSStringFromClass(moduleClass)); - [self registerAdditionalModuleClasses:@[moduleClass]]; - - return _moduleDataByName[moduleName].instance; + return [self moduleForName:RCTBridgeModuleNameForClass(moduleClass) lazilyLoadIfNecessary:YES]; } - (std::shared_ptr)_buildModuleRegistryUnlocked @@ -547,7 +561,7 @@ struct RCTInstanceCallback : public InstanceCallback { NSArray *moduleClassesCopy = [moduleClasses copy]; NSMutableArray *moduleDataByID = [NSMutableArray arrayWithCapacity:moduleClassesCopy.count]; for (Class moduleClass in moduleClassesCopy) { - if (RCTJSINativeModuleEnabled() && [moduleClass conformsToProtocol:@protocol(RCTJSINativeModule)]) { + if (RCTTurboModuleEnabled() && [moduleClass conformsToProtocol:@protocol(RCTTurboModule)]) { continue; } NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass); @@ -652,7 +666,7 @@ struct RCTInstanceCallback : public InstanceCallback { // we must use the names provided by the delegate method here. for (NSString *moduleName in moduleClasses) { Class moduleClass = moduleClasses[moduleName]; - if (RCTJSINativeModuleEnabled() && [moduleClass conformsToProtocol:@protocol(RCTJSINativeModule)]) { + if (RCTTurboModuleEnabled() && [moduleClass conformsToProtocol:@protocol(RCTTurboModule)]) { continue; } diff --git a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm index c687a60eb51..38d1dbb4f86 100644 --- a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm @@ -73,7 +73,7 @@ using namespace facebook::react; _imageLocalData = std::static_pointer_cast(localData); assert(_imageLocalData); auto future = _imageLocalData->getImageRequest().getResponseFuture(); - future.via(&MainQueueExecutor::instance()).then([self](ImageResponse &&imageResponse) { + future.via(&MainQueueExecutor::instance()).thenValue([self](ImageResponse &&imageResponse) { self.image = (__bridge UIImage *)imageResponse.getImage().get(); }); } diff --git a/React/Fabric/RCTSurfaceTouchHandler.mm b/React/Fabric/RCTSurfaceTouchHandler.mm index e51ec6dfdfd..14d1a807f8d 100644 --- a/React/Fabric/RCTSurfaceTouchHandler.mm +++ b/React/Fabric/RCTSurfaceTouchHandler.mm @@ -130,7 +130,7 @@ static BOOL AnyTouchesChanged(NSSet *touches) { template struct PointerHasher { constexpr std::size_t operator()(const PointerT &value) const { - return reinterpret_cast(&value); + return reinterpret_cast(value); } }; @@ -196,29 +196,39 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithTarget:(id)target action:(SEL)action - (void)_updateTouches:(NSSet *)touches { for (UITouch *touch in touches) { - UpdateActiveTouchWithUITouch(_activeTouches[touch], touch, _rootComponentView); + UpdateActiveTouchWithUITouch(_activeTouches.at(touch), touch, _rootComponentView); } } - (void)_unregisterTouches:(NSSet *)touches { for (UITouch *touch in touches) { - const auto &activeTouch = _activeTouches[touch]; + const auto &activeTouch = _activeTouches.at(touch); _identifierPool.enqueue(activeTouch.touch.identifier); _activeTouches.erase(touch); } } -- (void)_dispatchTouches:(NSSet *)touches eventType:(RCTTouchEventType)eventType +- (std::vector)_activeTouchesFromTouches:(NSSet *)touches +{ + std::vector activeTouches; + activeTouches.reserve(touches.count); + + for (UITouch *touch in touches) { + activeTouches.push_back(_activeTouches.at(touch)); + } + + return activeTouches; +} + +- (void)_dispatchActiveTouches:(std::vector)activeTouches eventType:(RCTTouchEventType)eventType { TouchEvent event = {}; std::unordered_set changedActiveTouches = {}; std::unordered_set uniqueEventEmitter = {}; BOOL isEndishEventType = eventType == RCTTouchEventTypeTouchEnd || eventType == RCTTouchEventTypeTouchCancel; - for (UITouch *touch in touches) { - const auto &activeTouch = _activeTouches[touch]; - + for (const auto &activeTouch : activeTouches) { if (!activeTouch.eventEmitter) { continue; } @@ -276,7 +286,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithTarget:(id)target action:(SEL)action [super touchesBegan:touches withEvent:event]; [self _registerTouches:touches]; - [self _dispatchTouches:touches eventType:RCTTouchEventTypeTouchStart]; + [self _dispatchActiveTouches:[self _activeTouchesFromTouches:touches] + eventType:RCTTouchEventTypeTouchStart]; if (self.state == UIGestureRecognizerStatePossible) { self.state = UIGestureRecognizerStateBegan; @@ -290,7 +301,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithTarget:(id)target action:(SEL)action [super touchesMoved:touches withEvent:event]; [self _updateTouches:touches]; - [self _dispatchTouches:touches eventType:RCTTouchEventTypeTouchMove]; + [self _dispatchActiveTouches:[self _activeTouchesFromTouches:touches] + eventType:RCTTouchEventTypeTouchMove]; self.state = UIGestureRecognizerStateChanged; } @@ -300,7 +312,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithTarget:(id)target action:(SEL)action [super touchesEnded:touches withEvent:event]; [self _updateTouches:touches]; - [self _dispatchTouches:touches eventType:RCTTouchEventTypeTouchEnd]; + [self _dispatchActiveTouches:[self _activeTouchesFromTouches:touches] + eventType:RCTTouchEventTypeTouchEnd]; [self _unregisterTouches:touches]; if (AllTouchesAreCancelledOrEnded(event.allTouches)) { @@ -315,7 +328,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithTarget:(id)target action:(SEL)action [super touchesCancelled:touches withEvent:event]; [self _updateTouches:touches]; - [self _dispatchTouches:touches eventType:RCTTouchEventTypeTouchCancel]; + [self _dispatchActiveTouches:[self _activeTouchesFromTouches:touches] + eventType:RCTTouchEventTypeTouchCancel]; [self _unregisterTouches:touches]; if (AllTouchesAreCancelledOrEnded(event.allTouches)) { @@ -327,10 +341,23 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithTarget:(id)target action:(SEL)action - (void)reset { - // Technically, `_activeTouches` must be already empty at this point, - // but just to be sure, we clear it explicitly. - _activeTouches.clear(); - _identifierPool.reset(); + [super reset]; + + if (_activeTouches.size() != 0) { + std::vector activeTouches; + activeTouches.reserve(_activeTouches.size()); + + for (auto const &pair : _activeTouches) { + activeTouches.push_back(pair.second); + } + + [self _dispatchActiveTouches:activeTouches + eventType:RCTTouchEventTypeTouchCancel]; + + // Force-unregistering all the touches. + _activeTouches.clear(); + _identifierPool.reset(); + } } - (BOOL)canPreventGestureRecognizer:(__unused UIGestureRecognizer *)preventedGestureRecognizer diff --git a/React/Fabric/Surface/RCTFabricSurface.mm b/React/Fabric/Surface/RCTFabricSurface.mm index dd7e5f9c938..bf067994618 100644 --- a/React/Fabric/Surface/RCTFabricSurface.mm +++ b/React/Fabric/Surface/RCTFabricSurface.mm @@ -49,7 +49,8 @@ _rootTag = [RCTAllocateRootViewTag() integerValue]; _minimumSize = CGSizeZero; - _maximumSize = CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX); + // FIXME: Replace with `_maximumSize = CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX);`. + _maximumSize = RCTScreenSize(); _touchHandler = [RCTSurfaceTouchHandler new]; diff --git a/React/Modules/RCTUIManager.m b/React/Modules/RCTUIManager.m index 0760c7e5786..a8960f88de2 100644 --- a/React/Modules/RCTUIManager.m +++ b/React/Modules/RCTUIManager.m @@ -488,6 +488,7 @@ static NSDictionary *deviceOrientationEventBody(UIDeviceOrientation orientation) UIUserInterfaceLayoutDirection layoutDirection; BOOL isNew; BOOL parentIsNew; + RCTDisplayType displayType; } RCTFrameData; // Construct arrays then hand off to main thread @@ -505,6 +506,7 @@ static NSDictionary *deviceOrientationEventBody(UIDeviceOrientation orientation) layoutMetrics.layoutDirection, shadowView.isNewView, shadowView.superview.isNewView, + layoutMetrics.displayType }; } } @@ -566,6 +568,7 @@ static NSDictionary *deviceOrientationEventBody(UIDeviceOrientation orientation) RCTLayoutAnimation *updatingLayoutAnimation = isNew ? nil : layoutAnimationGroup.updatingLayoutAnimation; BOOL shouldAnimateCreation = isNew && !frameData.parentIsNew; RCTLayoutAnimation *creatingLayoutAnimation = shouldAnimateCreation ? layoutAnimationGroup.creatingLayoutAnimation : nil; + BOOL isHidden = frameData.displayType == RCTDisplayTypeNone; void (^completion)(BOOL) = ^(BOOL finished) { completionsCalled++; @@ -581,6 +584,10 @@ static NSDictionary *deviceOrientationEventBody(UIDeviceOrientation orientation) if (view.reactLayoutDirection != layoutDirection) { view.reactLayoutDirection = layoutDirection; } + + if (view.isHidden != isHidden) { + view.hidden = isHidden; + } if (creatingLayoutAnimation) { diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index 13f98aff542..04b6e4e4cc5 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -36,6 +36,7 @@ shouldStartLoadForRequest:(NSMutableDictionary *)request @property (nonatomic, assign) UIEdgeInsets contentInset; @property (nonatomic, assign) BOOL automaticallyAdjustContentInsets; ++ (void)setClientAuthenticationCredential:(nullable NSURLCredential*)credential; - (void)postMessage:(NSString *)message; - (void)injectJavaScript:(NSString *)script; - (void)goForward; diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index 9f8e3443ec2..79f81df5de0 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -10,6 +10,8 @@ #import "RCTAutoInsetsProtocol.h" static NSString *const MessageHanderName = @"ReactNative"; +static NSURLCredential* clientAuthenticationCredential; + @interface RCTWKWebView () @property (nonatomic, copy) RCTDirectEventBlock onLoadingStart; @@ -310,6 +312,25 @@ static NSString *const MessageHanderName = @"ReactNative"; [self setBackgroundColor: _savedBackgroundColor]; } ++ (void)setClientAuthenticationCredential:(nullable NSURLCredential*)credential { + clientAuthenticationCredential = credential; +} + +- (void) webView:(WKWebView *)webView + didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable))completionHandler +{ + if (!clientAuthenticationCredential) { + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + return; + } + if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate) { + completionHandler(NSURLSessionAuthChallengeUseCredential, clientAuthenticationCredential); + } else { + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); +} +} + - (void)evaluateJS:(NSString *)js thenCall: (void (^)(NSString*)) callback { diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index 24394c4562e..10f15ce975d 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -323,7 +323,11 @@ dependencies { api 'com.google.code.findbugs:jsr305:3.0.2' api "com.squareup.okhttp3:okhttp:${OKHTTP_VERSION}" api "com.squareup.okhttp3:okhttp-urlconnection:${OKHTTP_VERSION}" +<<<<<<< HEAD api 'com.squareup.okio:okio:1.15.0' +======= + api 'com.squareup.okio:okio:1.14.0' +>>>>>>> parent of b864e7e63e... Revert "Merge branch 'master' into 0.58-stable" compile 'org.webkit:android-jsc:r174650' testImplementation "junit:junit:${JUNIT_VERSION}" diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/core/WritableNativeMapTest.java b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/core/WritableNativeMapTest.java new file mode 100644 index 00000000000..bb2ad2c9bab --- /dev/null +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/core/WritableNativeMapTest.java @@ -0,0 +1,104 @@ +package com.facebook.react.tests.core; + +import static org.fest.assertions.api.Assertions.assertThat; + +import android.support.test.runner.AndroidJUnit4; +import com.facebook.react.bridge.UnexpectedNativeTypeException; +import com.facebook.react.bridge.WritableNativeArray; +import com.facebook.react.bridge.WritableNativeMap; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class WritableNativeMapTest { + + private WritableNativeMap mMap; + + @Before + public void setup() { + mMap = new WritableNativeMap(); + mMap.putBoolean("boolean", true); + mMap.putDouble("double", 1.2); + mMap.putInt("int", 1); + mMap.putString("string", "abc"); + mMap.putMap("map", new WritableNativeMap()); + mMap.putArray("array", new WritableNativeArray()); + mMap.putBoolean("dvacca", true); + mMap.setUseNativeAccessor(true); + } + + @Test + public void testBoolean() { + assertThat(mMap.getBoolean("boolean")).isEqualTo(true); + } + + @Test(expected = UnexpectedNativeTypeException.class) + public void testBooleanInvalidType() { + mMap.getBoolean("string"); + } + + @Test + public void testDouble() { + assertThat(mMap.getDouble("double")).isEqualTo(1.2); + } + + @Test(expected = UnexpectedNativeTypeException.class) + public void testDoubleInvalidType() { + mMap.getDouble("string"); + } + + @Test + public void testInt() { + assertThat(mMap.getInt("int")).isEqualTo(1); + } + + @Test(expected = UnexpectedNativeTypeException.class) + public void testIntInvalidType() { + mMap.getInt("string"); + } + + @Test + public void testString() { + assertThat(mMap.getString("string")).isEqualTo("abc"); + } + + @Test(expected = UnexpectedNativeTypeException.class) + public void testStringInvalidType() { + mMap.getString("int"); + } + + @Test + public void testMap() { + assertThat(mMap.getMap("map")).isNotNull(); + } + + @Test(expected = UnexpectedNativeTypeException.class) + public void testMapInvalidType() { + mMap.getMap("string"); + } + + @Test + public void testArray() { + assertThat(mMap.getArray("array")).isNotNull(); + } + + @Test(expected = UnexpectedNativeTypeException.class) + public void testArrayInvalidType() { + mMap.getArray("string"); + } + + @Ignore("Needs to be implemented") + @Test + public void testErrorMessageContainsKey() { + String key = "fkg"; + try { + mMap.getString(key); + Assert.fail("Expected an UnexpectedNativeTypeException to be thrown"); + } catch (UnexpectedNativeTypeException e) { + assertThat(e.getMessage()).contains(key); + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java index 2e408b2e5d2..eb84d6e33d9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java @@ -325,7 +325,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { // shared under the hood. // See https://github.com/square/okhttp/wiki/Recipes#per-call-configuration for more information if (timeout != mClient.connectTimeoutMillis()) { - clientBuilder.readTimeout(timeout, TimeUnit.MILLISECONDS); + clientBuilder.connectTimeout(timeout, TimeUnit.MILLISECONDS); } OkHttpClient client = clientBuilder.build(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoHelpers.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoHelpers.java index 16dc414dcd6..01d3c6abbff 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoHelpers.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoHelpers.java @@ -7,6 +7,7 @@ package com.facebook.react.modules.systeminfo; import java.io.BufferedReader; import java.io.InputStreamReader; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Locale; @@ -84,7 +85,7 @@ public class AndroidInfoHelpers { Runtime.getRuntime().exec(new String[] {"/system/bin/getprop", METRO_HOST_PROP_NAME}); reader = new BufferedReader( - new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8)); + new InputStreamReader(process.getInputStream(), Charset.forName("UTF-8"))); String lastLine = ""; String line; diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java index c9bbcb73457..f28f271f7f0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java @@ -147,6 +147,11 @@ public final class WebSocketModule extends ReactContextBaseJavaModule { sendEvent("websocketOpen", params); } + @Override + public void onClosing(WebSocket websocket, int code, String reason) { + websocket.close(code, reason); + } + @Override public void onClosed(WebSocket webSocket, int code, String reason) { WritableMap params = Arguments.createMap(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java index 0176c529048..df3e443f96c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java @@ -562,6 +562,11 @@ public class NativeViewHierarchyManager { */ protected synchronized void dropView(View view) { UiThreadUtil.assertOnUiThread(); + if (mTagsToViewManagers.get(view.getId()) == null) { + // This view has already been dropped (likely due to a threading issue caused by async js + // execution). Ignore this drop operation. + return; + } if (!mRootTags.get(view.getId())) { // For non-root views we notify viewmanager with {@link ViewManager#onDropInstance} resolveViewManager(view.getId()).onDropViewInstance(view); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java index 47c97b11a11..885ab3dd2b3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java @@ -94,8 +94,6 @@ public interface ReactShadowNode { void removeAndDisposeAllChildren(); - @Nullable ReactStylesDiffMap getNewProps(); - /** * This method will be called by {@link UIManagerModule} once per batch, before calculating * layout. Will be only called for nodes that are marked as updated with {@link #markUpdated()} or @@ -348,12 +346,4 @@ public interface ReactShadowNode { boolean isMeasureDefined(); void dispose(); - - /** - * @return an immutable {@link List} containing the children of this - * {@link ReactShadowNode}. - */ - List getChildrenList(); - - void updateScreenLayout(ReactShadowNode prevNode); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java index 2f459eccc12..7fa72be0b1c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java @@ -6,12 +6,7 @@ */ package com.facebook.react.uimanager; -import static java.lang.System.arraycopy; - -import com.facebook.debug.holder.PrinterHolder; -import com.facebook.debug.tags.ReactDebugOverlayTags; import com.facebook.infer.annotation.Assertions; -import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.uimanager.annotations.ReactPropertyHolder; import com.facebook.yoga.YogaAlign; import com.facebook.yoga.YogaBaselineFunction; @@ -30,8 +25,6 @@ import com.facebook.yoga.YogaValue; import com.facebook.yoga.YogaWrap; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.List; import javax.annotation.Nullable; /** @@ -60,8 +53,6 @@ import javax.annotation.Nullable; @ReactPropertyHolder public class ReactShadowNodeImpl implements ReactShadowNode { - private static final boolean DEBUG = ReactBuildConfig.DEBUG || PrinterHolder.getPrinter().shouldDisplayLogMessage(ReactDebugOverlayTags.FABRIC_UI_MANAGER); - private static final String TAG = ReactShadowNodeImpl.class.getSimpleName(); private static final YogaConfig sYogaConfig; static { @@ -90,12 +81,6 @@ public class ReactShadowNodeImpl implements ReactShadowNode private final float[] mPadding = new float[Spacing.ALL + 1]; private final boolean[] mPaddingIsPercent = new boolean[Spacing.ALL + 1]; private YogaNode mYogaNode; - private int mGenerationDebugInformation = 1; - private ReactShadowNode mOriginalReactShadowNode = null; - - private @Nullable ReactStylesDiffMap mNewProps; - private long mInstanceHandle; - private boolean mIsSealed = false; public ReactShadowNodeImpl() { mDefaultPadding = new Spacing(0); @@ -109,32 +94,6 @@ public class ReactShadowNodeImpl implements ReactShadowNode } } - protected ReactShadowNodeImpl(ReactShadowNodeImpl original) { - mReactTag = original.mReactTag; - mRootTag = original.mRootTag; - mViewClassName = original.mViewClassName; - mThemedContext = original.mThemedContext; - mShouldNotifyOnLayout = original.mShouldNotifyOnLayout; - mIsLayoutOnly = original.mIsLayoutOnly; - mNativeParent = original.mNativeParent; - mDefaultPadding = new Spacing(original.mDefaultPadding); - // Cloned nodes should be always updated. - mNodeUpdated = true; - // "cached" screen coordinates are not cloned because FabricJS not always clone the last - // ReactShadowNode that was rendered in the screen. - mScreenX = 0; - mScreenY = 0; - mScreenWidth = 0; - mScreenHeight = 0; - mGenerationDebugInformation = original.mGenerationDebugInformation + 1; - arraycopy(original.mPadding, 0, mPadding, 0, original.mPadding.length); - arraycopy(original.mPaddingIsPercent, 0, mPaddingIsPercent, 0, original.mPaddingIsPercent.length); - mNewProps = null; - mParent = null; - mOriginalReactShadowNode = original; - mIsSealed = false; - } - /** * Nodes that return {@code true} will be treated as "virtual" nodes. That is, nodes that are not * mapped into native views (e.g. nested text node). By default this method returns {@code false}. @@ -339,12 +298,6 @@ public class ReactShadowNodeImpl implements ReactShadowNode // no-op } - @Override - @Nullable - public ReactStylesDiffMap getNewProps() { - return mNewProps; - } - /** * Called after layout step at the end of the UI batch from {@link UIManagerModule}. May be used * to enqueue additional ui operations for the native view. Will only be called on nodes marked as @@ -976,7 +929,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode } result.append("<").append(getClass().getSimpleName()).append(" view='").append(getViewClass()) - .append("' tag=").append(getReactTag()).append(" gen=").append(mGenerationDebugInformation); + .append("' tag=").append(getReactTag()); if (mYogaNode != null) { result.append(" layout='x:").append(getScreenX()) .append(" y:").append(getScreenY()).append(" w:").append(getLayoutWidth()).append(" h:") @@ -1003,17 +956,4 @@ public class ReactShadowNodeImpl implements ReactShadowNode } } - @Nullable - @Override - public List getChildrenList() { - return mChildren == null ? null : Collections.unmodifiableList(mChildren); - } - - @Override - public void updateScreenLayout(ReactShadowNode prevNode) { - mScreenHeight = prevNode.getScreenHeight(); - mScreenWidth = prevNode.getScreenWidth(); - mScreenX = prevNode.getScreenX(); - mScreenY = prevNode.getScreenY(); - } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ShadowNodeRegistry.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ShadowNodeRegistry.java index 74a136caca4..4ce41a0bb8d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ShadowNodeRegistry.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ShadowNodeRegistry.java @@ -9,6 +9,7 @@ package com.facebook.react.uimanager; import android.util.SparseArray; import android.util.SparseBooleanArray; +import android.view.View; import com.facebook.react.common.SingleThreadAsserter; /** @@ -36,6 +37,11 @@ public class ShadowNodeRegistry { public void removeRootNode(int tag) { mThreadAsserter.assertNow(); + if (tag == View.NO_ID) { + // This root node has already been removed (likely due to a threading issue caused by async js + // execution). Ignore this root removal. + return; + } if (!mRootTags.get(tag)) { throw new IllegalViewOperationException( "View with tag " + tag + " is not registered as a root view"); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java index 4abd015ebe0..f73493257fd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java @@ -18,6 +18,7 @@ import com.facebook.react.touch.ReactInterceptingViewGroup; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactPropGroup; import com.facebook.react.uimanager.annotations.ReactPropertyHolder; +import com.facebook.yoga.YogaMeasureMode; import java.util.Map; import javax.annotation.Nullable; @@ -218,9 +219,9 @@ public abstract class ViewManager ReadableNativeMap localData, ReadableNativeMap props, float width, - int widthMode, + YogaMeasureMode widthMode, float height, - int heightMode) { + YogaMeasureMode heightMode) { return null; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java index 878bb5a3dc7..4907870d637 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java @@ -8,7 +8,6 @@ package com.facebook.react.uimanager.events; import android.view.MotionEvent; - import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java index ff720bd8156..722dd122509 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java @@ -439,7 +439,7 @@ public class ReactImageView extends GenericDraweeView { hierarchy.setActualImageScaleType(mScaleType); if (mDefaultImageDrawable != null) { - hierarchy.setPlaceholderImage(mDefaultImageDrawable, ScalingUtils.ScaleType.CENTER); + hierarchy.setPlaceholderImage(mDefaultImageDrawable, mScaleType); } if (mLoadingImageDrawable != null) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index f10bd47ebbe..d39159a8b9d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -309,8 +309,18 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou @Override public void fling(int velocityY) { + // Workaround. + // On Android P if a ScrollView is inverted, we will get a wrong sign for + // velocityY (see https://issuetracker.google.com/issues/112385925). + // At the same time, mOnScrollDispatchHelper tracks the correct velocity direction. + // + // Hence, we can use the absolute value from whatever the OS gives + // us and use the sign of what mOnScrollDispatchHelper has tracked. + final int correctedVelocityY = (int)(Math.abs(velocityY) * Math.signum(mOnScrollDispatchHelper.getYFlingVelocity())); + + if (mPagingEnabled) { - flingAndSnap(velocityY); + flingAndSnap(correctedVelocityY); } else if (mScroller != null) { // FB SCROLLVIEW CHANGE @@ -326,7 +336,7 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou getScrollX(), // startX getScrollY(), // startY 0, // velocityX - velocityY, // velocityY + correctedVelocityY, // velocityY 0, // minX 0, // maxX 0, // minY @@ -339,9 +349,9 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou // END FB SCROLLVIEW CHANGE } else { - super.fling(velocityY); + super.fling(correctedVelocityY); } - handlePostTouchScrolling(0, velocityY); + handlePostTouchScrolling(0, correctedVelocityY); } private void enableFpsListener() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java index 8b1ba78d131..98d4e02e187 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java @@ -1,13 +1,11 @@ /** * Copyright (c) Facebook, Inc. and its affiliates. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. + *

This source code is licensed under the MIT license found in the LICENSE file in the root + * directory of this source tree. */ - package com.facebook.react.views.text; -import android.graphics.Rect; import android.os.Build; import android.text.BoringLayout; import android.text.Layout; @@ -15,15 +13,12 @@ import android.text.Spannable; import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; -import android.util.DisplayMetrics; import android.view.Gravity; import android.widget.TextView; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; -import com.facebook.react.uimanager.LayoutShadowNode; -import com.facebook.react.uimanager.ReactShadowNodeImpl; import com.facebook.react.uimanager.Spacing; import com.facebook.react.uimanager.UIViewOperationQueue; import com.facebook.react.uimanager.annotations.ReactProp; @@ -62,16 +57,17 @@ public class ReactTextShadowNode extends ReactBaseTextShadowNode { YogaMeasureMode widthMode, float height, YogaMeasureMode heightMode) { + // TODO(5578671): Handle text direction (see View#getTextDirectionHeuristic) TextPaint textPaint = sTextPaintInstance; textPaint.setTextSize(mFontSize != UNSET ? mFontSize : getDefaultFontSize()); Layout layout; - Spanned text = Assertions.assertNotNull( - mPreparedSpannableText, - "Spannable element has not been prepared in onBeforeLayout"); + Spanned text = + Assertions.assertNotNull( + mPreparedSpannableText, + "Spannable element has not been prepared in onBeforeLayout"); BoringLayout.Metrics boring = BoringLayout.isBoring(text, textPaint); - float desiredWidth = boring == null ? - Layout.getDesiredWidth(text, textPaint) : Float.NaN; + float desiredWidth = boring == null ? Layout.getDesiredWidth(text, textPaint) : Float.NaN; // technically, width should never be negative, but there is currently a bug in boolean unconstrainedWidth = widthMode == YogaMeasureMode.UNDEFINED || width < 0; @@ -89,70 +85,64 @@ public class ReactTextShadowNode extends ReactBaseTextShadowNode { break; } - if (boring == null && - (unconstrainedWidth || - (!YogaConstants.isUndefined(desiredWidth) && desiredWidth <= width))) { + if (boring == null + && (unconstrainedWidth + || (!YogaConstants.isUndefined(desiredWidth) && desiredWidth <= width))) { // Is used when the width is not known and the text is not boring, ie. if it contains // unicode characters. int hintWidth = (int) Math.ceil(desiredWidth); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - layout = new StaticLayout( - text, - textPaint, - hintWidth, - alignment, - 1.f, - 0.f, - mIncludeFontPadding); + layout = + new StaticLayout( + text, textPaint, hintWidth, alignment, 1.f, 0.f, mIncludeFontPadding); } else { - layout = StaticLayout.Builder.obtain(text, 0, text.length(), textPaint, hintWidth) - .setAlignment(alignment) - .setLineSpacing(0.f, 1.f) - .setIncludePad(mIncludeFontPadding) - .setBreakStrategy(mTextBreakStrategy) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) - .build(); + layout = + StaticLayout.Builder.obtain(text, 0, text.length(), textPaint, hintWidth) + .setAlignment(alignment) + .setLineSpacing(0.f, 1.f) + .setIncludePad(mIncludeFontPadding) + .setBreakStrategy(mTextBreakStrategy) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) + .build(); } } else if (boring != null && (unconstrainedWidth || boring.width <= width)) { // Is used for single-line, boring text when the width is either unknown or bigger // than the width of the text. - layout = BoringLayout.make( - text, - textPaint, - boring.width, - alignment, - 1.f, - 0.f, - boring, - mIncludeFontPadding); + layout = + BoringLayout.make( + text, + textPaint, + boring.width, + alignment, + 1.f, + 0.f, + boring, + mIncludeFontPadding); } else { // Is used for multiline, boring text and the width is known. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - layout = new StaticLayout( - text, - textPaint, - (int) width, - alignment, - 1.f, - 0.f, - mIncludeFontPadding); + layout = + new StaticLayout( + text, textPaint, (int) width, alignment, 1.f, 0.f, mIncludeFontPadding); } else { - layout = StaticLayout.Builder.obtain(text, 0, text.length(), textPaint, (int) width) - .setAlignment(alignment) - .setLineSpacing(0.f, 1.f) - .setIncludePad(mIncludeFontPadding) - .setBreakStrategy(mTextBreakStrategy) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) - .build(); + layout = + StaticLayout.Builder.obtain(text, 0, text.length(), textPaint, (int) width) + .setAlignment(alignment) + .setLineSpacing(0.f, 1.f) + .setIncludePad(mIncludeFontPadding) + .setBreakStrategy(mTextBreakStrategy) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) + .build(); } } if (mShouldNotifyOnTextLayout) { WritableArray lines = - FontMetricsUtil.getFontMetrics(text, layout, sTextPaintInstance, getThemedContext()); + FontMetricsUtil.getFontMetrics( + text, layout, sTextPaintInstance, getThemedContext()); WritableMap event = Arguments.createMap(); event.putArray("lines", lines); getThemedContext() @@ -161,7 +151,8 @@ public class ReactTextShadowNode extends ReactBaseTextShadowNode { } if (mNumberOfLines != UNSET && mNumberOfLines < layout.getLineCount()) { - return YogaMeasureOutput.make(layout.getWidth(), layout.getLineBottom(mNumberOfLines - 1)); + return YogaMeasureOutput.make( + layout.getWidth(), layout.getLineBottom(mNumberOfLines - 1)); } else { return YogaMeasureOutput.make(layout.getWidth(), layout.getHeight()); } @@ -215,17 +206,16 @@ public class ReactTextShadowNode extends ReactBaseTextShadowNode { if (mPreparedSpannableText != null) { ReactTextUpdate reactTextUpdate = - new ReactTextUpdate( - mPreparedSpannableText, - UNSET, - mContainsImages, - getPadding(Spacing.START), - getPadding(Spacing.TOP), - getPadding(Spacing.END), - getPadding(Spacing.BOTTOM), - getTextAlign(), - mTextBreakStrategy - ); + new ReactTextUpdate( + mPreparedSpannableText, + UNSET, + mContainsImages, + getPadding(Spacing.START), + getPadding(Spacing.TOP), + getPadding(Spacing.END), + getPadding(Spacing.BOTTOM), + getTextAlign(), + mTextBreakStrategy); uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), reactTextUpdate); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java index c2f4ed22bac..39cedcf7007 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java @@ -9,18 +9,18 @@ package com.facebook.react.views.text; import android.text.Layout; import android.text.Spannable; -import com.facebook.react.common.MapBuilder; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableNativeMap; +import com.facebook.react.common.MapBuilder; import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.ReactStylesDiffMap; import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.yoga.YogaMeasureMode; import java.util.Map; import javax.annotation.Nullable; -import com.facebook.yoga.YogaMeasureMode; /** * Concrete class for {@link ReactTextAnchorViewManager} which represents view managers of anchor @@ -109,18 +109,17 @@ public class ReactTextViewManager ReadableNativeMap localData, ReadableNativeMap props, float width, - int widthMode, + YogaMeasureMode widthMode, float height, - int heightMode) { + YogaMeasureMode heightMode) { - // TODO: should widthMode and heightMode be a YogaMeasureMode? return TextLayoutManager.measureText(context, view, localData, props, width, - YogaMeasureMode.fromInt(widthMode), + widthMode, height, - YogaMeasureMode.fromInt(heightMode)); + heightMode); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java index fdb7bb5cb1a..cbf49e34dc0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java @@ -384,33 +384,40 @@ public class TextAttributeProps { : -1; } - //TODO remove this from here + //TODO T31905686 remove this from here and add support to RTL private YogaDirection getLayoutDirection() { return YogaDirection.LTR; } public float getBottomPadding() { - // TODO convert into constants - return getFloatProp("bottomPadding", 0f); + return getPaddingProp(ViewProps.PADDING_BOTTOM); } public float getLeftPadding() { - return getFloatProp("leftPadding", 0f); + return getPaddingProp(ViewProps.PADDING_LEFT); } public float getStartPadding() { - return getFloatProp("startPadding", 0f); + return getPaddingProp(ViewProps.PADDING_START); } public float getEndPadding() { - return getFloatProp("endPadding", 0f); + return getPaddingProp(ViewProps.PADDING_END); } public float getTopPadding() { - return getFloatProp("topPadding", 0f); + return getPaddingProp(ViewProps.PADDING_TOP); } public float getRightPadding() { - return getFloatProp("rightPadding", 0f); + return getPaddingProp(ViewProps.PADDING_RIGHT); + } + + private float getPaddingProp(String paddingType) { + if (mProps.hasKey(ViewProps.PADDING)) { + return PixelUtil.toPixelFromDIP(getFloatProp(ViewProps.PADDING, 0f)); + } + + return PixelUtil.toPixelFromDIP(getFloatProp(paddingType, 0f)); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java index 69990f08749..27b86527906 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java @@ -29,8 +29,10 @@ import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableNativeMap; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.ReactStylesDiffMap; +import com.facebook.react.uimanager.ViewDefaults; import com.facebook.yoga.YogaConstants; import com.facebook.yoga.YogaMeasureMode; +import java.awt.font.TextAttribute; import java.util.ArrayList; import java.util.List; @@ -95,11 +97,9 @@ public class TextLayoutManager { new CustomLetterSpacingSpan(textAttributes.mLetterSpacing))); } } - if (textAttributes.mFontSize != UNSET) { - ops.add( - new SetSpanOperation( - start, end, new AbsoluteSizeSpan((int) (textAttributes.mFontSize)))); - } + ops.add( + new SetSpanOperation( + start, end, new AbsoluteSizeSpan(textAttributes.mFontSize))); if (textAttributes.mFontStyle != UNSET || textAttributes.mFontWeight != UNSET || textAttributes.mFontFamily != null) { @@ -163,23 +163,14 @@ public class TextLayoutManager { buildSpannedFromShadowNode(context, fragments, sb, ops); - // TODO: add support for AllowScaling in C++ -// if (textShadowNode.mFontSize == UNSET) { -// int defaultFontSize = -// textShadowNode.mAllowFontScaling -// ? (int) Math.ceil(PixelUtil.toPixelFromSP(ViewDefaults.FONT_SIZE_SP)) -// : (int) Math.ceil(PixelUtil.toPixelFromDIP(ViewDefaults.FONT_SIZE_SP)); -// -// ops.add(new SetSpanOperation(0, sb.length(), new AbsoluteSizeSpan(defaultFontSize))); -// } -// +// TODO T31905686: add support for inline Images // textShadowNode.mContainsImages = false; // textShadowNode.mHeightOfTallestInlineImage = Float.NaN; // While setting the Spans on the final text, we also check whether any of them are images. int priority = 0; for (SetSpanOperation op : ops) { -// TODO: add support for TextInlineImage in C++ +// TODO T31905686: add support for TextInlineImage in C++ // if (op.what instanceof TextInlineImageSpan) { // int height = ((TextInlineImageSpan) op.what).getHeight(); // textShadowNode.mContainsImages = true; diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaAlign.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaAlign.java index 6a84ffaf894..94878fd789b 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaAlign.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaAlign.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfig.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfig.java index b8312bd4588..40de7d2cdcc 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfig.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. @@ -8,6 +8,7 @@ package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.soloader.SoLoader; @DoNotStrip public class YogaConfig { @@ -15,7 +16,7 @@ public class YogaConfig { public static int SPACING_TYPE = 1; static { - YogaJNI.init(); + SoLoader.loadLibrary("yoga"); } long mNativePointer; diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaConstants.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaConstants.java index 10f152d48b0..61e212efea8 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaConstants.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaConstants.java @@ -35,4 +35,8 @@ public class YogaConstants { public static boolean isUndefined(YogaValue value) { return value.unit == YogaUnit.UNDEFINED; } + + public static float getUndefined() { + return UNDEFINED; + } } diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaDimension.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaDimension.java index 42f1ce76707..2ef2772689b 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaDimension.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaDimension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaDirection.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaDirection.java index 78d377d833f..6a5017cfed7 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaDirection.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaDirection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaDisplay.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaDisplay.java index df7bff2fafd..3ba4d56c8c0 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaDisplay.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaDisplay.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaEdge.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaEdge.java index 8d7d1b685f6..80a783e7daf 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaEdge.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaEdge.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaExperimentalFeature.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaExperimentalFeature.java index 82f2db94a33..33a8389dbf3 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaExperimentalFeature.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaExperimentalFeature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaFlexDirection.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaFlexDirection.java index 3d31caa219e..c5f9ab5dae6 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaFlexDirection.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaFlexDirection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaJNI.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaJNI.java deleted file mode 100644 index fb0138045dd..00000000000 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaJNI.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. - * - */ -package com.facebook.yoga; - -import com.facebook.soloader.SoLoader; - -public class YogaJNI { - private static boolean isInitialized = false; - - // Known constants. 1-3 used in previous experiments. Do not reuse. - public static int JNI_FAST_CALLS = 4; - - // set before loading any other Yoga code - public static boolean useFastCall = false; - - private static native void jni_bindNativeMethods(boolean useFastCall); - - static synchronized boolean init() { - if (!isInitialized) { - isInitialized = true; - SoLoader.loadLibrary("yoga"); - jni_bindNativeMethods(useFastCall); - return true; - } - return false; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaJustify.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaJustify.java index 521dad28862..6b1b83f5b2d 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaJustify.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaJustify.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaLogLevel.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaLogLevel.java index e6a9498e9a7..29476d67c54 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaLogLevel.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaLogLevel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaMeasureMode.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaMeasureMode.java index 7b24c26f963..24399f6288c 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaMeasureMode.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaMeasureMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java index 282931dc8a4..7dd2694745f 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. @@ -8,6 +8,7 @@ package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.soloader.SoLoader; import java.util.ArrayList; import java.util.List; import javax.annotation.Nullable; @@ -16,7 +17,7 @@ import javax.annotation.Nullable; public class YogaNode implements Cloneable { static { - YogaJNI.init(); + SoLoader.loadLibrary("yoga"); } /** @@ -159,6 +160,7 @@ public class YogaNode implements Cloneable { } private static native void jni_YGNodeInsertChild(long nativePointer, long childPointer, int index); + public void addChildAt(YogaNode child, int i) { if (child.mOwner != null) { throw new IllegalStateException("Child already has a parent, it must be removed first."); @@ -183,6 +185,18 @@ public class YogaNode implements Cloneable { jni_YGNodeInsertSharedChild(mNativePointer, child.mNativePointer, i); } + private static native void jni_YGNodeSetIsReferenceBaseline(long nativePointer, boolean isReferenceBaseline); + + public void setIsReferenceBaseline(boolean isReferenceBaseline) { + jni_YGNodeSetIsReferenceBaseline(mNativePointer, isReferenceBaseline); + } + + private static native boolean jni_YGNodeIsReferenceBaseline(long nativePointer); + + public boolean isReferenceBaseline() { + return jni_YGNodeIsReferenceBaseline(mNativePointer); + } + private static native void jni_YGNodeSetOwner(long nativePointer, long newOwnerNativePointer); private native long jni_YGNodeClone(long nativePointer, Object newNode); diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeType.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeType.java index c9dd58de491..28db7f1ff0a 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeType.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaOverflow.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaOverflow.java index 3003451f84e..8dec3649e05 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaOverflow.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaOverflow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaPositionType.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaPositionType.java index ecdcb950177..0392e6f8541 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaPositionType.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaPositionType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaPrintOptions.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaPrintOptions.java index 226c1a2a68d..fb1a6b1434b 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaPrintOptions.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaPrintOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaUnit.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaUnit.java index 76c406769f7..b9a98e95491 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaUnit.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaUnit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaValue.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaValue.java index 1eeb0f03f46..947cfcc7c72 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaValue.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaWrap.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaWrap.java index 170019738af..45f1220cb64 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaWrap.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaWrap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp b/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp index d785465690f..8c6536d49ba 100644 --- a/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp +++ b/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp @@ -371,6 +371,17 @@ void jni_YGNodeRemoveChild(jlong nativePointer, jlong childPointer) { _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer)); } +void jni_YGNodeSetIsReferenceBaseline( + jlong nativePointer, + jboolean isReferenceBaseline) { + YGNodeSetIsReferenceBaseline( + _jlong2YGNodeRef(nativePointer), isReferenceBaseline); +} + +jboolean jni_YGNodeIsReferenceBaseline(jlong nativePointer) { + return YGNodeIsReferenceBaseline(_jlong2YGNodeRef(nativePointer)); +} + void jni_YGNodeCalculateLayout( alias_ref, jlong nativePointer, @@ -647,130 +658,112 @@ jint jni_YGNodeGetInstanceCount() { } #define YGMakeNativeMethod(name) makeNativeMethod(#name, name) -#define YGRealMakeCriticalNativeMethod(name) \ - makeCriticalNativeMethod(#name, name) -#define YGWrapCriticalNativeMethodForRegularCall(name) \ - makeNativeMethod( \ - #name, \ - ::facebook::jni::detail::CriticalMethod::call<&name>) - -#define YGRegisterNatives(YGMakeCriticalNativeMethod) \ - registerNatives( \ - "com/facebook/yoga/YogaNode", \ - { \ - YGMakeNativeMethod(jni_YGNodeNew), \ - YGMakeNativeMethod(jni_YGNodeNewWithConfig), \ - YGMakeCriticalNativeMethod(jni_YGNodeFree), \ - YGMakeCriticalNativeMethod(jni_YGNodeReset), \ - YGMakeCriticalNativeMethod(jni_YGNodeClearChildren), \ - YGMakeCriticalNativeMethod(jni_YGNodeInsertChild), \ - YGMakeCriticalNativeMethod(jni_YGNodeInsertSharedChild), \ - YGMakeCriticalNativeMethod(jni_YGNodeRemoveChild), \ - YGMakeNativeMethod(jni_YGNodeCalculateLayout), \ - YGMakeCriticalNativeMethod(jni_YGNodeMarkDirty), \ - YGMakeCriticalNativeMethod( \ - jni_YGNodeMarkDirtyAndPropogateToDescendants), \ - YGMakeCriticalNativeMethod(jni_YGNodeIsDirty), \ - YGMakeCriticalNativeMethod(jni_YGNodeSetHasMeasureFunc), \ - YGMakeCriticalNativeMethod(jni_YGNodeSetHasBaselineFunc), \ - YGMakeCriticalNativeMethod(jni_YGNodeCopyStyle), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetDirection), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetDirection), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexDirection), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexDirection), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetJustifyContent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetJustifyContent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignItems), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignItems), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignSelf), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignSelf), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignContent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignContent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetPositionType), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPositionType), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexWrap), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetOverflow), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetOverflow), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetDisplay), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetDisplay), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlex), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexGrow), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexGrow), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexShrink), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexShrink), \ - YGMakeNativeMethod(jni_YGNodeStyleGetFlexBasis), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasis), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasisPercent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasisAuto), \ - YGMakeNativeMethod(jni_YGNodeStyleGetMargin), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMargin), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMarginPercent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMarginAuto), \ - YGMakeNativeMethod(jni_YGNodeStyleGetPadding), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPadding), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPaddingPercent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetBorder), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetBorder), \ - YGMakeNativeMethod(jni_YGNodeStyleGetPosition), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPosition), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPositionPercent), \ - YGMakeNativeMethod(jni_YGNodeStyleGetWidth), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidth), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidthPercent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidthAuto), \ - YGMakeNativeMethod(jni_YGNodeStyleGetHeight), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeight), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeightPercent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeightAuto), \ - YGMakeNativeMethod(jni_YGNodeStyleGetMinWidth), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinWidth), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinWidthPercent), \ - YGMakeNativeMethod(jni_YGNodeStyleGetMinHeight), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinHeight), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinHeightPercent), \ - YGMakeNativeMethod(jni_YGNodeStyleGetMaxWidth), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxWidth), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxWidthPercent), \ - YGMakeNativeMethod(jni_YGNodeStyleGetMaxHeight), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxHeight), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxHeightPercent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAspectRatio), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAspectRatio), \ - YGMakeCriticalNativeMethod(jni_YGNodeGetInstanceCount), \ - YGMakeCriticalNativeMethod(jni_YGNodePrint), \ - YGMakeNativeMethod(jni_YGNodeClone), \ - YGMakeCriticalNativeMethod(jni_YGNodeSetOwner), \ - }); \ - registerNatives( \ - "com/facebook/yoga/YogaConfig", \ - { \ - YGMakeNativeMethod(jni_YGConfigNew), \ - YGMakeNativeMethod(jni_YGConfigFree), \ - YGMakeNativeMethod(jni_YGConfigSetExperimentalFeatureEnabled), \ - YGMakeNativeMethod(jni_YGConfigSetUseWebDefaults), \ - YGMakeNativeMethod(jni_YGConfigSetPrintTreeFlag), \ - YGMakeNativeMethod(jni_YGConfigSetPointScaleFactor), \ - YGMakeNativeMethod(jni_YGConfigSetUseLegacyStretchBehaviour), \ - YGMakeNativeMethod(jni_YGConfigSetLogger), \ - YGMakeNativeMethod(jni_YGConfigSetHasCloneNodeFunc), \ - YGMakeNativeMethod( \ - jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour), \ - }); - -void jni_bindNativeMethods(alias_ref, jboolean useFastCall) { - if (useFastCall) { - YGRegisterNatives(YGRealMakeCriticalNativeMethod); - } else { - YGRegisterNatives(YGWrapCriticalNativeMethodForRegularCall); - } -} +#define YGMakeCriticalNativeMethod(name) makeCriticalNativeMethod(#name, name) jint JNI_OnLoad(JavaVM* vm, void*) { return initialize(vm, [] { registerNatives( - "com/facebook/yoga/YogaJNI", + "com/facebook/yoga/YogaNode", { - YGMakeNativeMethod(jni_bindNativeMethods), + YGMakeNativeMethod(jni_YGNodeNew), + YGMakeNativeMethod(jni_YGNodeNewWithConfig), + YGMakeCriticalNativeMethod(jni_YGNodeFree), + YGMakeCriticalNativeMethod(jni_YGNodeReset), + YGMakeCriticalNativeMethod(jni_YGNodeClearChildren), + YGMakeCriticalNativeMethod(jni_YGNodeInsertChild), + YGMakeCriticalNativeMethod(jni_YGNodeInsertSharedChild), + YGMakeCriticalNativeMethod(jni_YGNodeRemoveChild), + YGMakeCriticalNativeMethod(jni_YGNodeSetIsReferenceBaseline), + YGMakeCriticalNativeMethod(jni_YGNodeIsReferenceBaseline), + YGMakeNativeMethod(jni_YGNodeCalculateLayout), + YGMakeCriticalNativeMethod(jni_YGNodeMarkDirty), + YGMakeCriticalNativeMethod( + jni_YGNodeMarkDirtyAndPropogateToDescendants), + YGMakeCriticalNativeMethod(jni_YGNodeIsDirty), + YGMakeCriticalNativeMethod(jni_YGNodeSetHasMeasureFunc), + YGMakeCriticalNativeMethod(jni_YGNodeSetHasBaselineFunc), + YGMakeCriticalNativeMethod(jni_YGNodeCopyStyle), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetDirection), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetDirection), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexDirection), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexDirection), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetJustifyContent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetJustifyContent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignItems), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignItems), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignSelf), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignSelf), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignContent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignContent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetPositionType), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPositionType), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexWrap), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetOverflow), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetOverflow), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetDisplay), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetDisplay), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlex), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexGrow), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexGrow), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexShrink), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexShrink), + YGMakeNativeMethod(jni_YGNodeStyleGetFlexBasis), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasis), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasisPercent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasisAuto), + YGMakeNativeMethod(jni_YGNodeStyleGetMargin), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMargin), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMarginPercent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMarginAuto), + YGMakeNativeMethod(jni_YGNodeStyleGetPadding), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPadding), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPaddingPercent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetBorder), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetBorder), + YGMakeNativeMethod(jni_YGNodeStyleGetPosition), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPosition), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPositionPercent), + YGMakeNativeMethod(jni_YGNodeStyleGetWidth), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidth), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidthPercent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidthAuto), + YGMakeNativeMethod(jni_YGNodeStyleGetHeight), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeight), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeightPercent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeightAuto), + YGMakeNativeMethod(jni_YGNodeStyleGetMinWidth), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinWidth), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinWidthPercent), + YGMakeNativeMethod(jni_YGNodeStyleGetMinHeight), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinHeight), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinHeightPercent), + YGMakeNativeMethod(jni_YGNodeStyleGetMaxWidth), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxWidth), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxWidthPercent), + YGMakeNativeMethod(jni_YGNodeStyleGetMaxHeight), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxHeight), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxHeightPercent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAspectRatio), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAspectRatio), + YGMakeCriticalNativeMethod(jni_YGNodeGetInstanceCount), + YGMakeCriticalNativeMethod(jni_YGNodePrint), + YGMakeNativeMethod(jni_YGNodeClone), + YGMakeCriticalNativeMethod(jni_YGNodeSetOwner), + }); + registerNatives( + "com/facebook/yoga/YogaConfig", + { + YGMakeNativeMethod(jni_YGConfigNew), + YGMakeNativeMethod(jni_YGConfigFree), + YGMakeNativeMethod(jni_YGConfigSetExperimentalFeatureEnabled), + YGMakeNativeMethod(jni_YGConfigSetUseWebDefaults), + YGMakeNativeMethod(jni_YGConfigSetPrintTreeFlag), + YGMakeNativeMethod(jni_YGConfigSetPointScaleFactor), + YGMakeNativeMethod(jni_YGConfigSetUseLegacyStretchBehaviour), + YGMakeNativeMethod(jni_YGConfigSetLogger), + YGMakeNativeMethod(jni_YGConfigSetHasCloneNodeFunc), + YGMakeNativeMethod( + jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour), }); }); } diff --git a/ReactAndroid/src/main/jniLibs/arm64-v8a/libicu_common.so b/ReactAndroid/src/main/jniLibs/arm64-v8a/libicu_common.so new file mode 100644 index 00000000000..6a089dfe7f3 Binary files /dev/null and b/ReactAndroid/src/main/jniLibs/arm64-v8a/libicu_common.so differ diff --git a/ReactAndroid/src/main/jniLibs/x86_64/libicu_common.so b/ReactAndroid/src/main/jniLibs/x86_64/libicu_common.so new file mode 100644 index 00000000000..e6e8acf7952 Binary files /dev/null and b/ReactAndroid/src/main/jniLibs/x86_64/libicu_common.so differ diff --git a/ReactAndroid/src/main/third-party/android/support/BUCK b/ReactAndroid/src/main/third-party/android/support/BUCK index 5636024b963..2c67956ac8e 100644 --- a/ReactAndroid/src/main/third-party/android/support/BUCK +++ b/ReactAndroid/src/main/third-party/android/support/BUCK @@ -1,5 +1,5 @@ load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_library", "rn_android_resource", "rn_prebuilt_jar") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_library") rn_android_library( name = "support-v4", diff --git a/ReactAndroid/src/test/java/com/facebook/react/uimanager/layoutanimation/BUCK b/ReactAndroid/src/test/java/com/facebook/react/uimanager/layoutanimation/BUCK index 0a10da27bc1..6c791141d54 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/uimanager/layoutanimation/BUCK +++ b/ReactAndroid/src/test/java/com/facebook/react/uimanager/layoutanimation/BUCK @@ -1,4 +1,4 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_target", "react_native_tests_target", "rn_robolectric_test") +load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_target", "rn_robolectric_test") rn_robolectric_test( name = "layoutanimation", diff --git a/ReactCommon/cxxreact/CxxModule.h b/ReactCommon/cxxreact/CxxModule.h index f253c108c2e..5a4d330e67f 100644 --- a/ReactCommon/cxxreact/CxxModule.h +++ b/ReactCommon/cxxreact/CxxModule.h @@ -67,13 +67,14 @@ public: std::string name; size_t callbacks; + bool isPromise; std::function func; std::function syncFunc; const char *getType() { assert(func || syncFunc); - return func ? (callbacks == 2 ? "promise" : "async") : "sync"; + return func ? (isPromise ? "promise" : "async") : "sync"; } // std::function/lambda ctors @@ -82,24 +83,36 @@ public: std::function&& afunc) : name(std::move(aname)) , callbacks(0) + , isPromise(false) , func(std::bind(std::move(afunc))) {} Method(std::string aname, std::function&& afunc) : name(std::move(aname)) , callbacks(0) - , func(std::bind(std::move(afunc), _1)) {} + , isPromise(false) + , func(std::bind(std::move(afunc), std::placeholders::_1)) {} Method(std::string aname, std::function&& afunc) : name(std::move(aname)) , callbacks(1) - , func(std::bind(std::move(afunc), _1, _2)) {} + , isPromise(false) + , func(std::bind(std::move(afunc), std::placeholders::_1, std::placeholders::_2)) {} Method(std::string aname, std::function&& afunc) : name(std::move(aname)) , callbacks(2) + , isPromise(true) + , func(std::move(afunc)) {} + + Method(std::string aname, + std::function&& afunc, + AsyncTagType) + : name(std::move(aname)) + , callbacks(2) + , isPromise(false) , func(std::move(afunc)) {} // method pointer ctors @@ -108,25 +121,39 @@ public: Method(std::string aname, T* t, void (T::*method)()) : name(std::move(aname)) , callbacks(0) + , isPromise(false) , func(std::bind(method, t)) {} template Method(std::string aname, T* t, void (T::*method)(folly::dynamic)) : name(std::move(aname)) , callbacks(0) - , func(std::bind(method, t, _1)) {} + , isPromise(false) + , func(std::bind(method, t, std::placeholders::_1)) {} template Method(std::string aname, T* t, void (T::*method)(folly::dynamic, Callback)) : name(std::move(aname)) , callbacks(1) - , func(std::bind(method, t, _1, _2)) {} + , isPromise(false) + , func(std::bind(method, t, std::placeholders::_1, std::placeholders::_2)) {} template Method(std::string aname, T* t, void (T::*method)(folly::dynamic, Callback, Callback)) : name(std::move(aname)) , callbacks(2) - , func(std::bind(method, t, _1, _2, _3)) {} + , isPromise(true) + , func(std::bind(method, t, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)) {} + + template + Method(std::string aname, + T* t, + void (T::*method)(folly::dynamic, Callback, Callback), + AsyncTagType) + : name(std::move(aname)) + , callbacks(2) + , isPromise(false) + , func(std::bind(method, t, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)) {} // sync std::function/lambda ctors @@ -139,6 +166,7 @@ public: SyncTagType) : name(std::move(aname)) , callbacks(0) + , isPromise(false) , syncFunc([afunc=std::move(afunc)] (const folly::dynamic&) { return afunc(); }) {} @@ -148,6 +176,7 @@ public: SyncTagType) : name(std::move(aname)) , callbacks(0) + , isPromise(false) , syncFunc(std::move(afunc)) {} }; diff --git a/ReactCommon/cxxreact/CxxNativeModule.cpp b/ReactCommon/cxxreact/CxxNativeModule.cpp index cca885fc576..2b674c0c186 100644 --- a/ReactCommon/cxxreact/CxxNativeModule.cpp +++ b/ReactCommon/cxxreact/CxxNativeModule.cpp @@ -136,6 +136,8 @@ void CxxNativeModule::invoke(unsigned int reactMethodId, folly::dynamic&& params if (callId != -1) { fbsystrace_end_async_flow(TRACE_TAG_REACT_APPS, "native", callId); } + #else + (void)(callId); #endif SystraceSection s(method.name.c_str()); try { diff --git a/ReactCommon/cxxreact/MethodCall.cpp b/ReactCommon/cxxreact/MethodCall.cpp index a83c2955fe5..79c7f49a259 100644 --- a/ReactCommon/cxxreact/MethodCall.cpp +++ b/ReactCommon/cxxreact/MethodCall.cpp @@ -18,7 +18,7 @@ namespace react { static const char *errorPrefix = "Malformed calls from JS: "; -std::vector parseMethodCalls(folly::dynamic&& jsonData) throw(std::invalid_argument) { +std::vector parseMethodCalls(folly::dynamic&& jsonData) { if (jsonData.isNull()) { return {}; } @@ -77,4 +77,3 @@ std::vector parseMethodCalls(folly::dynamic&& jsonData) throw(std::i } }} - diff --git a/ReactCommon/cxxreact/MethodCall.h b/ReactCommon/cxxreact/MethodCall.h index b6ed095fb6c..be843b9abd2 100644 --- a/ReactCommon/cxxreact/MethodCall.h +++ b/ReactCommon/cxxreact/MethodCall.h @@ -27,6 +27,7 @@ struct MethodCall { , callId(cid) {} }; -std::vector parseMethodCalls(folly::dynamic&& calls) throw(std::invalid_argument); +/// \throws std::invalid_argument +std::vector parseMethodCalls(folly::dynamic&& calls); } } diff --git a/ReactCommon/cxxreact/ModuleRegistry.cpp b/ReactCommon/cxxreact/ModuleRegistry.cpp index 0e3044ce5a2..1d3ba722b8d 100644 --- a/ReactCommon/cxxreact/ModuleRegistry.cpp +++ b/ReactCommon/cxxreact/ModuleRegistry.cpp @@ -90,13 +90,13 @@ folly::Optional ModuleRegistry::getConfig(const std::string& name) if (it == modulesByName_.end()) { if (unknownModules_.find(name) != unknownModules_.end()) { - return nullptr; + return folly::none; } if (!moduleNotFoundCallback_ || !moduleNotFoundCallback_(name) || (it = modulesByName_.find(name)) == modulesByName_.end()) { unknownModules_.insert(name); - return nullptr; + return folly::none; } } size_t index = it->second; @@ -143,7 +143,7 @@ folly::Optional ModuleRegistry::getConfig(const std::string& name) if (config.size() == 2 && config[1].empty()) { // no constants or methods - return nullptr; + return folly::none; } else { return ModuleConfig{index, config}; } diff --git a/ReactCommon/cxxreact/NativeToJsBridge.cpp b/ReactCommon/cxxreact/NativeToJsBridge.cpp index cfd5634f44c..a9b7161df73 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.cpp +++ b/ReactCommon/cxxreact/NativeToJsBridge.cpp @@ -161,6 +161,8 @@ void NativeToJsBridge::callFunction( "JSCall", systraceCookie); SystraceSection s("NativeToJsBridge::callFunction", "module", module, "method", method); + #else + (void)(systraceCookie); #endif // This is safe because we are running on the executor's thread: it won't // destruct until after it's been unregistered (which we check above) and @@ -191,6 +193,8 @@ void NativeToJsBridge::invokeCallback(double callbackId, folly::dynamic&& argume "", systraceCookie); SystraceSection s("NativeToJsBridge::invokeCallback"); + #else + (void)(systraceCookie); #endif executor->invokeCallback(callbackId, arguments); }); diff --git a/ReactCommon/cxxreact/RecoverableError.h b/ReactCommon/cxxreact/RecoverableError.h index 5aec7101c38..2ecc64bfb4a 100644 --- a/ReactCommon/cxxreact/RecoverableError.h +++ b/ReactCommon/cxxreact/RecoverableError.h @@ -23,7 +23,7 @@ struct RecoverableError : public std::exception { : m_what { "facebook::react::Recoverable: " + what_ } {} - virtual const char* what() const throw() override { return m_what.c_str(); } + virtual const char* what() const noexcept override { return m_what.c_str(); } /** * runRethrowingAsRecoverable diff --git a/ReactCommon/cxxreact/SampleCxxModule.cpp b/ReactCommon/cxxreact/SampleCxxModule.cpp index d0b3199f869..1862c0f08da 100644 --- a/ReactCommon/cxxreact/SampleCxxModule.cpp +++ b/ReactCommon/cxxreact/SampleCxxModule.cpp @@ -114,6 +114,25 @@ auto SampleCxxModule::getMethods() -> std::vector { sample_->hello(); return nullptr; }, SyncTag), + Method("addIfPositiveAsPromise", [](dynamic args, Callback cb, Callback cbError) { + auto a = jsArgAsDouble(args, 0); + auto b = jsArgAsDouble(args, 1); + if (a < 0 || b < 0) { + cbError({"Negative number!"}); + } else { + cb({a + b}); + } + }), + Method("addIfPositiveAsAsync", [](dynamic args, Callback cb, Callback cbError) { + auto a = jsArgAsDouble(args, 0); + auto b = jsArgAsDouble(args, 1); + if (a < 0 || b < 0) { + cbError({"Negative number!"}); + } else { + cb({a + b}); + } + }, AsyncTag), + }; } diff --git a/ReactCommon/fabric/attributedstring/AttributedString.cpp b/ReactCommon/fabric/attributedstring/AttributedString.cpp index 630fb98f537..e2b31345016 100644 --- a/ReactCommon/fabric/attributedstring/AttributedString.cpp +++ b/ReactCommon/fabric/attributedstring/AttributedString.cpp @@ -73,7 +73,7 @@ std::string AttributedString::getString() const { } bool AttributedString::operator==(const AttributedString &rhs) const { - return fragments_ != rhs.fragments_; + return fragments_ == rhs.fragments_; } bool AttributedString::operator!=(const AttributedString &rhs) const { diff --git a/ReactCommon/fabric/attributedstring/TextAttributes.cpp b/ReactCommon/fabric/attributedstring/TextAttributes.cpp index 95f0940e30f..480dd012eb4 100644 --- a/ReactCommon/fabric/attributedstring/TextAttributes.cpp +++ b/ReactCommon/fabric/attributedstring/TextAttributes.cpp @@ -158,7 +158,7 @@ TextAttributes TextAttributes::defaultTextAttributes() { // Non-obvious (can be different among platforms) default text attributes. textAttributes.foregroundColor = blackColor(); textAttributes.backgroundColor = clearColor(); - textAttributes.fontSize = 12.0; + textAttributes.fontSize = 14.0; return textAttributes; }(); return textAttributes; diff --git a/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.cpp b/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.cpp index 245dcee932f..d1eba803342 100644 --- a/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.cpp +++ b/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.cpp @@ -32,11 +32,17 @@ void ParagraphShadowNode::setTextLayoutManager( textLayoutManager_ = textLayoutManager; } -void ParagraphShadowNode::updateLocalData() { +void ParagraphShadowNode::updateLocalDataIfNeeded() { ensureUnsealed(); + auto attributedString = getAttributedString(); + auto currentLocalData = std::static_pointer_cast(getLocalData()); + if (currentLocalData && currentLocalData->getAttributedString() == attributedString) { + return; + } + auto localData = std::make_shared(); - localData->setAttributedString(getAttributedString()); + localData->setAttributedString(std::move(attributedString)); localData->setTextLayoutManager(textLayoutManager_); setLocalData(localData); } @@ -52,7 +58,7 @@ Size ParagraphShadowNode::measure(LayoutConstraints layoutConstraints) const { } void ParagraphShadowNode::layout(LayoutContext layoutContext) { - updateLocalData(); + updateLocalDataIfNeeded(); ConcreteViewShadowNode::layout(layoutContext); } diff --git a/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.h b/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.h index c1d1f14dfbb..3eb68ae14ca 100644 --- a/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.h +++ b/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.h @@ -58,7 +58,7 @@ class ParagraphShadowNode : public ConcreteViewShadowNode< * Creates a `LocalData` object (with `AttributedText` and * `TextLayoutManager`) if needed. */ - void updateLocalData(); + void updateLocalDataIfNeeded(); SharedTextLayoutManager textLayoutManager_; diff --git a/ReactCommon/fabric/core/layout/LayoutableShadowNode.cpp b/ReactCommon/fabric/core/layout/LayoutableShadowNode.cpp index 61ae72fcc63..f502fd4d0ef 100644 --- a/ReactCommon/fabric/core/layout/LayoutableShadowNode.cpp +++ b/ReactCommon/fabric/core/layout/LayoutableShadowNode.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,35 @@ bool LayoutableShadowNode::LayoutableShadowNode::isLayoutOnly() const { return false; } +LayoutMetrics LayoutableShadowNode::getRelativeLayoutMetrics( + const LayoutableShadowNode &ancestorLayoutableShadowNode) const { + std::vector> ancestors; + + auto &ancestorShadowNode = + dynamic_cast(ancestorLayoutableShadowNode); + auto &shadowNode = dynamic_cast(*this); + + if (!shadowNode.constructAncestorPath(ancestorShadowNode, ancestors)) { + return EmptyLayoutMetrics; + } + + auto layoutMetrics = getLayoutMetrics(); + + for (const auto ¤tShadowNode : ancestors) { + auto layoutableCurrentShadowNode = + dynamic_cast(¤tShadowNode.get()); + + if (!layoutableCurrentShadowNode) { + return EmptyLayoutMetrics; + } + + layoutMetrics.frame.origin += + layoutableCurrentShadowNode->getLayoutMetrics().frame.origin; + } + + return layoutMetrics; +} + void LayoutableShadowNode::cleanLayout() { isLayoutClean_ = true; } diff --git a/ReactCommon/fabric/core/layout/LayoutableShadowNode.h b/ReactCommon/fabric/core/layout/LayoutableShadowNode.h index 74c82a2ce45..58b767443ea 100644 --- a/ReactCommon/fabric/core/layout/LayoutableShadowNode.h +++ b/ReactCommon/fabric/core/layout/LayoutableShadowNode.h @@ -59,6 +59,12 @@ class LayoutableShadowNode : public virtual Sealable { */ virtual bool isLayoutOnly() const; + /* + * Returns layout metrics relatively to the given ancestor node. + */ + LayoutMetrics getRelativeLayoutMetrics( + const LayoutableShadowNode &ancestorLayoutableShadowNode) const; + protected: /* * Clean or Dirty layout state: diff --git a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp index 1a282dd6e98..8855179b2bd 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp +++ b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp @@ -146,6 +146,25 @@ void ShadowNode::cloneChildrenIfShared() { children_ = std::make_shared(*children_); } +bool ShadowNode::constructAncestorPath( + const ShadowNode &ancestorShadowNode, + std::vector> &ancestors) const { + // Note: We have a decent idea of how to make it reasonable performant. + // This is not implemented yet though. See T36620537 for more details. + if (this == &ancestorShadowNode) { + return true; + } + + for (const auto &childShadowNode : *ancestorShadowNode.children_) { + if (constructAncestorPath(*childShadowNode, ancestors)) { + ancestors.push_back(std::ref(ancestorShadowNode)); + return true; + } + } + + return false; +} + #pragma mark - DebugStringConvertible #if RN_DEBUG_STRING_CONVERTIBLE diff --git a/ReactCommon/fabric/core/shadownode/ShadowNode.h b/ReactCommon/fabric/core/shadownode/ShadowNode.h index aa15621449c..17dbb64bfbe 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNode.h +++ b/ReactCommon/fabric/core/shadownode/ShadowNode.h @@ -101,6 +101,21 @@ class ShadowNode : public virtual Sealable, */ void setLocalData(const SharedLocalData &localData); + /* + * Forms a list of all ancestors of the node relative to the given ancestor. + * The list starts from the parent node and ends with the given ancestor node. + * Returns `true` if successful, `false` otherwise. + * Thread-safe if the subtree is immutable. + * The theoretical complexity of this algorithm is `O(n)`. Use it wisely. + * The particular implementation can use some tricks to mitigate the + * complexity problem up to `0(ln(n))` but this is not guaranteed. + * Particular consumers should use appropriate cache techniques based on + * `childIndex` and `nodeId` tracking. + */ + bool constructAncestorPath( + const ShadowNode &rootShadowNode, + std::vector> &ancestors) const; + #pragma mark - DebugStringConvertible #if RN_DEBUG_STRING_CONVERTIBLE diff --git a/ReactCommon/fabric/core/tests/ShadowNodeTest.cpp b/ReactCommon/fabric/core/tests/ShadowNodeTest.cpp index 45311bbfa27..cac7546d820 100644 --- a/ReactCommon/fabric/core/tests/ShadowNodeTest.cpp +++ b/ReactCommon/fabric/core/tests/ShadowNodeTest.cpp @@ -202,3 +202,78 @@ TEST(ShadowNodeTest, handleLocalData) { secondNode->sealRecursive(); ASSERT_ANY_THROW(secondNode->setLocalData(localDataOver9000)); } + +TEST(ShadowNodeTest, handleBacktracking) { + /* + * The structure: + * + * + * + * + * + * + * + * + * + */ + + auto props = std::make_shared(); + + auto nodeAA = std::make_shared( + ShadowNodeFragment{ + .props = props, + .children = ShadowNode::emptySharedShadowNodeSharedList()}, + nullptr); + + auto nodeABA = std::make_shared( + ShadowNodeFragment{ + .props = props, + .children = ShadowNode::emptySharedShadowNodeSharedList()}, + nullptr); + auto nodeABB = std::make_shared( + ShadowNodeFragment{ + .props = props, + .children = ShadowNode::emptySharedShadowNodeSharedList()}, + nullptr); + auto nodeABC = std::make_shared( + ShadowNodeFragment{ + .props = props, + .children = ShadowNode::emptySharedShadowNodeSharedList()}, + nullptr); + + auto nodeABChildren = std::make_shared>( + std::vector{nodeABA, nodeABB, nodeABC}); + auto nodeAB = std::make_shared( + ShadowNodeFragment{.props = props, .children = nodeABChildren}, nullptr); + + auto nodeAC = std::make_shared( + ShadowNodeFragment{ + .props = props, + .children = ShadowNode::emptySharedShadowNodeSharedList()}, + nullptr); + + auto nodeAChildren = std::make_shared>( + std::vector{nodeAA, nodeAB, nodeAC}); + auto nodeA = std::make_shared( + ShadowNodeFragment{.props = props, .children = nodeAChildren}, nullptr); + + auto nodeZ = std::make_shared( + ShadowNodeFragment{ + .props = props, + .children = ShadowNode::emptySharedShadowNodeSharedList()}, + nullptr); + + std::vector> ancestors = {}; + + // Negative case: + auto success = nodeZ->constructAncestorPath(*nodeA, ancestors); + ASSERT_FALSE(success); + ASSERT_EQ(ancestors.size(), 0); + + // Positive case: + success = nodeABC->constructAncestorPath(*nodeA, ancestors); + ASSERT_TRUE(success); + ASSERT_EQ(ancestors.size(), 2); + ASSERT_EQ(&ancestors[0].get(), nodeAB.get()); + ASSERT_EQ(&ancestors[1].get(), nodeA.get()); +} diff --git a/ReactCommon/fabric/events/EventBeat.h b/ReactCommon/fabric/events/EventBeat.h index 2f86600a433..448da6dee2a 100644 --- a/ReactCommon/fabric/events/EventBeat.h +++ b/ReactCommon/fabric/events/EventBeat.h @@ -58,13 +58,13 @@ class EventBeat { */ void setFailCallback(const FailCallback &failCallback); - protected: /* * Should be used by sublasses to send a beat. * Receiver might ignore the call if a beat was not requested. */ void beat(jsi::Runtime &runtime) const; + protected: BeatCallback beatCallback_; FailCallback failCallback_; mutable std::atomic isRequested_{false}; diff --git a/ReactCommon/fabric/textlayoutmanager/platform/android/TextLayoutManager.cpp b/ReactCommon/fabric/textlayoutmanager/platform/android/TextLayoutManager.cpp index 22354e2eb8d..251b81314bc 100644 --- a/ReactCommon/fabric/textlayoutmanager/platform/android/TextLayoutManager.cpp +++ b/ReactCommon/fabric/textlayoutmanager/platform/android/TextLayoutManager.cpp @@ -38,10 +38,16 @@ Size TextLayoutManager::measure( ReadableNativeMap::javaobject, ReadableNativeMap::javaobject, jint, + jint, + jint, jint)>("measure"); - int width = (int)layoutConstraints.maximumSize.width; - int height = (int)layoutConstraints.maximumSize.height; + auto minimumSize = layoutConstraints.minimumSize; + auto maximumSize = layoutConstraints.maximumSize; + int minWidth = (int)minimumSize.width; + int minHeight = (int)minimumSize.height; + int maxWidth = (int)maximumSize.width; + int maxHeight = (int)maximumSize.height; local_ref componentName = make_jstring("RCTText"); auto values = measure( fabricUIManager, @@ -49,14 +55,16 @@ Size TextLayoutManager::measure( componentName.get(), ReadableNativeMap::newObjectCxxArgs(toDynamic(attributedString)).get(), ReadableNativeMap::newObjectCxxArgs(toDynamic(paragraphAttributes)).get(), - width, - height); + minWidth, + maxWidth, + minHeight, + maxHeight); std::vector indices; indices.resize(values->size()); values->getRegion(0, values->size(), indices.data()); - return {(float)indices[0], (float)indices[1]}; + return {indices[0], indices[1]}; } } // namespace react diff --git a/ReactCommon/fabric/uimanager/Scheduler.cpp b/ReactCommon/fabric/uimanager/Scheduler.cpp index 6ad5d946cd1..478f52def84 100644 --- a/ReactCommon/fabric/uimanager/Scheduler.cpp +++ b/ReactCommon/fabric/uimanager/Scheduler.cpp @@ -49,6 +49,7 @@ Scheduler::Scheduler(const SharedContextContainer &contextContainer) eventDispatcher, contextContainer); uiManagerRef.setDelegate(this); + uiManagerRef.setShadowTreeRegistry(&shadowTreeRegistry_); uiManagerRef.setComponentDescriptorRegistry(componentDescriptorRegistry_); runtimeExecutor_([=](jsi::Runtime &runtime) { @@ -66,12 +67,11 @@ void Scheduler::startSurface( const folly::dynamic &initialProps, const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const { - std::lock_guard lock(mutex_); - auto shadowTree = std::make_unique(surfaceId, layoutConstraints, layoutContext); shadowTree->setDelegate(this); - shadowTreeRegistry_.emplace(surfaceId, std::move(shadowTree)); + + shadowTreeRegistry_.add(std::move(shadowTree)); #ifndef ANDROID runtimeExecutor_([=](jsi::Runtime &runtime) { @@ -96,11 +96,10 @@ void Scheduler::renderTemplateToSurface( *componentDescriptorRegistry_, nMR); - std::lock_guard lock(mutex_); - const auto &shadowTree = shadowTreeRegistry_.at(surfaceId); - assert(shadowTree); - shadowTree->complete( - std::make_shared(SharedShadowNodeList{tree})); + shadowTreeRegistry_.get(surfaceId, [=](const ShadowTree &shadowTree) { + shadowTree.complete( + std::make_shared(SharedShadowNodeList{tree})); + }); } catch (const std::exception &e) { LOG(ERROR) << " >>>> EXCEPTION <<< rendering uiTemplate in " << "Scheduler::renderTemplateToSurface: " << e.what(); @@ -108,14 +107,14 @@ void Scheduler::renderTemplateToSurface( } void Scheduler::stopSurface(SurfaceId surfaceId) const { - std::lock_guard lock(mutex_); - const auto &iterator = shadowTreeRegistry_.find(surfaceId); - auto &shadowTree = *iterator->second; - // As part of stopping the Surface, we have to commit an empty tree. - shadowTree.complete(std::const_pointer_cast( - ShadowNode::emptySharedShadowNodeSharedList())); - shadowTree.setDelegate(nullptr); - shadowTreeRegistry_.erase(iterator); + shadowTreeRegistry_.get(surfaceId, [](const ShadowTree &shadowTree) { + // As part of stopping the Surface, we have to commit an empty tree. + shadowTree.complete(std::const_pointer_cast( + ShadowNode::emptySharedShadowNodeSharedList())); + }); + + auto shadowTree = shadowTreeRegistry_.remove(surfaceId); + shadowTree->setDelegate(nullptr); #ifndef ANDROID runtimeExecutor_([=](jsi::Runtime &runtime) { @@ -128,21 +127,21 @@ Size Scheduler::measureSurface( SurfaceId surfaceId, const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const { - std::lock_guard lock(mutex_); - const auto &shadowTree = shadowTreeRegistry_.at(surfaceId); - assert(shadowTree); - return shadowTree->measure(layoutConstraints, layoutContext); + Size size; + shadowTreeRegistry_.get(surfaceId, [&](const ShadowTree &shadowTree) { + size = shadowTree.measure(layoutConstraints, layoutContext); + }); + return size; } void Scheduler::constraintSurfaceLayout( SurfaceId surfaceId, const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const { - std::lock_guard lock(mutex_); - const auto &shadowTree = shadowTreeRegistry_.at(surfaceId); - assert(shadowTree); - shadowTree->synchronize([&]() { - shadowTree->constraintLayout(layoutConstraints, layoutContext); + shadowTreeRegistry_.get(surfaceId, [&](const ShadowTree &shadowTree) { + shadowTree.synchronize([&]() { + shadowTree.constraintLayout(layoutConstraints, layoutContext); + }); }); } @@ -170,16 +169,11 @@ void Scheduler::shadowTreeDidCommit( #pragma mark - UIManagerDelegate void Scheduler::uiManagerDidFinishTransaction( - Tag rootTag, + SurfaceId surfaceId, const SharedShadowNodeUnsharedList &rootChildNodes) { - std::lock_guard lock(mutex_); - const auto iterator = shadowTreeRegistry_.find(rootTag); - if (iterator == shadowTreeRegistry_.end()) { - // This might happen during surface unmounting/deallocation process - // due to the asynchronous nature of JS calls. - return; - } - iterator->second->complete(rootChildNodes); + shadowTreeRegistry_.get(surfaceId, [&](const ShadowTree &shadowTree) { + shadowTree.complete(rootChildNodes); + }); } void Scheduler::uiManagerDidCreateShadowNode( diff --git a/ReactCommon/fabric/uimanager/Scheduler.h b/ReactCommon/fabric/uimanager/Scheduler.h index 9c36711627c..ac798133307 100644 --- a/ReactCommon/fabric/uimanager/Scheduler.h +++ b/ReactCommon/fabric/uimanager/Scheduler.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -75,7 +76,7 @@ class Scheduler final : public UIManagerDelegate, public ShadowTreeDelegate { #pragma mark - UIManagerDelegate void uiManagerDidFinishTransaction( - Tag rootTag, + SurfaceId surfaceId, const SharedShadowNodeUnsharedList &rootChildNodes) override; void uiManagerDidCreateShadowNode( const SharedShadowNode &shadowNode) override; @@ -89,17 +90,10 @@ class Scheduler final : public UIManagerDelegate, public ShadowTreeDelegate { private: SchedulerDelegate *delegate_; SharedComponentDescriptorRegistry componentDescriptorRegistry_; - mutable std::mutex mutex_; - mutable std::unordered_map> - shadowTreeRegistry_; // Protected by `mutex_`. - SharedEventDispatcher eventDispatcher_; + ShadowTreeRegistry shadowTreeRegistry_; SharedContextContainer contextContainer_; RuntimeExecutor runtimeExecutor_; std::shared_ptr uiManagerBinding_; - - void uiManagerDidFinishTransactionWithoutLock( - Tag rootTag, - const SharedShadowNodeUnsharedList &rootChildNodes); }; } // namespace react diff --git a/ReactCommon/fabric/uimanager/ShadowTree.h b/ReactCommon/fabric/uimanager/ShadowTree.h index 346dc96db98..a7398699df6 100644 --- a/ReactCommon/fabric/uimanager/ShadowTree.h +++ b/ReactCommon/fabric/uimanager/ShadowTree.h @@ -77,6 +77,11 @@ class ShadowTree final { */ bool complete(const SharedShadowNodeUnsharedList &rootChildNodes) const; + /* + * Returns a root shadow node that represents the last committed three. + */ + SharedRootShadowNode getRootShadowNode() const; + #pragma mark - Delegate /* @@ -105,11 +110,6 @@ class ShadowTree final { void toggleEventEmitters(const ShadowViewMutationList &mutations) const; void emitLayoutEvents(const ShadowViewMutationList &mutations) const; - /* - * Return `rootShadowNodeMutex_` protected by `commitMutex_`. - */ - SharedRootShadowNode getRootShadowNode() const; - const SurfaceId surfaceId_; mutable SharedRootShadowNode rootShadowNode_; // Protected by `commitMutex_`. ShadowTreeDelegate const *delegate_; diff --git a/ReactCommon/fabric/uimanager/ShadowTreeRegistry.cpp b/ReactCommon/fabric/uimanager/ShadowTreeRegistry.cpp new file mode 100644 index 00000000000..01a6ab7cad1 --- /dev/null +++ b/ReactCommon/fabric/uimanager/ShadowTreeRegistry.cpp @@ -0,0 +1,40 @@ +// Copyright (c) Facebook, Inc. and its affiliates. + +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +#include "ShadowTreeRegistry.h" + +namespace facebook { +namespace react { + +void ShadowTreeRegistry::add(std::unique_ptr &&shadowTree) const { + std::lock_guard lock(mutex_); + registry_.emplace(shadowTree->getSurfaceId(), std::move(shadowTree)); +} + +std::unique_ptr ShadowTreeRegistry::remove( + SurfaceId surfaceId) const { + std::lock_guard lock(mutex_); + auto iterator = registry_.find(surfaceId); + auto shadowTree = std::unique_ptr(iterator->second.release()); + registry_.erase(iterator); + return shadowTree; +} + +bool ShadowTreeRegistry::get( + SurfaceId surfaceId, + std::function callback) const { + std::lock_guard lock(mutex_); + auto iterator = registry_.find(surfaceId); + + if (iterator == registry_.end()) { + return false; + } + + callback(*iterator->second); + return true; +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/uimanager/ShadowTreeRegistry.h b/ReactCommon/fabric/uimanager/ShadowTreeRegistry.h new file mode 100644 index 00000000000..1bd300f1f75 --- /dev/null +++ b/ReactCommon/fabric/uimanager/ShadowTreeRegistry.h @@ -0,0 +1,55 @@ +// Copyright (c) Facebook, Inc. and its affiliates. + +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include + +namespace facebook { +namespace react { + +/* + * Owning registry of `ShadowTree`s. + */ +class ShadowTreeRegistry final { + public: + ShadowTreeRegistry() = default; + + /* + * Adds a `ShadowTree` instance to the registry. + * The ownership of the instance is also transferred to the registry. + * Can be called from any thread. + */ + void add(std::unique_ptr &&shadowTree) const; + + /* + * Removes a `ShadowTree` instance with given `surfaceId` from the registry + * and returns it as a result. + * The ownership of the instance is also transferred to the caller. + * Can be called from any thread. + */ + std::unique_ptr remove(SurfaceId surfaceId) const; + + /* + * Finds a `ShadowTree` instance with a given `surfaceId` in the registry and + * synchronously calls the `callback` with a reference to the instance while + * the mutex is being acquired. + * Returns `true` if the registry has `ShadowTree` instance with corresponding + * `surfaceId`, otherwise returns `false` without calling the `callback`. + * Can be called from any thread. + */ + bool get( + SurfaceId surfaceId, + std::function callback) const; + + private: + mutable std::mutex mutex_; + mutable std::unordered_map> + registry_; // Protected by `mutex_`. +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/uimanager/UIManager.cpp b/ReactCommon/fabric/uimanager/UIManager.cpp index 881362cb283..ff29c5f7e1f 100644 --- a/ReactCommon/fabric/uimanager/UIManager.cpp +++ b/ReactCommon/fabric/uimanager/UIManager.cpp @@ -67,6 +67,33 @@ void UIManager::completeSurface( } } +LayoutMetrics UIManager::getRelativeLayoutMetrics( + const ShadowNode &shadowNode, + const ShadowNode *ancestorShadowNode) const { + if (!ancestorShadowNode) { + shadowTreeRegistry_->get( + shadowNode.getRootTag(), [&](const ShadowTree &shadowTree) { + ancestorShadowNode = shadowTree.getRootShadowNode().get(); + }); + } + + auto layoutableShadowNode = + dynamic_cast(&shadowNode); + auto layoutableAncestorShadowNode = + dynamic_cast(ancestorShadowNode); + + if (!layoutableShadowNode || !layoutableAncestorShadowNode) { + return EmptyLayoutMetrics; + } + + return layoutableShadowNode->getRelativeLayoutMetrics( + *layoutableAncestorShadowNode); +} + +void UIManager::setShadowTreeRegistry(ShadowTreeRegistry *shadowTreeRegistry) { + shadowTreeRegistry_ = shadowTreeRegistry; +} + void UIManager::setComponentDescriptorRegistry( const SharedComponentDescriptorRegistry &componentDescriptorRegistry) { componentDescriptorRegistry_ = componentDescriptorRegistry; diff --git a/ReactCommon/fabric/uimanager/UIManager.h b/ReactCommon/fabric/uimanager/UIManager.h index f7431c9ad3d..33742a6d7e4 100644 --- a/ReactCommon/fabric/uimanager/UIManager.h +++ b/ReactCommon/fabric/uimanager/UIManager.h @@ -8,6 +8,7 @@ #include #include +#include #include namespace facebook { @@ -15,6 +16,8 @@ namespace react { class UIManager { public: + void setShadowTreeRegistry(ShadowTreeRegistry *shadowTreeRegistry); + void setComponentDescriptorRegistry( const SharedComponentDescriptorRegistry &componentDescriptorRegistry); @@ -49,6 +52,16 @@ class UIManager { SurfaceId surfaceId, const SharedShadowNodeUnsharedList &rootChildren) const; + /* + * Returns layout metrics of given `shadowNode` relative to + * `ancestorShadowNode` (relative to the root node in case if provided + * `ancestorShadowNode` is nullptr). + */ + LayoutMetrics getRelativeLayoutMetrics( + const ShadowNode &shadowNode, + const ShadowNode *ancestorShadowNode) const; + + ShadowTreeRegistry *shadowTreeRegistry_; SharedComponentDescriptorRegistry componentDescriptorRegistry_; UIManagerDelegate *delegate_; }; diff --git a/ReactCommon/fabric/uimanager/UIManagerBinding.cpp b/ReactCommon/fabric/uimanager/UIManagerBinding.cpp index 05341d3d7c9..6c460e97339 100644 --- a/ReactCommon/fabric/uimanager/UIManagerBinding.cpp +++ b/ReactCommon/fabric/uimanager/UIManagerBinding.cpp @@ -90,6 +90,7 @@ void UIManagerBinding::dispatchEvent( } void UIManagerBinding::invalidate() const { + uiManager_->setShadowTreeRegistry(nullptr); uiManager_->setDelegate(nullptr); } diff --git a/ReactCommon/fabric/uimanager/UIManagerDelegate.h b/ReactCommon/fabric/uimanager/UIManagerDelegate.h index e2375329d9a..cd6b881615b 100644 --- a/ReactCommon/fabric/uimanager/UIManagerDelegate.h +++ b/ReactCommon/fabric/uimanager/UIManagerDelegate.h @@ -23,7 +23,7 @@ class UIManagerDelegate { * The tree is not layed out and not sealed at this time. */ virtual void uiManagerDidFinishTransaction( - Tag rootTag, + SurfaceId surfaceId, const SharedShadowNodeUnsharedList &rootChildNodes) = 0; /* diff --git a/ReactCommon/jsiexecutor/jsireact/JSINativeModules.cpp b/ReactCommon/jsiexecutor/jsireact/JSINativeModules.cpp index aa1a7fdab8b..a15ceb05ca3 100644 --- a/ReactCommon/jsiexecutor/jsireact/JSINativeModules.cpp +++ b/ReactCommon/jsiexecutor/jsireact/JSINativeModules.cpp @@ -65,7 +65,7 @@ folly::Optional JSINativeModules::createModule( auto result = m_moduleRegistry->getConfig(name); if (!result.hasValue()) { - return nullptr; + return folly::none; } Value moduleInfo = m_genNativeModuleJS->call( diff --git a/ReactCommon/yoga/yoga/Utils.cpp b/ReactCommon/yoga/yoga/Utils.cpp index fa21a55b68d..5322642f744 100644 --- a/ReactCommon/yoga/yoga/Utils.cpp +++ b/ReactCommon/yoga/yoga/Utils.cpp @@ -52,7 +52,7 @@ bool YGFloatsEqual(const float a, const float b) { return yoga::isUndefined(a) && yoga::isUndefined(b); } -float YGFloatSanitize(const float& val) { +float YGFloatSanitize(const float val) { return yoga::isUndefined(val) ? 0 : val; } diff --git a/ReactCommon/yoga/yoga/Utils.h b/ReactCommon/yoga/yoga/Utils.h index e538cad9c50..db257ae51e7 100644 --- a/ReactCommon/yoga/yoga/Utils.h +++ b/ReactCommon/yoga/yoga/Utils.h @@ -91,7 +91,7 @@ bool YGFloatArrayEqual( } // This function returns 0 if YGFloatIsUndefined(val) is true and val otherwise -float YGFloatSanitize(const float& val); +float YGFloatSanitize(const float val); // This function unwraps optional and returns YGUndefined if not defined or // op.value otherwise diff --git a/ReactCommon/yoga/yoga/YGNode.cpp b/ReactCommon/yoga/yoga/YGNode.cpp index 76f662e710c..189a3df1c2c 100644 --- a/ReactCommon/yoga/yoga/YGNode.cpp +++ b/ReactCommon/yoga/yoga/YGNode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. @@ -12,8 +12,8 @@ using namespace facebook; YGFloatOptional YGNode::getLeadingPosition( - const YGFlexDirection& axis, - const float& axisSize) const { + const YGFlexDirection axis, + const float axisSize) const { if (YGFlexDirectionIsRow(axis)) { const YGValue* leadingPosition = YGComputedEdgeValue(style_.position, YGEdgeStart, &YGValueUndefined); @@ -31,8 +31,8 @@ YGFloatOptional YGNode::getLeadingPosition( } YGFloatOptional YGNode::getTrailingPosition( - const YGFlexDirection& axis, - const float& axisSize) const { + const YGFlexDirection axis, + const float axisSize) const { if (YGFlexDirectionIsRow(axis)) { const YGValue* trailingPosition = YGComputedEdgeValue(style_.position, YGEdgeEnd, &YGValueUndefined); @@ -49,7 +49,7 @@ YGFloatOptional YGNode::getTrailingPosition( : YGResolveValue(*trailingPosition, axisSize); } -bool YGNode::isLeadingPositionDefined(const YGFlexDirection& axis) const { +bool YGNode::isLeadingPositionDefined(const YGFlexDirection axis) const { return (YGFlexDirectionIsRow(axis) && YGComputedEdgeValue(style_.position, YGEdgeStart, &YGValueUndefined) ->unit != YGUnitUndefined) || @@ -57,7 +57,7 @@ bool YGNode::isLeadingPositionDefined(const YGFlexDirection& axis) const { ->unit != YGUnitUndefined; } -bool YGNode::isTrailingPosDefined(const YGFlexDirection& axis) const { +bool YGNode::isTrailingPosDefined(const YGFlexDirection axis) const { return (YGFlexDirectionIsRow(axis) && YGComputedEdgeValue(style_.position, YGEdgeEnd, &YGValueUndefined) ->unit != YGUnitUndefined) || @@ -66,8 +66,8 @@ bool YGNode::isTrailingPosDefined(const YGFlexDirection& axis) const { } YGFloatOptional YGNode::getLeadingMargin( - const YGFlexDirection& axis, - const float& widthSize) const { + const YGFlexDirection axis, + const float widthSize) const { if (YGFlexDirectionIsRow(axis) && style_.margin[YGEdgeStart].unit != YGUnitUndefined) { return YGResolveValueMargin(style_.margin[YGEdgeStart], widthSize); @@ -79,8 +79,8 @@ YGFloatOptional YGNode::getLeadingMargin( } YGFloatOptional YGNode::getTrailingMargin( - const YGFlexDirection& axis, - const float& widthSize) const { + const YGFlexDirection axis, + const float widthSize) const { if (YGFlexDirectionIsRow(axis) && style_.margin[YGEdgeEnd].unit != YGUnitUndefined) { return YGResolveValueMargin(style_.margin[YGEdgeEnd], widthSize); @@ -92,8 +92,8 @@ YGFloatOptional YGNode::getTrailingMargin( } YGFloatOptional YGNode::getMarginForAxis( - const YGFlexDirection& axis, - const float& widthSize) const { + const YGFlexDirection axis, + const float widthSize) const { return getLeadingMargin(axis, widthSize) + getTrailingMargin(axis, widthSize); } @@ -204,8 +204,8 @@ void YGNode::setLayoutDimension(float dimension, int index) { // If both left and right are defined, then use left. Otherwise return // +left or -right depending on which is defined. YGFloatOptional YGNode::relativePosition( - const YGFlexDirection& axis, - const float& axisSize) const { + const YGFlexDirection axis, + const float axisSize) const { if (isLeadingPositionDefined(axis)) { return getLeadingPosition(axis, axisSize); } @@ -424,7 +424,7 @@ bool YGNode::isNodeFlexible() { (resolveFlexGrow() != 0 || resolveFlexShrink() != 0)); } -float YGNode::getLeadingBorder(const YGFlexDirection& axis) const { +float YGNode::getLeadingBorder(const YGFlexDirection axis) const { if (YGFlexDirectionIsRow(axis) && style_.border[YGEdgeStart].unit != YGUnitUndefined && !yoga::isUndefined(style_.border[YGEdgeStart].value) && @@ -437,7 +437,7 @@ float YGNode::getLeadingBorder(const YGFlexDirection& axis) const { return YGFloatMax(computedEdgeValue, 0.0f); } -float YGNode::getTrailingBorder(const YGFlexDirection& flexDirection) const { +float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) const { if (YGFlexDirectionIsRow(flexDirection) && style_.border[YGEdgeEnd].unit != YGUnitUndefined && !yoga::isUndefined(style_.border[YGEdgeEnd].value) && @@ -452,8 +452,8 @@ float YGNode::getTrailingBorder(const YGFlexDirection& flexDirection) const { } YGFloatOptional YGNode::getLeadingPadding( - const YGFlexDirection& axis, - const float& widthSize) const { + const YGFlexDirection axis, + const float widthSize) const { const YGFloatOptional& paddingEdgeStart = YGResolveValue(style_.padding[YGEdgeStart], widthSize); if (YGFlexDirectionIsRow(axis) && @@ -469,8 +469,8 @@ YGFloatOptional YGNode::getLeadingPadding( } YGFloatOptional YGNode::getTrailingPadding( - const YGFlexDirection& axis, - const float& widthSize) const { + const YGFlexDirection axis, + const float widthSize) const { if (YGFlexDirectionIsRow(axis) && style_.padding[YGEdgeEnd].unit != YGUnitUndefined && !YGResolveValue(style_.padding[YGEdgeEnd], widthSize).isUndefined() && @@ -486,15 +486,15 @@ YGFloatOptional YGNode::getTrailingPadding( } YGFloatOptional YGNode::getLeadingPaddingAndBorder( - const YGFlexDirection& axis, - const float& widthSize) const { + const YGFlexDirection axis, + const float widthSize) const { return getLeadingPadding(axis, widthSize) + YGFloatOptional(getLeadingBorder(axis)); } YGFloatOptional YGNode::getTrailingPaddingAndBorder( - const YGFlexDirection& axis, - const float& widthSize) const { + const YGFlexDirection axis, + const float widthSize) const { return getTrailingPadding(axis, widthSize) + YGFloatOptional(getTrailingBorder(axis)); } diff --git a/ReactCommon/yoga/yoga/YGNode.h b/ReactCommon/yoga/yoga/YGNode.h index d771aad2460..678926d3a0d 100644 --- a/ReactCommon/yoga/yoga/YGNode.h +++ b/ReactCommon/yoga/yoga/YGNode.h @@ -17,6 +17,7 @@ struct YGNode { void* context_ = nullptr; YGPrintFunc print_ = nullptr; bool hasNewLayout_ = true; + bool isReferenceBaseline_ = false; YGNodeType nodeType_ = YGNodeTypeDefault; YGMeasureFunc measure_ = nullptr; YGBaselineFunc baseline_ = nullptr; @@ -32,8 +33,8 @@ struct YGNode { {YGValueUndefined, YGValueUndefined}}; YGFloatOptional relativePosition( - const YGFlexDirection& axis, - const float& axisSize) const; + const YGFlexDirection axis, + const float axisSize) const; public: YGNode() = default; @@ -93,6 +94,10 @@ struct YGNode { return lineIndex_; } + bool isReferenceBaseline() { + return isReferenceBaseline_; + } + // returns the YGNodeRef that owns this YGNode. An owner is used to identify // the YogaTree that a YGNode belongs to. // This method will return the parent of the YGNode when a YGNode only belongs @@ -133,36 +138,36 @@ struct YGNode { // Methods related to positions, margin, padding and border YGFloatOptional getLeadingPosition( - const YGFlexDirection& axis, - const float& axisSize) const; - bool isLeadingPositionDefined(const YGFlexDirection& axis) const; - bool isTrailingPosDefined(const YGFlexDirection& axis) const; + const YGFlexDirection axis, + const float axisSize) const; + bool isLeadingPositionDefined(const YGFlexDirection axis) const; + bool isTrailingPosDefined(const YGFlexDirection axis) const; YGFloatOptional getTrailingPosition( - const YGFlexDirection& axis, - const float& axisSize) const; + const YGFlexDirection axis, + const float axisSize) const; YGFloatOptional getLeadingMargin( - const YGFlexDirection& axis, - const float& widthSize) const; + const YGFlexDirection axis, + const float widthSize) const; YGFloatOptional getTrailingMargin( - const YGFlexDirection& axis, - const float& widthSize) const; - float getLeadingBorder(const YGFlexDirection& flexDirection) const; - float getTrailingBorder(const YGFlexDirection& flexDirection) const; + const YGFlexDirection axis, + const float widthSize) const; + float getLeadingBorder(const YGFlexDirection flexDirection) const; + float getTrailingBorder(const YGFlexDirection flexDirection) const; YGFloatOptional getLeadingPadding( - const YGFlexDirection& axis, - const float& widthSize) const; + const YGFlexDirection axis, + const float widthSize) const; YGFloatOptional getTrailingPadding( - const YGFlexDirection& axis, - const float& widthSize) const; + const YGFlexDirection axis, + const float widthSize) const; YGFloatOptional getLeadingPaddingAndBorder( - const YGFlexDirection& axis, - const float& widthSize) const; + const YGFlexDirection axis, + const float widthSize) const; YGFloatOptional getTrailingPaddingAndBorder( - const YGFlexDirection& axis, - const float& widthSize) const; + const YGFlexDirection axis, + const float widthSize) const; YGFloatOptional getMarginForAxis( - const YGFlexDirection& axis, - const float& widthSize) const; + const YGFlexDirection axis, + const float widthSize) const; // Setters void setContext(void* context) { @@ -211,6 +216,10 @@ struct YGNode { lineIndex_ = lineIndex; } + void setIsReferenceBaseline(bool isReferenceBaseline) { + isReferenceBaseline_ = isReferenceBaseline; + } + void setOwner(YGNodeRef owner) { owner_ = owner; } diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index 6e42d51aeee..10f27bf080a 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. @@ -380,6 +380,14 @@ void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src) { memcpy(dest, src, sizeof(YGConfig)); } +void YGNodeSetIsReferenceBaseline(YGNodeRef node, bool isReferenceBaseline) { + node->setIsReferenceBaseline(isReferenceBaseline); +} + +bool YGNodeIsReferenceBaseline(YGNodeRef node) { + return node->isReferenceBaseline(); +} + void YGNodeInsertChild( const YGNodeRef node, const YGNodeRef child, @@ -1138,7 +1146,8 @@ static float YGBaseline(const YGNodeRef node) { if (child->getStyle().positionType == YGPositionTypeAbsolute) { continue; } - if (YGNodeAlignItem(node, child) == YGAlignBaseline) { + if (YGNodeAlignItem(node, child) == YGAlignBaseline || + child->isReferenceBaseline()) { baselineChild = child; break; } @@ -1211,9 +1220,9 @@ static inline bool YGNodeIsLayoutDimDefined( static YGFloatOptional YGNodeBoundAxisWithinMinAndMax( const YGNodeRef node, - const YGFlexDirection& axis, - const float& value, - const float& axisSize) { + const YGFlexDirection axis, + const float value, + const float axisSize) { YGFloatOptional min; YGFloatOptional max; @@ -1902,7 +1911,7 @@ static float YGNodeCalculateAvailableInnerDim( return availableInnerDim; } -static void YGNodeComputeFlexBasisForChildren( +static float YGNodeComputeFlexBasisForChildren( const YGNodeRef node, const float availableInnerWidth, const float availableInnerHeight, @@ -1911,8 +1920,8 @@ static void YGNodeComputeFlexBasisForChildren( YGDirection direction, YGFlexDirection mainAxis, const YGConfigRef config, - bool performLayout, - float& totalOuterFlexBasis) { + bool performLayout) { + float totalOuterFlexBasis = 0.0f; YGNodeRef singleFlexChild = nullptr; YGVector children = node->getChildren(); YGMeasureMode measureModeMainDim = @@ -1982,6 +1991,8 @@ static void YGNodeComputeFlexBasisForChildren( child->getLayout().computedFlexBasis + child->getMarginForAxis(mainAxis, availableInnerWidth)); } + + return totalOuterFlexBasis; } // This function assumes that all the children of node have their @@ -2413,17 +2424,17 @@ static void YGResolveFlexibleLength( static void YGJustifyMainAxis( const YGNodeRef node, YGCollectFlexItemsRowValues& collectedFlexItemsValues, - const uint32_t& startOfLineIndex, - const YGFlexDirection& mainAxis, - const YGFlexDirection& crossAxis, - const YGMeasureMode& measureModeMainDim, - const YGMeasureMode& measureModeCrossDim, - const float& mainAxisownerSize, - const float& ownerWidth, - const float& availableInnerMainDim, - const float& availableInnerCrossDim, - const float& availableInnerWidth, - const bool& performLayout) { + const uint32_t startOfLineIndex, + const YGFlexDirection mainAxis, + const YGFlexDirection crossAxis, + const YGMeasureMode measureModeMainDim, + const YGMeasureMode measureModeCrossDim, + const float mainAxisownerSize, + const float ownerWidth, + const float availableInnerMainDim, + const float availableInnerCrossDim, + const float availableInnerWidth, + const bool performLayout) { const YGStyle& style = node->getStyle(); const float leadingPaddingAndBorderMain = YGUnwrapFloatOptional( node->getLeadingPaddingAndBorder(mainAxis, ownerWidth)); @@ -2893,11 +2904,9 @@ static void YGNodelayoutImpl( const float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth; - float totalOuterFlexBasis = 0; - // STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM - YGNodeComputeFlexBasisForChildren( + float totalOuterFlexBasis = YGNodeComputeFlexBasisForChildren( node, availableInnerWidth, availableInnerHeight, @@ -2906,8 +2915,7 @@ static void YGNodelayoutImpl( direction, mainAxis, config, - performLayout, - totalOuterFlexBasis); + performLayout); const bool flexBasisOverflows = measureModeMainDim == YGMeasureModeUndefined ? false diff --git a/ReactCommon/yoga/yoga/Yoga.h b/ReactCommon/yoga/yoga/Yoga.h index d5da362decd..dddab8bb341 100644 --- a/ReactCommon/yoga/yoga/Yoga.h +++ b/ReactCommon/yoga/yoga/Yoga.h @@ -114,6 +114,12 @@ WIN_EXPORT void YGNodeSetChildren( const YGNodeRef children[], const uint32_t count); +WIN_EXPORT void YGNodeSetIsReferenceBaseline( + YGNodeRef node, + bool isReferenceBaseline); + +WIN_EXPORT bool YGNodeIsReferenceBaseline(YGNodeRef node); + WIN_EXPORT void YGNodeCalculateLayout( const YGNodeRef node, const float availableWidth, diff --git a/flow-github/metro.js b/flow-github/metro.js index 88ef8feae5f..bb67ab543d5 100644 --- a/flow-github/metro.js +++ b/flow-github/metro.js @@ -71,3 +71,7 @@ declare module 'metro/src/ModuleGraph/worker/collectDependencies' { declare module 'metro/src/JSTransformer/worker' { declare module.exports: any; } + +declare module 'metro/src/DeltaBundler/Serializers/plainJSBundle' { + declare module.exports: any; +} diff --git a/local-cli/generator/promptSync.js b/local-cli/generator/promptSync.js index c8af74c487a..2388ef04694 100644 --- a/local-cli/generator/promptSync.js +++ b/local-cli/generator/promptSync.js @@ -43,7 +43,7 @@ function create() { process.stdin.setRawMode(true); } - var buf = new Buffer(3); + var buf = Buffer.alloc(3); var str = '', character, read; @@ -62,7 +62,7 @@ function create() { insert = str.length; process.stdout.write('\u001b[2K\u001b[0G' + ask + str); process.stdout.write('\u001b[' + (insert + ask.length + 1) + 'G'); - buf = new Buffer(3); + buf = Buffer.alloc(3); } continue; // any other 3 character sequence is ignored } diff --git a/local-cli/server/util/copyToClipBoard.js b/local-cli/server/util/copyToClipBoard.js index 1f22477b9b1..e6b1bd7a18f 100644 --- a/local-cli/server/util/copyToClipBoard.js +++ b/local-cli/server/util/copyToClipBoard.js @@ -23,15 +23,15 @@ function copyToClipBoard(content) { switch (process.platform) { case 'darwin': var child = spawn('pbcopy', []); - child.stdin.end(new Buffer(content, 'utf8')); + child.stdin.end(Buffer.from(content, 'utf8')); return true; case 'win32': var child = spawn('clip', []); - child.stdin.end(new Buffer(content, 'utf8')); + child.stdin.end(Buffer.from(content, 'utf8')); return true; case 'linux': var child = spawn(xsel, ['--clipboard', '--input']); - child.stdin.end(new Buffer(content, 'utf8')); + child.stdin.end(Buffer.from(content, 'utf8')); return true; default: return false; diff --git a/local-cli/templates/HelloWorld/_flowconfig b/local-cli/templates/HelloWorld/_flowconfig index f3eb74de673..9bded78be9b 100644 --- a/local-cli/templates/HelloWorld/_flowconfig +++ b/local-cli/templates/HelloWorld/_flowconfig @@ -67,4 +67,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError [version] -^0.85.0 +^0.86.0 diff --git a/package.json b/package.json index 7103e75760b..a787d496ee8 100644 --- a/package.json +++ b/package.json @@ -170,6 +170,8 @@ "glob": "^7.1.1", "graceful-fs": "^4.1.3", "inquirer": "^3.0.6", + "jest": "24.0.0-alpha.6", + "jest-junit": "5.2.0", "lodash": "^4.17.5", "metro": "^0.49.1", "metro-babel-register": "^0.49.1", @@ -187,11 +189,11 @@ "opn": "^3.0.2", "optimist": "^0.6.1", "plist": "^3.0.0", - "pretty-format": "24.0.0-alpha.4", + "pretty-format": "24.0.0-alpha.6", "promise": "^7.1.1", "prop-types": "^15.5.8", "react-clone-referenced-element": "^1.0.1", - "react-devtools-core": "^3.4.0", + "react-devtools-core": "^3.4.2", "regenerator-runtime": "^0.11.0", "rimraf": "^2.5.4", "semver": "^5.0.3", @@ -205,6 +207,7 @@ }, "devDependencies": { "@babel/core": "^7.0.0", + "@reactions/component": "^2.0.2", "async": "^2.4.0", "babel-eslint": "9.0.0", "babel-generator": "^6.26.0", @@ -218,9 +221,9 @@ "eslint-plugin-prettier": "2.6.0", "eslint-plugin-react": "7.8.2", "eslint-plugin-react-native": "3.5.0", - "flow-bin": "^0.85.0", - "jest": "24.0.0-alpha.4", - "jest-junit": "5.1.0", + "flow-bin": "^0.86.0", + "jest": "24.0.0-alpha.6", + "jest-junit": "5.2.0", "prettier": "1.13.6", "react": "16.6.3", "react-native-dummy": "0.1.0", diff --git a/yarn.lock b/yarn.lock index 9723976822e..1e07f618f8d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.0.0-beta.35": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== @@ -645,6 +645,10 @@ lodash "^4.17.10" to-fast-properties "^2.0.0" +"@reactions/component@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@reactions/component/-/component-2.0.2.tgz#40f8c1c2c37baabe57a0c944edb9310dc1ec6642" + abab@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f" @@ -1055,13 +1059,21 @@ babel-helpers@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-jest@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.0.0-alpha.4.tgz#e03318023fb23c7646d4ffec97cec8b9034d5e5c" - integrity sha512-Z+KXWy+12w8h87l7G0muSDNh3XNclze3ohRpD0hqBypwZRUgX/755RYW6MpZhxSgHC1de3d9lUnYR016al0bfg== +babel-jest@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1" + integrity sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew== dependencies: babel-plugin-istanbul "^4.1.6" - babel-preset-jest "^24.0.0-alpha.4" + babel-preset-jest "^23.2.0" + +babel-jest@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.0.0-alpha.6.tgz#e3bd746b82456fc67fb7b4c9152a9aacbc747a8d" + integrity sha512-2scrmuFWZcQ4Bc0ULhzhKH8eQCC1XAa6TPs9QD7ofYeJsrC5XeJj4EfACYyW5NnvhStXm9R/OU1uoxWDAas1wQ== + dependencies: + babel-plugin-istanbul "^4.1.6" + babel-preset-jest "^24.0.0-alpha.6" babel-messages@^6.23.0: version "6.23.0" @@ -1080,10 +1092,15 @@ babel-plugin-istanbul@^4.1.6: istanbul-lib-instrument "^1.10.1" test-exclude "^4.2.1" -babel-plugin-jest-hoist@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.0.0-alpha.4.tgz#4fcb1369b3814f98496153c86946916c22d0a0aa" - integrity sha512-7xF5AEQCJXqT4rRvIK/tUnAAa4OCk62yiemep61qNgyTlGJNeS/SC1CecPOkV0KEhRrVZOhwLScHXAUWxaYagg== +babel-plugin-jest-hoist@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167" + integrity sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc= + +babel-plugin-jest-hoist@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.0.0-alpha.6.tgz#b1e3e1b8d3d64f1f94dde438b7fbb5f91506b6f7" + integrity sha512-Z06kZ8x8EtaBgUUI9Rkg3oZBq3jWhlF2yHFOzxBvjkQGQU/r014RjcIVT5qKeYDGn9Z8eYHy8w//a0qOphSI3Q== babel-plugin-syntax-object-rest-spread@^6.13.0: version "6.13.0" @@ -1129,12 +1146,20 @@ babel-preset-fbjs@^3.0.0, babel-preset-fbjs@^3.0.1: "@babel/plugin-transform-template-literals" "^7.0.0" babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" -babel-preset-jest@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.0.0-alpha.4.tgz#2f704b57695d801d1622fb809355a426c5ff0556" - integrity sha512-4/TENlz9eSYPTFBWGsJ8Ezpoj77BkFtIJz2tT7EykfFbbh1OwPoc97+JcFWd0HUtOrKf7SYoT3DW2Adc7XveuA== +babel-preset-jest@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46" + integrity sha1-jsegOhOPABoaj7HoETZSvxpV2kY= dependencies: - babel-plugin-jest-hoist "^24.0.0-alpha.4" + babel-plugin-jest-hoist "^23.2.0" + babel-plugin-syntax-object-rest-spread "^6.13.0" + +babel-preset-jest@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.0.0-alpha.6.tgz#effeb7f6927ac2734dd55e2f3936bbaab7312a6a" + integrity sha512-XuKtUS/hIRfRgJHTVpwGe2yZfE6SFqTElzMdG79tUuOs8z+BxURTCNuVXecVcXDuermn7HA7NAi9VS0zgSmc4g== + dependencies: + babel-plugin-jest-hoist "^24.0.0-alpha.6" babel-plugin-syntax-object-rest-spread "^6.13.0" babel-register@^6.26.0: @@ -2282,17 +2307,29 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" -expect@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/expect/-/expect-24.0.0-alpha.4.tgz#f7d05692668b40983d2affdcf600743a726c9c8d" - integrity sha512-7geaVKj1pxwgNuKXV1osvcCRWPZMrJeWMa5jv6kCJHLjtLwz3yUuGdfVUIL/3JSFVchG3h9nZpE7RNYiAFxpTw== +expect@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-23.6.0.tgz#1e0c8d3ba9a581c87bd71fb9bc8862d443425f98" + integrity sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w== dependencies: ansi-styles "^3.2.0" - jest-diff "^24.0.0-alpha.4" - jest-get-type "^24.0.0-alpha.4" - jest-matcher-utils "^24.0.0-alpha.4" - jest-message-util "^24.0.0-alpha.4" - jest-regex-util "^24.0.0-alpha.4" + jest-diff "^23.6.0" + jest-get-type "^22.1.0" + jest-matcher-utils "^23.6.0" + jest-message-util "^23.4.0" + jest-regex-util "^23.3.0" + +expect@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/expect/-/expect-24.0.0-alpha.6.tgz#55f1edb1d73e1b0b58474b4775331480d50839cd" + integrity sha512-FcafdwfuHoDPgzVlBrhRVp7s2y5Qd+Jv4nlHtCAlO5b1BWArhZFwc9n1Jp4M8/q5nINICkbSFoA1bmR6czLg3w== + dependencies: + ansi-styles "^3.2.0" + jest-diff "^24.0.0-alpha.6" + jest-get-type "^24.0.0-alpha.6" + jest-matcher-utils "^24.0.0-alpha.6" + jest-message-util "^24.0.0-alpha.6" + jest-regex-util "^24.0.0-alpha.6" extend-shallow@^1.1.2: version "1.1.4" @@ -2553,10 +2590,10 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" -flow-bin@^0.85.0: - version "0.85.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.85.0.tgz#a3ca80748a35a071d5bbb2fcd61d64d977fc53a6" - integrity sha512-ougBA2q6Rn9sZrjZQ9r5pTFxCotlGouySpD2yRIuq5AYwwfIT8HHhVMeSwrN5qJayjHINLJyrnsSkkPCZyfMrQ== +flow-bin@^0.86.0: + version "0.86.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.86.0.tgz#153a28722b4dc13b7200c74b644dd4d9f4969a11" + integrity sha512-ulRvFH3ewGIYwg+qPk/OJXoe3Nhqi0RyR0wqgK0b1NzUDEC6O99zU39MBTickXvlrr6iwRO6Wm4lVGeDmnzbew== for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" @@ -3386,18 +3423,18 @@ istanbul-reports@^1.5.1: dependencies: handlebars "^4.0.3" -jest-changed-files@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.0.0-alpha.4.tgz#ffcc670aa1734c2d064d7d6c79851da8ca6a563d" - integrity sha512-UySN8v8OmcN4QL4zJAjL0EE8wqvltwKH69tKzrbAb7Mj1IuOBdlvccJUoDnKg9MkVAbVqk/3/sgn28tWFf7prg== +jest-changed-files@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.0.0-alpha.6.tgz#f3fd2e96f67f3e1e7e2bc74fc7c81c5e53801404" + integrity sha512-0Z2UpqTqMNhMNEtIK/1nCD7jR4+w1YM7zAaMFQMJG28UiV0Oqarn9u5OeH66BbUvB9FnKvVJTrSPpgPpR9f2YA== dependencies: execa "^1.0.0" throat "^4.0.0" -jest-cli@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.0.0-alpha.4.tgz#a91c843b6e53f6a8f953813b704dd12411c98e9c" - integrity sha512-eRjpuLgY2pPPJLFAZ7sLQE9k250Or/HiLZmsmgku4zVV9pHj/LAJzm7S74HOwv+JWexsFqKiYRgW8PrIFWoNNw== +jest-cli@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.0.0-alpha.6.tgz#d5e4ee6c39d2912a70ac78352521d8c606ea27b9" + integrity sha512-xPp1CqmyE1i66hnci4Mk/eRrPHAKAmWZjKXDTa084NSpmEVnvbapDFEcSlWFvEhzGx5Hux8nIXjk8qr1ODAA4Q== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.1" @@ -3410,21 +3447,21 @@ jest-cli@^24.0.0-alpha.4: istanbul-lib-coverage "^1.2.0" istanbul-lib-instrument "^1.10.1" istanbul-lib-source-maps "^1.2.4" - jest-changed-files "^24.0.0-alpha.4" - jest-config "^24.0.0-alpha.4" - jest-environment-jsdom "^24.0.0-alpha.4" - jest-get-type "^24.0.0-alpha.4" - jest-haste-map "^24.0.0-alpha.4" - jest-message-util "^24.0.0-alpha.4" - jest-regex-util "^24.0.0-alpha.4" - jest-resolve-dependencies "^24.0.0-alpha.4" - jest-runner "^24.0.0-alpha.4" - jest-runtime "^24.0.0-alpha.4" - jest-snapshot "^24.0.0-alpha.4" - jest-util "^24.0.0-alpha.4" - jest-validate "^24.0.0-alpha.4" - jest-watcher "^24.0.0-alpha.4" - jest-worker "^24.0.0-alpha.4" + jest-changed-files "^24.0.0-alpha.6" + jest-config "^24.0.0-alpha.6" + jest-environment-jsdom "^24.0.0-alpha.6" + jest-get-type "^24.0.0-alpha.6" + jest-haste-map "^24.0.0-alpha.6" + jest-message-util "^24.0.0-alpha.6" + jest-regex-util "^24.0.0-alpha.6" + jest-resolve-dependencies "^24.0.0-alpha.6" + jest-runner "^24.0.0-alpha.6" + jest-runtime "^24.0.0-alpha.6" + jest-snapshot "^24.0.0-alpha.6" + jest-util "^24.0.0-alpha.6" + jest-validate "^24.0.0-alpha.6" + jest-watcher "^24.0.0-alpha.6" + jest-worker "^24.0.0-alpha.6" micromatch "^2.3.11" node-notifier "^5.2.1" prompts "^1.1.0" @@ -3436,88 +3473,175 @@ jest-cli@^24.0.0-alpha.4: which "^1.2.12" yargs "^12.0.2" -jest-config@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.0.0-alpha.4.tgz#e07ba3625db86ca28ee34d9422566260a54c865f" - integrity sha512-JlGeIY4cVi+xkNSbL1+44QS6Y0fSSsv/hpLSy+Ml1ruX0cmyGVMUfsq3X5mGa+q843mW9pnkLJRuLVd7Oisuig== +jest-config@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.6.0.tgz#f82546a90ade2d8c7026fbf6ac5207fc22f8eb1d" + integrity sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ== dependencies: babel-core "^6.0.0" - babel-jest "^24.0.0-alpha.4" + babel-jest "^23.6.0" chalk "^2.0.1" glob "^7.1.1" - jest-environment-jsdom "^24.0.0-alpha.4" - jest-environment-node "^24.0.0-alpha.4" - jest-get-type "^24.0.0-alpha.4" - jest-jasmine2 "^24.0.0-alpha.4" - jest-regex-util "^24.0.0-alpha.4" - jest-resolve "^24.0.0-alpha.4" - jest-util "^24.0.0-alpha.4" - jest-validate "^24.0.0-alpha.4" + jest-environment-jsdom "^23.4.0" + jest-environment-node "^23.4.0" + jest-get-type "^22.1.0" + jest-jasmine2 "^23.6.0" + jest-regex-util "^23.3.0" + jest-resolve "^23.6.0" + jest-util "^23.4.0" + jest-validate "^23.6.0" micromatch "^2.3.11" - pretty-format "^24.0.0-alpha.4" + pretty-format "^23.6.0" -jest-diff@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.0.0-alpha.4.tgz#fc17a96b6143f686ad2a9977a60b62593a38e0e4" - integrity sha512-T3ZbPHcYOBCye60zjygOwbVyl83qC/MxRgi7CphRh8o+vUZ61Mr34LToLWwgRGxym1X7zI07ATuI33cdksreNw== +jest-config@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.0.0-alpha.6.tgz#63f86a568a4e2135bee93396dedca04c7a2da14b" + integrity sha512-f9fGnkqxuYZnrioQ05eWZLSp750h+VkWJ1EU5xrf9zRR7Zu9BUTPubomvT0/FUbxK9QszxmU5SMKvdNKuwrwpw== + dependencies: + babel-core "^6.0.0" + babel-jest "^24.0.0-alpha.6" + chalk "^2.0.1" + glob "^7.1.1" + jest-environment-jsdom "^24.0.0-alpha.6" + jest-environment-node "^24.0.0-alpha.6" + jest-get-type "^24.0.0-alpha.6" + jest-jasmine2 "^24.0.0-alpha.6" + jest-regex-util "^24.0.0-alpha.6" + jest-resolve "^24.0.0-alpha.6" + jest-util "^24.0.0-alpha.6" + jest-validate "^24.0.0-alpha.6" + micromatch "^2.3.11" + pretty-format "^24.0.0-alpha.6" + +jest-diff@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.6.0.tgz#1500f3f16e850bb3d71233408089be099f610c7d" + integrity sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g== dependencies: chalk "^2.0.1" diff "^3.2.0" - jest-get-type "^24.0.0-alpha.4" - pretty-format "^24.0.0-alpha.4" + jest-get-type "^22.1.0" + pretty-format "^23.6.0" + +jest-diff@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.0.0-alpha.6.tgz#9770b9d2067d40f3f8ff4001fcaf0eb0e5390f36" + integrity sha512-WXk920DseU/E93jfRv47RLUmYfZeVmEDDE2VF3P2tMoJSCsZ3A00KbjCtlgJ/8hXA7vPLPJN6SBcb5kqqRJ/RQ== + dependencies: + chalk "^2.0.1" + diff "^3.2.0" + jest-get-type "^24.0.0-alpha.6" + pretty-format "^24.0.0-alpha.6" jest-docblock@^21.0.0: version "21.2.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" integrity sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw== +<<<<<<< HEAD jest-docblock@^24.0.0-alpha.4: version "24.0.0-alpha.4" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.0.0-alpha.4.tgz#883264370210bbd4dfadf9ea0bc5f89baca926c1" integrity sha512-NQ6DsiCR6OLLZ8XI1X5E0L/WzobR1vBRbPj5GDNIseblMKtCBOsVy9tzvl3+sgLDoQcWB4GctfrBD7UM9/pItg== +======= +jest-docblock@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.0.0-alpha.6.tgz#abb38d04afd624cbfb34e13fa9e0c1053388a333" + integrity sha512-veghPy2eBQ5r8XXd+VLK7AfCxJMTwqA8B2fknR24aibIkGW7dj4fq538HtwIvXkRpUO5f1b5x6IEsCb9g+e6qw== dependencies: detect-newline "^2.1.0" -jest-each@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.0.0-alpha.4.tgz#24e0402e631df539e93cdfbfd0641ef39b598124" - integrity sha512-tnD25TU9HmZG/+5zUnWK8nITVqqBOl037oDroHKYrgPdyJez4WbZuwkZDVotsz3rb58Y/aSaCIeRXMUX6+JIDg== +jest-each@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.6.0.tgz#ba0c3a82a8054387016139c733a05242d3d71575" + integrity sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg== +>>>>>>> parent of b864e7e63e... Revert "Merge branch 'master' into 0.58-stable" dependencies: chalk "^2.0.1" - jest-util "^24.0.0-alpha.4" - pretty-format "^24.0.0-alpha.4" + pretty-format "^23.6.0" -jest-environment-jsdom@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.0.0-alpha.4.tgz#07999caaebe6e6b76de9f10cb583b8c113b8d326" - integrity sha512-W+fRQiUChrsuzqn6SiC4FGsfq81sCjsQgBN5k/uLEaP/xYf+ZgtBcYGwT86X1xTYxhP2p16IfezYbkbZwIF6Ug== +jest-each@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.0.0-alpha.6.tgz#9f73236c940ec82fca62992435c671cfa9a871eb" + integrity sha512-l9Dm0R6dKUT+4wRsQTAm52tAlcI0QQPOuLYouN997Ac/0t+dwPH9j/gMxpcSw6GHf3g208jZIPaA/fbR1ZMh9Q== dependencies: - jest-mock "^24.0.0-alpha.4" - jest-util "^24.0.0-alpha.4" + chalk "^2.0.1" + jest-util "^24.0.0-alpha.6" + pretty-format "^24.0.0-alpha.6" + +jest-environment-jsdom@^23.4.0: + version "23.4.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz#056a7952b3fea513ac62a140a2c368c79d9e6023" + integrity sha1-BWp5UrP+pROsYqFAosNox52eYCM= + dependencies: + jest-mock "^23.2.0" + jest-util "^23.4.0" jsdom "^11.5.1" -jest-environment-node@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.0.0-alpha.4.tgz#7eb4922a1dd9def27cc323b3404873e0d73e79b7" - integrity sha512-+mXkdhFzr8LBlfGRGczlcgwBPQI7RIzQWR+bYRB2lkCB6DP8cZoYApUBHjcE9JlPU56LFGcm+GrZFfdTILqFcQ== +jest-environment-jsdom@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.0.0-alpha.6.tgz#a829e26120a056a6c0a4dbdf20b7d2bbb6a306bd" + integrity sha512-wM3z01cTdUzS1/l0k/74AxU01Uzz7KT5s45wEqrJk2YTztbRo8epEUg0rhd7kPwxYoqbEW/fpgszzMKETcS/4A== dependencies: - jest-mock "^24.0.0-alpha.4" - jest-util "^24.0.0-alpha.4" + jest-mock "^24.0.0-alpha.6" + jest-util "^24.0.0-alpha.6" + jsdom "^11.5.1" + +jest-environment-node@^23.4.0: + version "23.4.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.4.0.tgz#57e80ed0841dea303167cce8cd79521debafde10" + integrity sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA= + dependencies: + jest-mock "^23.2.0" + jest-util "^23.4.0" + +jest-environment-node@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.0.0-alpha.6.tgz#81104a599f1db3afc7c2c2c17d1cc2772e3a8870" + integrity sha512-23QNlMuij/DqbJknKste29nOBiK/ly7fN2RkIOkeEBmimTObM8ou0C7k21jkxVnBQOtAjWuHpv0ycz1YK6G5RA== + dependencies: + jest-mock "^24.0.0-alpha.6" + jest-util "^24.0.0-alpha.6" jest-get-type@^22.1.0: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4" integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w== -jest-get-type@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.0.0-alpha.4.tgz#2cef0446d2777229c0c2fa327d0da50507adc037" - integrity sha512-MCjKloodDPKLKCJ9yQ72n+PtJtwSAUG5JRBeSWEXF7DEO2GqwYW/nY94UdmEbug0oc+oxNzsAxNMy7nluWS/Jw== +jest-get-type@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.0.0-alpha.6.tgz#23cc13e4e04c61f001356529675a6aec5a2ef53d" + integrity sha512-U9hmkEfO5dtccZ96iQgbPARorzyVRYWiRnrm5GO4l5iJOpK86fuUsZLjETu+cOpd72RVh00aEm/tVOhZrLizbA== +<<<<<<< HEAD jest-haste-map@24.0.0-alpha.6: version "24.0.0-alpha.6" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.0.0-alpha.6.tgz#fb2c785080f391b923db51846b86840d0d773076" integrity sha512-+NO2HMbjvrG8BC39ieLukdpFrcPhhjCJGhpbHodHNZygH1Tt06WrlNYGpZtWKx/zpf533tCtMQXO/q59JenjNw== +======= +jest-haste-map@24.0.0-alpha.4: + version "24.0.0-alpha.4" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.0.0-alpha.4.tgz#209c13e79a09b4d380d6c46ab12ecc82f02b84ff" + integrity sha512-I2KD+LkcXjQHrPadfE5jx4AQmnxrpziV9NQIrFbytClRJtBKsloL+DlfPdn2sAIIF7y34irlUSB7aybTgxev7A== +>>>>>>> parent of b864e7e63e... Revert "Merge branch 'master' into 0.58-stable" + dependencies: + fb-watchman "^2.0.0" + graceful-fs "^4.1.11" + invariant "^2.2.4" +<<<<<<< HEAD + jest-serializer "^24.0.0-alpha.6" + jest-worker "^24.0.0-alpha.6" +======= + jest-serializer "^24.0.0-alpha.4" + jest-worker "^24.0.0-alpha.4" +>>>>>>> parent of b864e7e63e... Revert "Merge branch 'master' into 0.58-stable" + micromatch "^2.3.11" + sane "^3.0.0" + +jest-haste-map@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.0.0-alpha.6.tgz#fb2c785080f391b923db51846b86840d0d773076" + integrity sha512-+NO2HMbjvrG8BC39ieLukdpFrcPhhjCJGhpbHodHNZygH1Tt06WrlNYGpZtWKx/zpf533tCtMQXO/q59JenjNw== dependencies: fb-watchman "^2.0.0" graceful-fs "^4.1.11" @@ -3527,67 +3651,93 @@ jest-haste-map@24.0.0-alpha.6: micromatch "^2.3.11" sane "^3.0.0" -jest-haste-map@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.0.0-alpha.4.tgz#209c13e79a09b4d380d6c46ab12ecc82f02b84ff" - integrity sha512-I2KD+LkcXjQHrPadfE5jx4AQmnxrpziV9NQIrFbytClRJtBKsloL+DlfPdn2sAIIF7y34irlUSB7aybTgxev7A== - dependencies: - fb-watchman "^2.0.0" - graceful-fs "^4.1.11" - invariant "^2.2.4" - jest-serializer "^24.0.0-alpha.4" - jest-worker "^24.0.0-alpha.4" - micromatch "^2.3.11" - sane "^3.0.0" - -jest-jasmine2@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.0.0-alpha.4.tgz#ce4e24cb1257c6e64e54e6632e74feeb1bb1c3f2" - integrity sha512-LMdRgseO5qU6fEe3LFhPVk6+F5Jn7z1nfKoVvzjPsHJZ0EPwpob7y1VV9pG4riMZkDGpFsAdHOGziaD5/pgnqg== +jest-jasmine2@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz#840e937f848a6c8638df24360ab869cc718592e0" + integrity sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ== dependencies: babel-traverse "^6.0.0" chalk "^2.0.1" co "^4.6.0" - expect "^24.0.0-alpha.4" + expect "^23.6.0" is-generator-fn "^1.0.0" - jest-diff "^24.0.0-alpha.4" - jest-each "^24.0.0-alpha.4" - jest-matcher-utils "^24.0.0-alpha.4" - jest-message-util "^24.0.0-alpha.4" - jest-snapshot "^24.0.0-alpha.4" - jest-util "^24.0.0-alpha.4" - pretty-format "^24.0.0-alpha.4" + jest-diff "^23.6.0" + jest-each "^23.6.0" + jest-matcher-utils "^23.6.0" + jest-message-util "^23.4.0" + jest-snapshot "^23.6.0" + jest-util "^23.4.0" + pretty-format "^23.6.0" -jest-junit@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-5.1.0.tgz#e8e497d810a829bf02783125aab74b5df6caa8fe" - integrity sha512-3EVf1puv2ox5wybQDfLX3AEn3IKOgDV4E76y4pO2hBu46DEtAFZZAm//X1pzPQpqKji0zqgMIzqzF/K+uGAX9A== +jest-jasmine2@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.0.0-alpha.6.tgz#a3ea4ac5e71c366360bfebc96fd2b5a6274b3292" + integrity sha512-u00yGK7La1O2PVCuAhQ7bepRsOJmrdtEZVAzvganBfxqNzEIEeBtsBgv4MrQDb/CqM43XqTtJIo5Cb8AiUsxrw== dependencies: + babel-traverse "^6.0.0" + chalk "^2.0.1" + co "^4.6.0" + expect "^24.0.0-alpha.6" + is-generator-fn "^1.0.0" + jest-diff "^24.0.0-alpha.6" + jest-each "^24.0.0-alpha.6" + jest-matcher-utils "^24.0.0-alpha.6" + jest-message-util "^24.0.0-alpha.6" + jest-snapshot "^24.0.0-alpha.6" + jest-util "^24.0.0-alpha.6" + pretty-format "^24.0.0-alpha.6" + +jest-junit@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-5.2.0.tgz#980401db7aa69999cf117c6d740a8135c22ae379" + integrity sha512-Mdg0Qpdh1Xm/FA1B/mcLlmEmlr3XzH5pZg7MvcAwZhjHijPRd1z/UwYwkwNHmCV7o4ZOWCf77nLu7ZkhHHrtJg== + dependencies: + jest-config "^23.6.0" jest-validate "^23.0.1" mkdirp "^0.5.1" strip-ansi "^4.0.0" xml "^1.0.1" -jest-leak-detector@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.0.0-alpha.4.tgz#a14886af34e0f54c5ae84a58a07e96c353d1c190" - integrity sha512-IsHvueFwNqIc/VWk7V+yox21vGnWZz/6idEqcQAm1aZaVaydmMz3hB/YmvyhiE+qZaQF7HlyvbdS+FJkbaD1iA== +jest-leak-detector@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.0.0-alpha.6.tgz#01f95a351f6689f7162224bbdcde3ccdca6b0a8e" + integrity sha512-jFjDN9F5H47lE8TgM1+K4cR6ep3/cKwx+PP/qnuJpwKeKEp69DyvxXYriExbq54eo3Ed5yq7yH+PsAf6dwllew== dependencies: - pretty-format "^24.0.0-alpha.4" + pretty-format "^24.0.0-alpha.6" -jest-matcher-utils@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.0.0-alpha.4.tgz#a3d4246ef5c8a05097c7df5dfc3bdf36134a9fbb" - integrity sha512-gBDcpSg+4EyYodQV12gVSOPYBcgBE5W+gBmsaMOqHtVQNYvORu9JSK4zeBbR/amC5z1rIsMXOCXRMbN2QepXMA== +jest-matcher-utils@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz#726bcea0c5294261a7417afb6da3186b4b8cac80" + integrity sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog== dependencies: chalk "^2.0.1" - jest-get-type "^24.0.0-alpha.4" - pretty-format "^24.0.0-alpha.4" + jest-get-type "^22.1.0" + pretty-format "^23.6.0" -jest-message-util@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.0.0-alpha.4.tgz#e0d4511ef7f94e4bae89aef5f818ffbc6271a51a" - integrity sha512-K3kh0/SL/0/eZQcKwO96d9toQU2IWRKaYxulb8qWMbEnpW2wjBVB8trMU/3r408knVPesKoxPU4V5VdM5xr53g== +jest-matcher-utils@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.0.0-alpha.6.tgz#124f3363fdf69d3cc940e53ce868156cc8642552" + integrity sha512-kGJff51/cbi9KcRvYW4q+k8iGM/3k07cA+nAdu8FEjsCT+xqs7mhA5TcSWpOc1qwaGftYiz9HxfHJ2gWTwPyCQ== + dependencies: + chalk "^2.0.1" + jest-get-type "^24.0.0-alpha.6" + pretty-format "^24.0.0-alpha.6" + +jest-message-util@^23.4.0: + version "23.4.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f" + integrity sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8= + dependencies: + "@babel/code-frame" "^7.0.0-beta.35" + chalk "^2.0.1" + micromatch "^2.3.11" + slash "^1.0.0" + stack-utils "^1.0.1" + +jest-message-util@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.0.0-alpha.6.tgz#050c9194ca710f8759907e9e12f4c53061ba46fa" + integrity sha512-6wgFC5laPLBR84EioBn1OnYPi9UijhtV6tL+eukIXOqdLfy9eY8GeGTxbphJJJUmSP9g1+wM5Mzk6ycXou4Wlg== dependencies: "@babel/code-frame" "^7.0.0" chalk "^2.0.1" @@ -3595,56 +3745,75 @@ jest-message-util@^24.0.0-alpha.4: slash "^2.0.0" stack-utils "^1.0.1" -jest-mock@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.0.0-alpha.4.tgz#ec74931dedf61885830fb0ae39350438b29beab9" - integrity sha512-sImD6rT87SNuIhnUvS8e+lSCuaGAJcpGOqZFE2epXelGqhqriYLViMC5eP5b1az5D1CaOkQWx2AZAQg8mGfKtw== +jest-mock@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134" + integrity sha1-rRxg8p6HGdR8JuETgJi20YsmETQ= -jest-regex-util@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.0.0-alpha.4.tgz#acbac6df4d895a9d3008595efbac5f759b9f69c3" - integrity sha512-zjkN2+Ue4ryS9n7OCXshqtG/oa3f4xXqOeSyxoTmGl5vQ/zAurlHnKA/x54BZtgwFxWLumEuNeyDX85sakwItQ== +jest-mock@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.0.0-alpha.6.tgz#26ee1fe581c4ee71f604ffd4fae6743d8d3a899d" + integrity sha512-1wrKUhTwSi4BNk3ztjbS6IgBrPyWno6ClHekSHefB82PbKtZAJ2PbU2sTAqkBP/OZetFPIe3BgaHuoumsuZazg== -jest-resolve-dependencies@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.0.0-alpha.4.tgz#4b9bebc99a87d1f03c6fa54904f48a785bd00d80" - integrity sha512-0Le1dW8eOsMbMpiMCg9blxoRNzwhqZKEjuvE6hT+msZQNdiHbPS9qqCnUGPs6SHLuIWTB3qKGEgjsJHDrckSBg== +jest-regex-util@^23.3.0: + version "23.3.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5" + integrity sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U= + +jest-regex-util@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.0.0-alpha.6.tgz#290684073641e2be4c0a5ddaaf4450d7956f7b57" + integrity sha512-kfV9Z/Sfj/PRcuJLrnk4IoOC0GDfzEn+GmPZ2PI8ql+xa3EYq/+bM75SnbvM6axLaaiLavxPZfoAY5UK07N1Wg== + +jest-resolve-dependencies@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.0.0-alpha.6.tgz#a345714786dfed646ca0e1d69c03e99f54c7f415" + integrity sha512-llBtvVgESLt7xPK3NGVYNb7FSr15GzDXJPkYyhvXV7ox1/8hSurWieKis19tWoqkC81zTeQNM/65CAcv7EPVug== dependencies: - jest-regex-util "^24.0.0-alpha.4" - jest-snapshot "^24.0.0-alpha.4" + jest-regex-util "^24.0.0-alpha.6" + jest-snapshot "^24.0.0-alpha.6" -jest-resolve@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.0.0-alpha.4.tgz#9073d5635d1088fa01b1239be8e45ffca567b50d" - integrity sha512-oXqZgPErAVz6QRRQBshPcOpd8d4z9lyEuxoS4+6ifcw0x3bWu0u50fhqqivJrBcX195Ul1kUgsE8zHisQEG6UA== +jest-resolve@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.6.0.tgz#cf1d1a24ce7ee7b23d661c33ba2150f3aebfa0ae" + integrity sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA== dependencies: browser-resolve "^1.11.3" chalk "^2.0.1" realpath-native "^1.0.0" -jest-runner@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.0.0-alpha.4.tgz#6134e33d75aa26acff07d3ec71a892f8cc1c581a" - integrity sha512-HYlraLrQs2mwAQSJM02ozNWDjTXxpIj8QxcMgXhZkfD32VNrR6PR+/c1d76hQ2S0Y6NEkPonesG5fM3l0uV/YA== +jest-resolve@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.0.0-alpha.6.tgz#652abbae048b531311315aa546c5c8ad663ea6a2" + integrity sha512-+RFkYvG5DJ6A2R2r8zrJX3Hv9byIM0Ytrib2mpc8FNrLAe5fEEmaC+GdcVx5b0ybh1F7ZPoFNSoEWKZpK9+76A== + dependencies: + browser-resolve "^1.11.3" + chalk "^2.0.1" + realpath-native "^1.0.0" + +jest-runner@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.0.0-alpha.6.tgz#520692dfc07de1cfe4261c806a9b8f0225bd16df" + integrity sha512-EeQ4pkfwPakGREYcKi8oJc/OWmfkld7AaNDkClbKuaKUyS0gkGNXUc9YijvlyA8VBXYTDqMRs8E8HoWKsW5LTw== dependencies: exit "^0.1.2" graceful-fs "^4.1.11" - jest-config "^24.0.0-alpha.4" - jest-docblock "^24.0.0-alpha.4" - jest-haste-map "^24.0.0-alpha.4" - jest-jasmine2 "^24.0.0-alpha.4" - jest-leak-detector "^24.0.0-alpha.4" - jest-message-util "^24.0.0-alpha.4" - jest-runtime "^24.0.0-alpha.4" - jest-util "^24.0.0-alpha.4" - jest-worker "^24.0.0-alpha.4" + jest-config "^24.0.0-alpha.6" + jest-docblock "^24.0.0-alpha.6" + jest-haste-map "^24.0.0-alpha.6" + jest-jasmine2 "^24.0.0-alpha.6" + jest-leak-detector "^24.0.0-alpha.6" + jest-message-util "^24.0.0-alpha.6" + jest-runtime "^24.0.0-alpha.6" + jest-util "^24.0.0-alpha.6" + jest-worker "^24.0.0-alpha.6" source-map-support "^0.5.6" throat "^4.0.0" -jest-runtime@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.0.0-alpha.4.tgz#f8cb479c5a21a4ec23eadf3d3993afd4778e9a0a" - integrity sha512-3SjUWFB3U6WrhK5Av0kCTZLTI+wjvjDsYVwsE8EeTRt9kGnELm+WezUQuHtKSun0Ygvi0xZLdAl/E0X1hHaeow== +jest-runtime@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.0.0-alpha.6.tgz#3c9e5d032324b95360736115a8182639d4120e82" + integrity sha512-91VTDRHcrvKFQRI9NeVe2+PfMekV0Bo3fNFArfmISpx3fOLqt96AbFWltAFMVkaLTLuVizyYBkKFXCfYYytQ2Q== dependencies: babel-core "^6.0.0" babel-plugin-istanbul "^4.1.6" @@ -3654,14 +3823,14 @@ jest-runtime@^24.0.0-alpha.4: fast-json-stable-stringify "^2.0.0" glob "^7.1.3" graceful-fs "^4.1.11" - jest-config "^24.0.0-alpha.4" - jest-haste-map "^24.0.0-alpha.4" - jest-message-util "^24.0.0-alpha.4" - jest-regex-util "^24.0.0-alpha.4" - jest-resolve "^24.0.0-alpha.4" - jest-snapshot "^24.0.0-alpha.4" - jest-util "^24.0.0-alpha.4" - jest-validate "^24.0.0-alpha.4" + jest-config "^24.0.0-alpha.6" + jest-haste-map "^24.0.0-alpha.6" + jest-message-util "^24.0.0-alpha.6" + jest-regex-util "^24.0.0-alpha.6" + jest-resolve "^24.0.0-alpha.6" + jest-snapshot "^24.0.0-alpha.6" + jest-util "^24.0.0-alpha.6" + jest-validate "^24.0.0-alpha.6" micromatch "^2.3.11" realpath-native "^1.0.0" slash "^2.0.0" @@ -3669,47 +3838,86 @@ jest-runtime@^24.0.0-alpha.4: write-file-atomic "^2.1.0" yargs "^12.0.2" +<<<<<<< HEAD jest-serializer@24.0.0-alpha.6, jest-serializer@^24.0.0-alpha.6: version "24.0.0-alpha.6" resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.0.0-alpha.6.tgz#27d2fee4b1a85698717a30c3ec2ab80767312597" integrity sha512-IPA5T6/GhlE6dedSk7Cd7YfuORnYjN0VD5iJVFn1Q81RJjpj++Hen5kJbKcg547vXsQ1TddV15qOA/zeIfOCLw== jest-serializer@^24.0.0-alpha.4: +======= +jest-serializer@24.0.0-alpha.4: +>>>>>>> parent of b864e7e63e... Revert "Merge branch 'master' into 0.58-stable" version "24.0.0-alpha.4" resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.0.0-alpha.4.tgz#939c31155b95bebc1ef6f76ae34dbf2c06046e52" integrity sha512-g/hO2JM6c96wGzbiQNdbOrLlx8p+cA8W8+EwFkKtUlWcmBCxbsZb8TaIK2FLfvxCTKPwMhBujhw46GM5WppAsQ== -jest-snapshot@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.0.0-alpha.4.tgz#be3d515a38cd75021d2814bc59fdc1dce03f58b8" - integrity sha512-RnNyMfG7Esgykkru9n9BBlR6CiXEdvrdiZSw2+i3LKw7rO5/jjG4w2SDcTM/Rh2j6EEhWQn5Fhr7T/PAUNybiw== +jest-serializer@^24.0.0-alpha.4, jest-serializer@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.0.0-alpha.6.tgz#27d2fee4b1a85698717a30c3ec2ab80767312597" + integrity sha512-IPA5T6/GhlE6dedSk7Cd7YfuORnYjN0VD5iJVFn1Q81RJjpj++Hen5kJbKcg547vXsQ1TddV15qOA/zeIfOCLw== + +jest-snapshot@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.6.0.tgz#f9c2625d1b18acda01ec2d2b826c0ce58a5aa17a" + integrity sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg== dependencies: babel-types "^6.0.0" chalk "^2.0.1" - jest-diff "^24.0.0-alpha.4" - jest-matcher-utils "^24.0.0-alpha.4" - jest-message-util "^24.0.0-alpha.4" - jest-resolve "^24.0.0-alpha.4" + jest-diff "^23.6.0" + jest-matcher-utils "^23.6.0" + jest-message-util "^23.4.0" + jest-resolve "^23.6.0" mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^24.0.0-alpha.4" + pretty-format "^23.6.0" semver "^5.5.0" -jest-util@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.0.0-alpha.4.tgz#0021abb2b09c1fea68dc748f6bf3eb93789b5cb4" - integrity sha512-2NYByhPpApO3BwtdWFxhOzjUl70EU5yRtJiqRv3dbsjIKV9pRPdvHUr7miz0GsZkeUyCehrzwJgaWL5iNa3T5Q== +jest-snapshot@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.0.0-alpha.6.tgz#89659179ccd8f47e4476850f04e9810e6ea9a425" + integrity sha512-TzNqLIwje0rh637ibAoD+BO0rTngznhUnlmM1AcCIxb663oLfxzSjMIhxwcQ4bhATlsrluerNfGeqp07DEWkPQ== + dependencies: + babel-types "^6.0.0" + chalk "^2.0.1" + jest-diff "^24.0.0-alpha.6" + jest-matcher-utils "^24.0.0-alpha.6" + jest-message-util "^24.0.0-alpha.6" + jest-resolve "^24.0.0-alpha.6" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + pretty-format "^24.0.0-alpha.6" + semver "^5.5.0" + +jest-util@^23.4.0: + version "23.4.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.4.0.tgz#4d063cb927baf0a23831ff61bec2cbbf49793561" + integrity sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE= dependencies: callsites "^2.0.0" chalk "^2.0.1" graceful-fs "^4.1.11" is-ci "^1.0.10" - jest-message-util "^24.0.0-alpha.4" + jest-message-util "^23.4.0" + mkdirp "^0.5.1" + slash "^1.0.0" + source-map "^0.6.0" + +jest-util@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.0.0-alpha.6.tgz#974ce25422e1b545d225b90ac0bdcd5453dfd634" + integrity sha512-u8iGWbLABtJIJeZ0oB01n0BBUuDQT0iQvNXYN0+9WTKO+pHgv37ItYAbMQNM0NjIZig0l410VoFeWqg1KJyxpw== + dependencies: + callsites "^2.0.0" + chalk "^2.0.1" + graceful-fs "^4.1.11" + is-ci "^1.0.10" + jest-message-util "^24.0.0-alpha.6" mkdirp "^0.5.1" slash "^2.0.0" source-map "^0.6.0" -jest-validate@^23.0.1: +jest-validate@^23.0.1, jest-validate@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474" integrity sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A== @@ -3719,25 +3927,26 @@ jest-validate@^23.0.1: leven "^2.1.0" pretty-format "^23.6.0" -jest-validate@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.0.0-alpha.4.tgz#c66cc7d771a17c6441e31d0d4f26f71090e88e47" - integrity sha512-zgkrTlFv0mQjbxAGus2GXEfgZex3iIlZ2xEq/rZqZ3np/cegDPotlC6MckmSRLqHFAzrwe3SRrreXZUSApHJGQ== +jest-validate@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.0.0-alpha.6.tgz#19f8a9ac395199c9b4965297a159caf7024f4713" + integrity sha512-E6N3xiZ0EQais9WW3alpWO3NNGxvrbbwkXGPLimpSKEwpz29ezL93C4XFPnzZ2Xet+7I5SJxrvgOYkFJLreAdQ== dependencies: chalk "^2.0.1" - jest-get-type "^24.0.0-alpha.4" + jest-get-type "^24.0.0-alpha.6" leven "^2.1.0" - pretty-format "^24.0.0-alpha.4" + pretty-format "^24.0.0-alpha.6" -jest-watcher@^24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.0.0-alpha.4.tgz#71ac48ccb510cedaaa1156a637a1bacdc837fdf8" - integrity sha512-RDL1n5BAbnseRTZQDAlBoLmjla3sDx1LQuadFa7a73ujxPG9nQyDusVAnVf8JU684zlNMNpQ4BdK50GAQZW0TQ== +jest-watcher@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.0.0-alpha.6.tgz#e54918ae31bfed17581fa3978afbe5cf20e9c512" + integrity sha512-CxL49DV+dNa7ET1OAFGoZd0F1Bt8dgdwyycV9znLkB+RJrVm+kh8KPF24LM5p66f5oQyhAfuxO71u6eRPYkSGg== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.1" string-length "^2.0.0" +<<<<<<< HEAD jest-worker@24.0.0-alpha.6, jest-worker@^24.0.0-alpha.6: version "24.0.0-alpha.6" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0-alpha.6.tgz#463681b92c117c57107135c14b9b9d6cd51d80ce" @@ -3746,19 +3955,29 @@ jest-worker@24.0.0-alpha.6, jest-worker@^24.0.0-alpha.6: merge-stream "^1.0.1" jest-worker@^24.0.0-alpha.4: +======= +jest-worker@24.0.0-alpha.4: +>>>>>>> parent of b864e7e63e... Revert "Merge branch 'master' into 0.58-stable" version "24.0.0-alpha.4" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0-alpha.4.tgz#6766d11b66e7b2d61f79711d159125657084d021" integrity sha512-kZYIxqwkvaQggTBiOnoGoI7pyHAsCgFg+1C9NCSpkaQOLQ/MpEdY6cTPTbLwWdtzSloWnECAAj8p9es2VLQd/Q== dependencies: merge-stream "^1.0.1" -jest@24.0.0-alpha.4: - version "24.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/jest/-/jest-24.0.0-alpha.4.tgz#fc57357ec1a4e12700616569f2ec1b3d2ab3c87f" - integrity sha512-peUdEeRk23o1ntvnoQc6CqOrhIlqXMK88tXXf/MepL6uK17+w2paC+ut0KpdAJ4rNAIoIlN8TLyXspiFDM3w0w== +jest-worker@^24.0.0-alpha.4, jest-worker@^24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0-alpha.6.tgz#463681b92c117c57107135c14b9b9d6cd51d80ce" + integrity sha512-iXtH7MR9bjWlNnlnRBcrBRrb4cSVxML96La5vsnmBvDI+mJnkP5uEt6Fgpo5Y8f3z9y2Rd7wuPnKRxqQsiU/dA== + dependencies: + merge-stream "^1.0.1" + +jest@24.0.0-alpha.6: + version "24.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/jest/-/jest-24.0.0-alpha.6.tgz#2635f90c5f5deaeb47e9c0f3e4ab3ed290f59bf4" + integrity sha512-2mVzUbDspFFZFB0bmT4cEbWmnMqz4CGEY1EiNCngO//NL+OSEqXPLwV/wdFWwLb3QeYm7TSgTE7Mf18ZAHSrhw== dependencies: import-local "^2.0.0" - jest-cli "^24.0.0-alpha.4" + jest-cli "^24.0.0-alpha.6" "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" @@ -4130,9 +4349,15 @@ merge@^1.2.0: integrity sha1-dTHjnUlJwoGma4xabgJl6LBYlNo= metro-babel-register@^0.49.1: +<<<<<<< HEAD version "0.49.2" resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.49.2.tgz#746c73311135bd6c2af4d83c2cc6c5cbcf0e8a65" integrity sha512-xx+SNwJ3Dl4MmSNn1RpUGc7b5pyTxXdpqpE7Fuk499rZffypVI1uhKOjKt2lwQhlyD03sXuvB/m3RdEg3mivWg== +======= + version "0.49.1" + resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.49.1.tgz#b84d81690d41aab83ab288745863e0e21ad761c3" + integrity sha512-hBVAbX5xUPlEy0aKRvGCR4Yn309oGwKl3An6sOLHvtZB4z45eDVbaBSSaMW2q8IGwahdrunYdWtaLVESpBoX6Q== +>>>>>>> parent of b864e7e63e... Revert "Merge branch 'master' into 0.58-stable" dependencies: "@babel/core" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" @@ -4147,6 +4372,7 @@ metro-babel-register@^0.49.1: core-js "^2.2.2" escape-string-regexp "^1.0.5" +<<<<<<< HEAD metro-babel7-plugin-react-transform@0.49.2: version "0.49.2" resolved "https://registry.yarnpkg.com/metro-babel7-plugin-react-transform/-/metro-babel7-plugin-react-transform-0.49.2.tgz#d4c43faa6f2b91cc1b244a36a5d708ae8d39dbb2" @@ -4201,6 +4427,62 @@ metro-react-native-babel-preset@0.49.2: version "0.49.2" resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.49.2.tgz#8d53610e044e0c9a53a03d307e1c51f9e8577abc" integrity sha512-N0+4ramShYCHSAVEPUNWIZuKZskWj8/RDSoinhadHpdpHORMbMxLkexSOVHLluB+XFQ+DENLEx5oVPYwOlENBA== +======= +metro-babel7-plugin-react-transform@0.49.1: + version "0.49.1" + resolved "https://registry.yarnpkg.com/metro-babel7-plugin-react-transform/-/metro-babel7-plugin-react-transform-0.49.1.tgz#eb34c351abe217df942113d95752a0989f4aa38e" + integrity sha512-54kIDUaPNC0we/mm4L0xHNcsQOu79ojTIsPZSciiAX2z5fRt7IBxaaV2EaQ/nSDQ5xBzDXQ0kbM7oLliq7IuPw== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + +metro-cache@0.49.1: + version "0.49.1" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.49.1.tgz#eebbf64d1b7711ca311444727e1e7a0d8cf3ebe3" + integrity sha512-6+B4E8XLUXocogWfMGg+lEpAxEdSsjzcu6Emr+ORhEnBY7P2nln951SHJ2MXYGGyrW3j85awQoj5xUqZUA44sg== + dependencies: + jest-serializer "24.0.0-alpha.4" + metro-core "0.49.1" + mkdirp "^0.5.1" + rimraf "^2.5.4" + +metro-config@0.49.1: + version "0.49.1" + resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.49.1.tgz#4db688461bc9a4bdebc884e1e65e9f22c172aadd" + integrity sha512-mFA9TZOayRZWcB1c6qE4HKNsQOnPfBzsc+buNlGW4/eQBZb1GKl7TLMp8izV5Xwzmq0QkNuM5IVxqXIIC3ydHA== + dependencies: + cosmiconfig "^5.0.5" + metro "0.49.1" + metro-cache "0.49.1" + metro-core "0.49.1" + pretty-format "24.0.0-alpha.4" + +metro-core@0.49.1, metro-core@^0.49.1: + version "0.49.1" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.49.1.tgz#552ccbd21273fb4a6ae88b1407a79d84966e47cc" + integrity sha512-YcoCqPpKL/5Zto3bG2BM/WFt/P2bP7hVwEFLo50wuX6iE3SHYBjzgPeYCY7oc2IuqT0z6igxqdbHaLLrEqQg7w== + dependencies: + jest-haste-map "24.0.0-alpha.4" + lodash.throttle "^4.1.1" + metro-resolver "0.49.1" + wordwrap "^1.0.0" + +metro-memory-fs@^0.49.1: + version "0.49.1" + resolved "https://registry.yarnpkg.com/metro-memory-fs/-/metro-memory-fs-0.49.1.tgz#e1f107c9d6b01492e4bf7d3261e59fa81373dee9" + integrity sha512-x7BRfcZ4J9N9BKHnofZq0+BwZ9YLVsiaCb3gC69/ibHpZGIHrfq5y5mEtidnQ00TLyT4t+otnislvsuZRofvxg== + +metro-minify-uglify@0.49.1: + version "0.49.1" + resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.49.1.tgz#4a06d9c908872a6080ec649e9206c42c20fd5d44" + integrity sha512-OqtakK7nEwjoGVhNL5BVxcveHK7DeICrkpI9JYfEVAEwyBC8FkQkvOVWbU4O2yX2Hcz/TuTjnGgeKKkCZI4lGw== + dependencies: + uglify-es "^3.1.9" + +metro-react-native-babel-preset@0.49.1: + version "0.49.1" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.49.1.tgz#6df6195599055fe6010b81ad0e5a47c199e6a9c0" + integrity sha512-GYg2Sl7uVoRIvU4d3aN6UB65/aHxEU9GmjzFc7NWMQ1zkMZeRvcJaqZ5ijurNQLgN1TyEsIsKrV+3/KV9Xxnog== +>>>>>>> parent of b864e7e63e... Revert "Merge branch 'master' into 0.58-stable" dependencies: "@babel/plugin-proposal-class-properties" "^7.0.0" "@babel/plugin-proposal-export-default-from" "^7.0.0" @@ -4235,6 +4517,7 @@ metro-react-native-babel-preset@0.49.2: "@babel/plugin-transform-typescript" "^7.0.0" "@babel/plugin-transform-unicode-regex" "^7.0.0" "@babel/template" "^7.0.0" +<<<<<<< HEAD metro-babel7-plugin-react-transform "0.49.2" react-transform-hmr "^1.0.4" @@ -4256,6 +4539,29 @@ metro@0.49.2, metro@^0.49.1: version "0.49.2" resolved "https://registry.yarnpkg.com/metro/-/metro-0.49.2.tgz#0fd615d9f451893a0816721b46e94dcf49dda0f6" integrity sha512-GSNMigeQq+QQ++qwEnWx0hjtYCZIvogn4JuqpKqOyVqNbg+aIheJPvxfDzjF9OXM5WHuNsTfGLW8n5kbUmQJSg== +======= + metro-babel7-plugin-react-transform "0.49.1" + react-transform-hmr "^1.0.4" + +metro-resolver@0.49.1: + version "0.49.1" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.49.1.tgz#f8bd37d664567310e5b39d89b735bdc7aa09b10b" + integrity sha512-DuOA9Ev8WrEandVBx5eeqT2wHYxQ8+1Ici6zzY3nKLgEO8V9tyealYiYcHeGXOVo1h1nu66UIrcPrZSdcNXWCA== + dependencies: + absolute-path "^0.0.0" + +metro-source-map@0.49.1: + version "0.49.1" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.49.1.tgz#2e216830f103a351d2d72fc48540eb7fcd317423" + integrity sha512-18efANoSG0gFrH9L1y5xyA9ZK1DycTJWb3NxlUAJxs2nZIvdPYfobrIeNw31SAmbdaw6ZSzuczS7IDOdJmde8Q== + dependencies: + source-map "^0.5.6" + +metro@0.49.1, metro@^0.49.1: + version "0.49.1" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.49.1.tgz#a59e00901640a4c4a856ad6f6129634cdb55e31e" + integrity sha512-TJbeL7lPs7CS4Ja7tLUmYPfTQa0TmtNBgiSTOlV54iD6pPjJrJeJgiJGeDfl8cPXXd6xNfcopX5AGg9nh2eCnw== +>>>>>>> parent of b864e7e63e... Revert "Merge branch 'master' into 0.58-stable" dependencies: "@babel/core" "^7.0.0" "@babel/generator" "^7.0.0" @@ -4278,6 +4584,7 @@ metro@0.49.2, metro@^0.49.1: fs-extra "^1.0.0" graceful-fs "^4.1.3" image-size "^0.6.0" +<<<<<<< HEAD jest-haste-map "24.0.0-alpha.6" jest-worker "24.0.0-alpha.6" json-stable-stringify "^1.0.1" @@ -4290,6 +4597,20 @@ metro@0.49.2, metro@^0.49.1: metro-react-native-babel-preset "0.49.2" metro-resolver "0.49.2" metro-source-map "0.49.2" +======= + jest-haste-map "24.0.0-alpha.4" + jest-worker "24.0.0-alpha.4" + json-stable-stringify "^1.0.1" + lodash.throttle "^4.1.1" + merge-stream "^1.0.1" + metro-cache "0.49.1" + metro-config "0.49.1" + metro-core "0.49.1" + metro-minify-uglify "0.49.1" + metro-react-native-babel-preset "0.49.1" + metro-resolver "0.49.1" + metro-source-map "0.49.1" +>>>>>>> parent of b864e7e63e... Revert "Merge branch 'master' into 0.58-stable" mime-types "2.1.11" mkdirp "^0.5.1" node-fetch "^2.2.0" @@ -5068,7 +5389,7 @@ prettier@1.13.6: resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.6.tgz#00ae0b777ad92f81a9e7a1df2f0470b6dab0cb44" integrity sha512-p5eqCNiohWZN++7aJXUVj0JgLqHCPLf9GLIcLBHGNWs4Y9FJOPs6+KNO2WT0udJIQJTbeZFrJkjzjcb8fkAYYQ== -pretty-format@24.0.0-alpha.4, pretty-format@^24.0.0-alpha.4: +pretty-format@24.0.0-alpha.4: version "24.0.0-alpha.4" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.0.0-alpha.4.tgz#cc1f7497e2496b71f8ad99f1526096e515fada03" integrity sha512-icvbBt3XlLEVqPHdHwR2Ou9+hezS9Eccd+mA+fXfOU7T9t7ClOpq2HgCwlyw+3WogccCubKWnmzyrA/3ZZ/aOA== @@ -5076,7 +5397,11 @@ pretty-format@24.0.0-alpha.4, pretty-format@^24.0.0-alpha.4: ansi-regex "^4.0.0" ansi-styles "^3.2.0" +<<<<<<< HEAD pretty-format@24.0.0-alpha.6: +======= +pretty-format@24.0.0-alpha.6, pretty-format@^24.0.0-alpha.6: +>>>>>>> parent of b864e7e63e... Revert "Merge branch 'master' into 0.58-stable" version "24.0.0-alpha.6" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.0.0-alpha.6.tgz#25ad2fa46b342d6278bf241c5d2114d4376fbac1" integrity sha512-zG2m6YJeuzwBFqb5EIdmwYVf30sap+iMRuYNPytOccEXZMAJbPIFGKVJ/U0WjQegmnQbRo9CI7j6j3HtDaifiA== @@ -5215,10 +5540,10 @@ react-deep-force-update@^1.0.0: resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.2.tgz#3d2ae45c2c9040cbb1772be52f8ea1ade6ca2ee1" integrity sha512-WUSQJ4P/wWcusaH+zZmbECOk7H5N2pOIl0vzheeornkIMhu+qrNdGFm0bDZLCb0hSF0jf/kH1SgkNGfBdTc4wA== -react-devtools-core@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-3.4.0.tgz#6b61594dce01b129a9e0b44b5bc4952f8f59ceec" - integrity sha512-yV3LLhoRwbfcQyVPNwb1EZ9W7CGu+kX2EqyZ3Cl5C+cbXcb6FJ3YSeeBt9BQB+hjyjRMBjQSKqnpPS6OMSEUow== +react-devtools-core@^3.4.2: + version "3.4.2" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-3.4.2.tgz#4888b428f1db9a3078fdff66a1da14f71fb1680e" + integrity sha512-1pqbxenMeOiVPLf5Fm69woc+Q/pb/lLfWCizJuVJQDm9v7x0fcr76VMcq6Q30Onv3ikkfrlAQgOcOdCk/0t5tA== dependencies: shell-quote "^1.6.1" ws "^3.3.1"