From c355a34de107befd26bc495272b91c11957f3fd0 Mon Sep 17 00:00:00 2001 From: hotchemi Date: Sat, 13 Jan 2018 17:12:00 -0800 Subject: [PATCH 01/25] Fix links to beginner friendly issues Summary: While I was reading README I found wrong links to `beginner friendly issues` so just fixed them. Closes https://github.com/facebook/react-native/pull/17579 Differential Revision: D6719845 Pulled By: shergin fbshipit-source-id: 5c3290f70efbd8c40c2d3482c23c198ab45d510e --- CONTRIBUTING.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9c160039726402..34a94428f2542b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -78,7 +78,7 @@ Working on your first Pull Request? You can learn how from this free video serie [**How to Contribute to an Open Source Project on GitHub**](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github) -We have a list of [beginner friendly issues](https://github.com/facebook/react-native/labels/Good%20First%20Task) to help you get your feet wet in the React Native codebase and familiar with our contribution process. This is a great place to get started. +We have a list of [beginner friendly issues](https://github.com/facebook/react-native/labels/Good%20first%20issue) to help you get your feet wet in the React Native codebase and familiar with our contribution process. This is a great place to get started. ### Proposing a change diff --git a/README.md b/README.md index 42b0f72c8e5052..014138ab3e28cd 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ Read our [contributing guide](https://facebook.github.io/react-native/docs/contr ### Beginner Friendly Bugs -We have a list of [beginner friendly issues](https://github.com/facebook/react-native/labels/Good%20First%20Issue) to help you get your feet wet in the React Native codebase and familiar with our contribution process. This is a great place to get started. +We have a list of [beginner friendly issues](https://github.com/facebook/react-native/labels/Good%20first%20issue) to help you get your feet wet in the React Native codebase and familiar with our contribution process. This is a great place to get started. --- From 83ed9d170b8fd750a345fc608ec69db2fe3ca9b2 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Sun, 14 Jan 2018 10:42:04 -0800 Subject: [PATCH 02/25] RN: Create SyntheticEvent and ScrollEvent Types Reviewed By: sahrens Differential Revision: D6720478 fbshipit-source-id: b542bd50db7cd7085aecce8b986c6922bfb24a43 --- Libraries/Types/CoreEventTypes.js | 42 ++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/Libraries/Types/CoreEventTypes.js b/Libraries/Types/CoreEventTypes.js index e05e4e3b2c5d90..ea2e5ec16f6344 100644 --- a/Libraries/Types/CoreEventTypes.js +++ b/Libraries/Types/CoreEventTypes.js @@ -26,4 +26,44 @@ export type LayoutEvent = {| +persist: () => void, |}; -export type PressEvent = Object; +export type SyntheticEvent = {| + +bubbles: ?boolean, + +cancelable: ?boolean, + +currentTarget: number, + +defaultPrevented: ?boolean, + +dispatchConfig: {| + +registrationName: string, + |}, + +eventPhase: ?number, + +isDefaultPrevented: () => boolean, + +isPropagationStopped: () => boolean, + +isTrusted: ?boolean, + +nativeEvent: T, + +target: ?number, + +timeStamp: number, + +type: ?string, +|}; + +export type PressEvent = SyntheticEvent; + +export type ScrollEvent = SyntheticEvent<{| + +contentInset: {| + +bottom: number, + +left: number, + +right: number, + +top: number, + |}, + +contentOffset: {| + +y: number, + +x: number, + |}, + +contentSize: {| + +height: number, + +width: number, + |}, + +layoutMeasurement: {| + +height: number, + +width: number, + |}, + +zoomScale: number, +|}>; From e758cb7f397b37b5621a4e0afcabc1c74443bc06 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sun, 14 Jan 2018 19:32:22 -0800 Subject: [PATCH 03/25] Prettier for TextInput.js Summary: Trivial. Reviewed By: sahrens Differential Revision: D6690929 fbshipit-source-id: 82906cd4a0eec320f998661ed48b9352b9b72670 --- Libraries/Components/TextInput/TextInput.js | 100 ++++++++++++-------- 1 file changed, 62 insertions(+), 38 deletions(-) diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index ddd509ef0fd0dd..90c46b5e017c9b 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -8,6 +8,7 @@ * * @providesModule TextInput * @flow + * @format */ 'use strict'; @@ -50,8 +51,14 @@ const onlyMultiline = { if (Platform.OS === 'android') { var AndroidTextInput = requireNativeComponent('AndroidTextInput', null); } else if (Platform.OS === 'ios') { - var RCTMultilineTextInputView = requireNativeComponent('RCTMultilineTextInputView', null); - var RCTSinglelineTextInputView = requireNativeComponent('RCTSinglelineTextInputView', null); + var RCTMultilineTextInputView = requireNativeComponent( + 'RCTMultilineTextInputView', + null, + ); + var RCTSinglelineTextInputView = requireNativeComponent( + 'RCTSinglelineTextInputView', + null, + ); } type Event = Object; @@ -279,11 +286,7 @@ const TextInput = createReactClass({ * Determines the color of the keyboard. * @platform ios */ - keyboardAppearance: PropTypes.oneOf([ - 'default', - 'light', - 'dark', - ]), + keyboardAppearance: PropTypes.oneOf(['default', 'light', 'dark']), /** * Determines how the return key should look. On Android you can also use * `returnKeyLabel`. @@ -448,8 +451,8 @@ const TextInput = createReactClass({ */ secureTextEntry: PropTypes.bool, /** - * The highlight and cursor color of the text input. - */ + * The highlight and cursor color of the text input. + */ selectionColor: ColorPropType, /** * An instance of `DocumentSelectionState`, this is some state that is responsible for @@ -603,8 +606,10 @@ const TextInput = createReactClass({ * Returns `true` if the input is currently focused; `false` otherwise. */ isFocused: function(): boolean { - return TextInputState.currentlyFocusedField() === - ReactNative.findNodeHandle(this._inputRef); + return ( + TextInputState.currentlyFocusedField() === + ReactNative.findNodeHandle(this._inputRef) + ); }, contextTypes: { @@ -627,13 +632,13 @@ const TextInput = createReactClass({ } this._focusSubscription = this.context.focusEmitter.addListener( 'focus', - (el) => { + el => { if (this === el) { this.requestAnimationFrame(this.focus); } else if (this.isFocused()) { this.blur(); } - } + }, ); if (this.props.autoFocus) { this.context.onFocusRequested(this); @@ -652,7 +657,7 @@ const TextInput = createReactClass({ }, childContextTypes: { - isInAParentText: PropTypes.bool + isInAParentText: PropTypes.bool, }, /** @@ -671,13 +676,11 @@ const TextInput = createReactClass({ }, _getText: function(): ?string { - return typeof this.props.value === 'string' ? - this.props.value : - ( - typeof this.props.defaultValue === 'string' ? - this.props.defaultValue : - '' - ); + return typeof this.props.value === 'string' + ? this.props.value + : typeof this.props.defaultValue === 'string' + ? this.props.defaultValue + : ''; }, _setNativeRef: function(ref: any) { @@ -691,7 +694,10 @@ const TextInput = createReactClass({ props.style = [this.props.style]; if (props.selection && props.selection.end == null) { - props.selection = {start: props.selection.start, end: props.selection.start}; + props.selection = { + start: props.selection.start, + end: props.selection.start, + }; } if (!props.multiline) { @@ -699,13 +705,15 @@ const TextInput = createReactClass({ for (var propKey in onlyMultiline) { if (props[propKey]) { const error = new Error( - 'TextInput prop `' + propKey + '` is only supported with multiline.' + 'TextInput prop `' + + propKey + + '` is only supported with multiline.', ); warning(false, '%s', error.stack); } } } - textContainer = + textContainer = ( ; + /> + ); } else { var children = props.children; var childCount = 0; React.Children.forEach(children, () => ++childCount); invariant( !(props.value && childCount), - 'Cannot specify both value and children.' + 'Cannot specify both value and children.', ); if (childCount >= 1) { - children = {children}; + children = ( + + {children} + + ); } if (props.inputView) { children = [children, props.inputView]; } props.style.unshift(styles.multilineInput); - textContainer = + textContainer = ( ; + /> + ); } return ( @@ -779,17 +793,20 @@ const TextInput = createReactClass({ React.Children.forEach(children, () => ++childCount); invariant( !(this.props.value && childCount), - 'Cannot specify both value and children.' + 'Cannot specify both value and children.', ); if (childCount > 1) { children = {children}; } if (props.selection && props.selection.end == null) { - props.selection = {start: props.selection.start, end: props.selection.start}; + props.selection = { + start: props.selection.start, + end: props.selection.start, + }; } - const textContainer = + const textContainer = ( ; + /> + ); return ( Date: Sun, 14 Jan 2018 19:32:24 -0800 Subject: [PATCH 04/25] Prettier for Text.js Summary: Trivial. Reviewed By: sahrens Differential Revision: D6715229 fbshipit-source-id: 13ae84920c98e0d8e8f1b64aeadfa770b64ea3b4 --- Libraries/Text/Text.js | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 7f9907e76e26ad..6268e59cc59391 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -8,6 +8,7 @@ * * @providesModule Text * @flow + * @format */ 'use strict'; @@ -422,10 +423,10 @@ const Text = createReactClass({ return {isInAParentText: true}; }, childContextTypes: { - isInAParentText: PropTypes.bool + isInAParentText: PropTypes.bool, }, contextTypes: { - isInAParentText: PropTypes.bool + isInAParentText: PropTypes.bool, }, /** * Only assigned if touch is needed. @@ -448,10 +449,11 @@ const Text = createReactClass({ if (this.props.onStartShouldSetResponder || this._hasPressHandler()) { if (!this._handlers) { this._handlers = { - onStartShouldSetResponder: (): bool => { - const shouldSetFromProps = this.props.onStartShouldSetResponder && - // $FlowFixMe(>=0.41.0) - this.props.onStartShouldSetResponder(); + onStartShouldSetResponder: (): boolean => { + const shouldSetFromProps = + this.props.onStartShouldSetResponder && + // $FlowFixMe(>=0.41.0) + this.props.onStartShouldSetResponder(); const setResponder = shouldSetFromProps || this._hasPressHandler(); if (setResponder && !this.touchableHandleActivePressIn) { // Attach and bind all the other handlers only the first time a touch @@ -462,7 +464,10 @@ const Text = createReactClass({ } } this.touchableHandleActivePressIn = () => { - if (this.props.suppressHighlighting || !this._hasPressHandler()) { + if ( + this.props.suppressHighlighting || + !this._hasPressHandler() + ) { return; } this.setState({ @@ -471,7 +476,10 @@ const Text = createReactClass({ }; this.touchableHandleActivePressOut = () => { - if (this.props.suppressHighlighting || !this._hasPressHandler()) { + if ( + this.props.suppressHighlighting || + !this._hasPressHandler() + ) { return; } this.setState({ @@ -513,12 +521,15 @@ const Text = createReactClass({ this.props.onResponderTerminate && this.props.onResponderTerminate.apply(this, arguments); }.bind(this), - onResponderTerminationRequest: function(): bool { + onResponderTerminationRequest: function(): boolean { // Allow touchable or props.onResponderTerminationRequest to deny // the request var allowTermination = this.touchableHandleResponderTerminationRequest(); if (allowTermination && this.props.onResponderTerminationRequest) { - allowTermination = this.props.onResponderTerminationRequest.apply(this, arguments); + allowTermination = this.props.onResponderTerminationRequest.apply( + this, + arguments, + ); } return allowTermination; }.bind(this), @@ -533,7 +544,7 @@ const Text = createReactClass({ if (newProps.selectionColor != null) { newProps = { ...newProps, - selectionColor: processColor(newProps.selectionColor) + selectionColor: processColor(newProps.selectionColor), }; } if (Touchable.TOUCH_TARGET_DEBUG && newProps.onPress) { @@ -555,13 +566,13 @@ type RectOffset = { left: number, right: number, bottom: number, -} +}; var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; var RCTText = createReactNativeComponentClass( viewConfig.uiViewClassName, - () => viewConfig + () => viewConfig, ); var RCTVirtualText = RCTText; From a5af841d259b6b29d95a9fb346a0ffce9c6efbfe Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sun, 14 Jan 2018 19:32:26 -0800 Subject: [PATCH 05/25] Prettier for View, Image and co. Summary: Trivial beauty. Reviewed By: sahrens Differential Revision: D6715955 fbshipit-source-id: 3632750591f53d4673a2ce76309a0cc62946524d --- Libraries/Components/View/View.js | 17 ++++--- Libraries/Image/AssetRegistry.js | 5 +- Libraries/Image/AssetSourceResolver.js | 41 +++++++++------- Libraries/Image/Image.android.js | 68 +++++++++++++++++--------- Libraries/Image/Image.ios.js | 46 ++++++++++++----- Libraries/Image/ImageEditor.js | 3 +- Libraries/Image/ImageResizeMode.js | 9 ++-- Libraries/Image/ImageSource.js | 1 + Libraries/Image/ImageSourcePropType.js | 1 + Libraries/Image/ImageStore.js | 7 +-- Libraries/Image/ImageStylePropTypes.js | 3 +- Libraries/Image/nativeImageSource.js | 7 ++- 12 files changed, 134 insertions(+), 74 deletions(-) diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index f10f183c08f06f..87a8ca0884cc9c 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -8,6 +8,7 @@ * * @providesModule View * @flow + * @format */ 'use strict'; @@ -52,17 +53,18 @@ const View = createReactClass({ */ viewConfig: { uiViewClassName: 'RCTView', - validAttributes: ReactNativeViewAttributes.RCTView + validAttributes: ReactNativeViewAttributes.RCTView, }, contextTypes: { isInAParentText: PropTypes.bool, }, - render: function() { + render() { invariant( !(this.context.isInAParentText && Platform.OS === 'android'), - 'Nesting of within is not supported on Android.'); + 'Nesting of within is not supported on Android.', + ); // WARNING: This method will not be used in production mode as in that mode we // replace wrapper component View with generated native wrapper RCTView. Avoid @@ -76,17 +78,18 @@ const RCTView = requireNativeComponent('RCTView', View, { nativeOnly: { nativeBackgroundAndroid: true, nativeForegroundAndroid: true, - } + }, }); if (__DEV__) { const UIManager = require('UIManager'); - const viewConfig = UIManager.viewConfigs && UIManager.viewConfigs.RCTView || {}; + const viewConfig = + (UIManager.viewConfigs && UIManager.viewConfigs.RCTView) || {}; for (const prop in viewConfig.nativeProps) { const viewAny: any = View; // Appease flow if (!viewAny.propTypes[prop] && !ReactNativeStyleAttributes[prop]) { throw new Error( - 'View is missing propType for native prop `' + prop + '`' + 'View is missing propType for native prop `' + prop + '`', ); } } @@ -98,4 +101,4 @@ if (__DEV__) { } // No one should depend on the DEV-mode createClass View wrapper. -module.exports = ((ViewToExport : any) : typeof RCTView); +module.exports = ((ViewToExport: any): typeof RCTView); diff --git a/Libraries/Image/AssetRegistry.js b/Libraries/Image/AssetRegistry.js index 116500eda7ff58..4871fe370f70fd 100644 --- a/Libraries/Image/AssetRegistry.js +++ b/Libraries/Image/AssetRegistry.js @@ -8,10 +8,10 @@ * * @providesModule AssetRegistry * @flow + * @format */ 'use strict'; - export type PackagerAsset = { +__packager_asset: boolean, +fileSystemLocation: string, @@ -24,7 +24,6 @@ export type PackagerAsset = { +type: string, }; - var assets: Array = []; function registerAsset(asset: PackagerAsset): number { @@ -37,4 +36,4 @@ function getAssetByID(assetId: number): PackagerAsset { return assets[assetId - 1]; } -module.exports = { registerAsset, getAssetByID }; +module.exports = {registerAsset, getAssetByID}; diff --git a/Libraries/Image/AssetSourceResolver.js b/Libraries/Image/AssetSourceResolver.js index 0869c39e4a0704..db7f642b862d0b 100644 --- a/Libraries/Image/AssetSourceResolver.js +++ b/Libraries/Image/AssetSourceResolver.js @@ -8,6 +8,7 @@ * * @providesModule AssetSourceResolver * @flow + * @format */ 'use strict'; @@ -19,7 +20,7 @@ export type ResolvedAssetSource = { scale: number, }; -import type { PackagerAsset } from 'AssetRegistry'; +import type {PackagerAsset} from 'AssetRegistry'; const PixelRatio = require('PixelRatio'); const Platform = require('Platform'); @@ -43,22 +44,18 @@ function getScaledAssetPath(asset): string { function getAssetPathInDrawableFolder(asset): string { var scale = AssetSourceResolver.pickScale(asset.scales, PixelRatio.get()); var drawbleFolder = assetPathUtils.getAndroidResourceFolderName(asset, scale); - var fileName = assetPathUtils.getAndroidResourceIdentifier(asset); + var fileName = assetPathUtils.getAndroidResourceIdentifier(asset); return drawbleFolder + '/' + fileName + '.' + asset.type; } class AssetSourceResolver { - serverUrl: ?string; // where the jsbundle is being run from jsbundleUrl: ?string; // the asset to resolve asset: PackagerAsset; - constructor(serverUrl: ?string, - jsbundleUrl: ?string, - asset: PackagerAsset - ) { + constructor(serverUrl: ?string, jsbundleUrl: ?string, asset: PackagerAsset) { this.serverUrl = serverUrl; this.jsbundleUrl = jsbundleUrl; this.asset = asset; @@ -78,9 +75,9 @@ class AssetSourceResolver { } if (Platform.OS === 'android') { - return this.isLoadedFromFileSystem() ? - this.drawableFolderInBundle() : - this.resourceIdentifierWithoutScale(); + return this.isLoadedFromFileSystem() + ? this.drawableFolderInBundle() + : this.resourceIdentifierWithoutScale(); } else { return this.scaledAssetURLNearBundle(); } @@ -93,8 +90,12 @@ class AssetSourceResolver { assetServerURL(): ResolvedAssetSource { invariant(!!this.serverUrl, 'need server to load from'); return this.fromSource( - this.serverUrl + getScaledAssetPath(this.asset) + - '?platform=' + Platform.OS + '&hash=' + this.asset.hash + this.serverUrl + + getScaledAssetPath(this.asset) + + '?platform=' + + Platform.OS + + '&hash=' + + this.asset.hash, ); } @@ -122,8 +123,13 @@ class AssetSourceResolver { * E.g. 'assets_awesomemodule_icon' */ resourceIdentifierWithoutScale(): ResolvedAssetSource { - invariant(Platform.OS === 'android', 'resource identifiers work on Android'); - return this.fromSource(assetPathUtils.getAndroidResourceIdentifier(this.asset)); + invariant( + Platform.OS === 'android', + 'resource identifiers work on Android', + ); + return this.fromSource( + assetPathUtils.getAndroidResourceIdentifier(this.asset), + ); } /** @@ -133,9 +139,7 @@ class AssetSourceResolver { */ drawableFolderInBundle(): ResolvedAssetSource { const path = this.jsbundleUrl || 'file://'; - return this.fromSource( - path + getAssetPathInDrawableFolder(this.asset) - ); + return this.fromSource(path + getAssetPathInDrawableFolder(this.asset)); } fromSource(source: string): ResolvedAssetSource { @@ -161,7 +165,6 @@ class AssetSourceResolver { // in which case we default to 1 return scales[scales.length - 1] || 1; } - } - module.exports = AssetSourceResolver; +module.exports = AssetSourceResolver; diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index 1105134e45e086..a8cac24a513181 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -8,6 +8,7 @@ * * @providesModule Image * @flow + * @format */ 'use strict'; @@ -32,9 +33,7 @@ var merge = require('merge'); var requireNativeComponent = require('requireNativeComponent'); var resolveAssetSource = require('resolveAssetSource'); -var { - ImageLoader, -} = NativeModules; +var {ImageLoader} = NativeModules; let _requestId = 1; function generateRequestId() { @@ -75,14 +74,16 @@ var ImageViewAttributes = merge(ReactNativeViewAttributes.UIView, { }); var ViewStyleKeys = new Set(Object.keys(ViewStylePropTypes)); -var ImageSpecificStyleKeys = new Set(Object.keys(ImageStylePropTypes).filter(x => !ViewStyleKeys.has(x))); +var ImageSpecificStyleKeys = new Set( + Object.keys(ImageStylePropTypes).filter(x => !ViewStyleKeys.has(x)), +); var Image = createReactClass({ displayName: 'Image', propTypes: { ...ViewPropTypes, style: StyleSheetPropType(ImageStylePropTypes), - /** + /** * `uri` is a string representing the resource identifier for the image, which * could be an http address, a local file path, or a static image * resource (which should be wrapped in the `require('./path/to/image.png')` function). @@ -108,11 +109,12 @@ var Image = createReactClass({ width: PropTypes.number, height: PropTypes.number, headers: PropTypes.objectOf(PropTypes.string), - })) + }), + ), ]), /** - * blurRadius: the blur radius of the blur filter added to the image - */ + * blurRadius: the blur radius of the blur filter added to the image + */ blurRadius: PropTypes.number, /** * similarly to `source`, this property represents the resource used to render @@ -202,9 +204,12 @@ var Image = createReactClass({ .then(function(sizes) { success(sizes.width, sizes.height); }) - .catch(failure || function() { - console.warn('Failed to get size for image: ' + url); - }); + .catch( + failure || + function() { + console.warn('Failed to get size for image: ' + url); + }, + ); }, /** @@ -231,7 +236,9 @@ var Image = createReactClass({ * @return a mapping from url to cache status, such as "disk" or "memory". If a requested URL is * not in the mapping, it means it's not in the cache. */ - async queryCache(urls: Array): Promise> { + async queryCache( + urls: Array, + ): Promise> { return await ImageLoader.queryCache(urls); }, @@ -255,12 +262,14 @@ var Image = createReactClass({ }, contextTypes: { - isInAParentText: PropTypes.bool + isInAParentText: PropTypes.bool, }, render: function() { const source = resolveAssetSource(this.props.source); - const loadingIndicatorSource = resolveAssetSource(this.props.loadingIndicatorSource); + const loadingIndicatorSource = resolveAssetSource( + this.props.loadingIndicatorSource, + ); // As opposed to the ios version, here we render `null` when there is no source, source.uri // or source array. @@ -270,11 +279,15 @@ var Image = createReactClass({ } if (this.props.src) { - console.warn('The component requires a `source` property rather than `src`.'); + console.warn( + 'The component requires a `source` property rather than `src`.', + ); } if (this.props.children) { - throw new Error('The component cannot contain children. If you want to render content on top of the image, consider using the component or absolute positioning.'); + throw new Error( + 'The component cannot contain children. If you want to render content on top of the image, consider using the component or absolute positioning.', + ); } if (source && (source.uri || Array.isArray(source))) { @@ -292,20 +305,27 @@ var Image = createReactClass({ const {onLoadStart, onLoad, onLoadEnd, onError} = this.props; const nativeProps = merge(this.props, { style, - shouldNotifyLoadEvents: !!(onLoadStart || onLoad || onLoadEnd || onError), + shouldNotifyLoadEvents: !!( + onLoadStart || + onLoad || + onLoadEnd || + onError + ), src: sources, headers: source.headers, - loadingIndicatorSrc: loadingIndicatorSource ? loadingIndicatorSource.uri : null, + loadingIndicatorSrc: loadingIndicatorSource + ? loadingIndicatorSource.uri + : null, }); if (this.context.isInAParentText) { - return ; + return ; } else { - return ; + return ; } } return null; - } + }, }); var styles = StyleSheet.create({ @@ -323,6 +343,10 @@ var cfg = { }, }; var RKImage = requireNativeComponent('RCTImageView', Image, cfg); -var RCTTextInlineImage = requireNativeComponent('RCTTextInlineImage', Image, cfg); +var RCTTextInlineImage = requireNativeComponent( + 'RCTTextInlineImage', + Image, + cfg, +); module.exports = Image; diff --git a/Libraries/Image/Image.ios.js b/Libraries/Image/Image.ios.js index a9c4a8f8fd9c8d..fd99b986b88594 100644 --- a/Libraries/Image/Image.ios.js +++ b/Libraries/Image/Image.ios.js @@ -8,6 +8,7 @@ * * @providesModule Image * @flow + * @format */ 'use strict'; @@ -190,8 +191,8 @@ const Image = createReactClass({ */ accessibilityLabel: PropTypes.node, /** - * blurRadius: the blur radius of the blur filter added to the image - */ + * blurRadius: the blur radius of the blur filter added to the image + */ blurRadius: PropTypes.number, /** * When the image is resized, the corners of the size specified @@ -241,7 +242,13 @@ const Image = createReactClass({ * - `repeat`: Repeat the image to cover the frame of the view. The * image will keep it's size and aspect ratio. (iOS only) */ - resizeMode: PropTypes.oneOf(['cover', 'contain', 'stretch', 'repeat', 'center']), + resizeMode: PropTypes.oneOf([ + 'cover', + 'contain', + 'stretch', + 'repeat', + 'center', + ]), /** * A unique identifier for this element to be used in UI Automation * testing scripts. @@ -314,9 +321,14 @@ const Image = createReactClass({ success: (width: number, height: number) => void, failure?: (error: any) => void, ) { - ImageViewManager.getSize(uri, success, failure || function() { - console.warn('Failed to get size for image: ' + uri); - }); + ImageViewManager.getSize( + uri, + success, + failure || + function() { + console.warn('Failed to get size for image: ' + uri); + }, + ); }, /** * Prefetches a remote image for later use by downloading it to the disk @@ -345,11 +357,15 @@ const Image = createReactClass({ */ viewConfig: { uiViewClassName: 'UIView', - validAttributes: ReactNativeViewAttributes.UIView + validAttributes: ReactNativeViewAttributes.UIView, }, render: function() { - const source = resolveAssetSource(this.props.source) || { uri: undefined, width: undefined, height: undefined }; + const source = resolveAssetSource(this.props.source) || { + uri: undefined, + width: undefined, + height: undefined, + }; let sources; let style; @@ -358,7 +374,8 @@ const Image = createReactClass({ sources = source; } else { const {width, height, uri} = source; - style = flattenStyle([{width, height}, styles.base, this.props.style]) || {}; + style = + flattenStyle([{width, height}, styles.base, this.props.style]) || {}; sources = [source]; if (uri === '') { @@ -366,15 +383,20 @@ const Image = createReactClass({ } } - const resizeMode = this.props.resizeMode || (style || {}).resizeMode || 'cover'; // Workaround for flow bug t7737108 + const resizeMode = + this.props.resizeMode || (style || {}).resizeMode || 'cover'; // Workaround for flow bug t7737108 const tintColor = (style || {}).tintColor; // Workaround for flow bug t7737108 if (this.props.src) { - console.warn('The component requires a `source` property rather than `src`.'); + console.warn( + 'The component requires a `source` property rather than `src`.', + ); } if (this.props.children) { - throw new Error('The component cannot contain children. If you want to render content on top of the image, consider using the component or absolute positioning.'); + throw new Error( + 'The component cannot contain children. If you want to render content on top of the image, consider using the component or absolute positioning.', + ); } return ( diff --git a/Libraries/Image/ImageEditor.js b/Libraries/Image/ImageEditor.js index 3e0a4d3d211167..90868c7736623e 100644 --- a/Libraries/Image/ImageEditor.js +++ b/Libraries/Image/ImageEditor.js @@ -8,6 +8,7 @@ * * @providesModule ImageEditor * @flow + * @format */ 'use strict'; @@ -63,7 +64,7 @@ class ImageEditor { uri: string, cropData: ImageCropData, success: (uri: string) => void, - failure: (error: Object) => void + failure: (error: Object) => void, ) { RCTImageEditingManager.cropImage(uri, cropData, success, failure); } diff --git a/Libraries/Image/ImageResizeMode.js b/Libraries/Image/ImageResizeMode.js index 0f9cb3b3df97b2..26c0029e247fa3 100644 --- a/Libraries/Image/ImageResizeMode.js +++ b/Libraries/Image/ImageResizeMode.js @@ -8,6 +8,7 @@ * * @providesModule ImageResizeMode * @flow + * @format */ 'use strict'; @@ -38,10 +39,10 @@ var ImageResizeMode = keyMirror({ */ stretch: null, /** - * center - The image will be scaled down such that it is completely visible, - * if bigger than the area of the view. - * The image will not be scaled up. - */ + * center - The image will be scaled down such that it is completely visible, + * if bigger than the area of the view. + * The image will not be scaled up. + */ center: null, /** diff --git a/Libraries/Image/ImageSource.js b/Libraries/Image/ImageSource.js index 57e38da0f7ebf8..59fa2c0174729a 100644 --- a/Libraries/Image/ImageSource.js +++ b/Libraries/Image/ImageSource.js @@ -8,6 +8,7 @@ * * @providesModule ImageSource * @flow + * @format */ 'use strict'; diff --git a/Libraries/Image/ImageSourcePropType.js b/Libraries/Image/ImageSourcePropType.js index eb21de802c69f3..3ace885f6e15ad 100644 --- a/Libraries/Image/ImageSourcePropType.js +++ b/Libraries/Image/ImageSourcePropType.js @@ -8,6 +8,7 @@ * * @providesModule ImageSourcePropType * @no-flow + * @format */ 'use strict'; diff --git a/Libraries/Image/ImageStore.js b/Libraries/Image/ImageStore.js index f03262d6d08fec..6eb06418eebd91 100644 --- a/Libraries/Image/ImageStore.js +++ b/Libraries/Image/ImageStore.js @@ -8,6 +8,7 @@ * * @providesModule ImageStore * @flow + * @format */ 'use strict'; @@ -18,7 +19,7 @@ class ImageStore { * Check if the ImageStore contains image data for the specified URI. * @platform ios */ - static hasImageForTag(uri: string, callback: (hasImage: bool) => void) { + static hasImageForTag(uri: string, callback: (hasImage: boolean) => void) { if (RCTImageStoreManager.hasImageForTag) { RCTImageStoreManager.hasImageForTag(uri, callback); } else { @@ -56,7 +57,7 @@ class ImageStore { static addImageFromBase64( base64ImageData: string, success: (uri: string) => void, - failure: (error: any) => void + failure: (error: any) => void, ) { RCTImageStoreManager.addImageFromBase64(base64ImageData, success, failure); } @@ -75,7 +76,7 @@ class ImageStore { static getBase64ForTag( uri: string, success: (base64ImageData: string) => void, - failure: (error: any) => void + failure: (error: any) => void, ) { RCTImageStoreManager.getBase64ForTag(uri, success, failure); } diff --git a/Libraries/Image/ImageStylePropTypes.js b/Libraries/Image/ImageStylePropTypes.js index 70f21d32d3fbce..2953b81ab7156f 100644 --- a/Libraries/Image/ImageStylePropTypes.js +++ b/Libraries/Image/ImageStylePropTypes.js @@ -8,6 +8,7 @@ * * @providesModule ImageStylePropTypes * @flow + * @format */ 'use strict'; @@ -51,7 +52,7 @@ var ImageStylePropTypes = { * http://frescolib.org/docs/rounded-corners-and-circles.html * * @platform android - */ + */ overlayColor: ReactPropTypes.string, // Android-Specific styles diff --git a/Libraries/Image/nativeImageSource.js b/Libraries/Image/nativeImageSource.js index d9d71da7cda6ea..5cb79ecffa2b9b 100644 --- a/Libraries/Image/nativeImageSource.js +++ b/Libraries/Image/nativeImageSource.js @@ -8,6 +8,7 @@ * * @providesModule nativeImageSource * @flow + * @format */ 'use strict'; @@ -21,7 +22,7 @@ type SourceSpec = { // http://facebook.github.io/react-native/docs/images.html#why-not-automatically-size-everything width: number, height: number, -} +}; /** * In hybrid apps, use `nativeImageSource` to access images that are already available @@ -40,7 +41,9 @@ type SourceSpec = { function nativeImageSource(spec: SourceSpec): Object { const uri = Platform.select(spec); if (!uri) { - console.warn(`No image name given for ${Platform.OS}: ${JSON.stringify(spec)}`); + console.warn( + `No image name given for ${Platform.OS}: ${JSON.stringify(spec)}`, + ); } return { From 5dbb3c586c9e8483aa7e6f1edd35ffb12bd4305d Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sun, 14 Jan 2018 19:32:28 -0800 Subject: [PATCH 06/25] Modern TextInput's render function for iOS Reviewed By: sahrens Differential Revision: D6690930 fbshipit-source-id: a6ce5f006b4e6d63feef0f9c0743fb19b0e546fa --- Libraries/Components/TextInput/TextInput.js | 57 ++++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 90c46b5e017c9b..1b32396c541152 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -669,7 +669,9 @@ const TextInput = createReactClass({ render: function() { if (Platform.OS === 'ios') { - return this._renderIOS(); + return UIManager.RCTVirtualText + ? this._renderIOS() + : this._renderIOSLegacy(); } else if (Platform.OS === 'android') { return this._renderAndroid(); } @@ -687,7 +689,7 @@ const TextInput = createReactClass({ this._inputRef = ref; }, - _renderIOS: function() { + _renderIOSLegacy: function() { var textContainer; var props = Object.assign({}, this.props); @@ -778,6 +780,57 @@ const TextInput = createReactClass({ ); }, + _renderIOS: function() { + var props = Object.assign({}, this.props); + props.style = [this.props.style]; + + if (props.selection && props.selection.end == null) { + props.selection = { + start: props.selection.start, + end: props.selection.start, + }; + } + + const RCTTextInputView = props.multiline + ? RCTMultilineTextInputView + : RCTSinglelineTextInputView; + + if (props.multiline) { + props.style.unshift(styles.multilineInput); + } + + const textContainer = ( + + ); + + return ( + + {textContainer} + + ); + }, + _renderAndroid: function() { const props = Object.assign({}, this.props); props.style = [this.props.style]; From 95320626e111d092b7954f370d307df00ea3bb75 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sun, 14 Jan 2018 19:32:31 -0800 Subject: [PATCH 07/25] Slight modernizing of Text.js to make it compatible with coming changes Reviewed By: sahrens Differential Revision: D6688488 fbshipit-source-id: da020b3510ac7163f63cb5cebc27ec4306b1136c --- Libraries/Text/Text.js | 42 +++++++----------------------------------- 1 file changed, 7 insertions(+), 35 deletions(-) diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 6268e59cc59391..0f8fe1a1767b76 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -15,37 +15,20 @@ const ColorPropType = require('ColorPropType'); const EdgeInsetsPropType = require('EdgeInsetsPropType'); const NativeMethodsMixin = require('NativeMethodsMixin'); -const Platform = require('Platform'); const React = require('React'); const PropTypes = require('prop-types'); -const ReactNativeViewAttributes = require('ReactNativeViewAttributes'); const StyleSheetPropType = require('StyleSheetPropType'); const TextStylePropTypes = require('TextStylePropTypes'); const Touchable = require('Touchable'); +const UIManager = require('UIManager'); const createReactClass = require('create-react-class'); -const createReactNativeComponentClass = require('createReactNativeComponentClass'); +const requireNativeComponent = require('requireNativeComponent'); const mergeFast = require('mergeFast'); const processColor = require('processColor'); const stylePropType = StyleSheetPropType(TextStylePropTypes); -const viewConfig = { - validAttributes: mergeFast(ReactNativeViewAttributes.UIView, { - isHighlighted: true, - numberOfLines: true, - ellipsizeMode: true, - allowFontScaling: true, - disabled: true, - selectable: true, - selectionColor: true, - adjustsFontSizeToFit: true, - minimumFontScale: true, - textBreakStrategy: true, - }), - uiViewClassName: 'RCTText', -}; - /** * A React component for displaying text. * @@ -418,7 +401,6 @@ const Text = createReactClass({ }); }, mixins: [NativeMethodsMixin], - viewConfig: viewConfig, getChildContext(): Object { return {isInAParentText: true}; }, @@ -568,21 +550,11 @@ type RectOffset = { bottom: number, }; -var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; - -var RCTText = createReactNativeComponentClass( - viewConfig.uiViewClassName, - () => viewConfig, -); -var RCTVirtualText = RCTText; +const PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; -if (Platform.OS === 'android') { - RCTVirtualText = createReactNativeComponentClass('RCTVirtualText', () => ({ - validAttributes: mergeFast(ReactNativeViewAttributes.UIView, { - isHighlighted: true, - }), - uiViewClassName: 'RCTVirtualText', - })); -} +const RCTText = requireNativeComponent('RCTText'); +const RCTVirtualText = UIManager.RCTVirtualText + ? requireNativeComponent('RCTVirtualText') + : RCTText; module.exports = Text; From 52648326e6ac4470eeffc0a56d91bc487bc1eae4 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sun, 14 Jan 2018 19:32:33 -0800 Subject: [PATCH 08/25] Generalization of `isInAParentText` context Summary: Currently `isInAParentText` context works as imaginary `isInAAncestorText` context (not like a real `isInAParentText`). Let's imagine we have hierarchy like: `View -> Text -> Text* -> View* -> Text* -> Text* -> View*` With current implementation all nodes marked with asterisk have `isInAParentText` context, which is incorrect (because some of them actually in View context). With the new implemetations it will work like this: `View -> Text -> Text* -> View* -> Text -> Text* -> View*` So, only nodes which have (or ) as a parent will have `isInAParentText` context. This change allows to select proper `Text` vs. `VirtualText` component in cases where and components can interleave each other. Reviewed By: sahrens Differential Revision: D6690495 fbshipit-source-id: f7c59b23d0eaf68a1d08036b858d99c9547f7878 --- Libraries/Components/TextInput/TextInput.js | 22 ++++++++++++-------- Libraries/Components/View/View.js | 11 +++++++--- Libraries/Components/View/ViewContext.js | 23 +++++++++++++++++++++ Libraries/Image/Image.android.js | 8 +++---- Libraries/Text/Text.js | 17 ++++++++------- 5 files changed, 56 insertions(+), 25 deletions(-) create mode 100644 Libraries/Components/View/ViewContext.js diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 1b32396c541152..d16115cad7e9bb 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -31,6 +31,7 @@ const TimerMixin = require('react-timer-mixin'); const TouchableWithoutFeedback = require('TouchableWithoutFeedback'); const UIManager = require('UIManager'); const ViewPropTypes = require('ViewPropTypes'); +const {ViewContextTypes} = require('ViewContext'); /* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error * found when Flow v0.54 was deployed. To see the error delete this comment and @@ -48,6 +49,8 @@ const onlyMultiline = { children: true, }; +import type {ViewChildContext} from 'ViewContext'; + if (Platform.OS === 'android') { var AndroidTextInput = requireNativeComponent('AndroidTextInput', null); } else if (Platform.OS === 'ios') { @@ -612,11 +615,6 @@ const TextInput = createReactClass({ ); }, - contextTypes: { - onFocusRequested: PropTypes.func, - focusEmitter: PropTypes.instanceOf(EventEmitter), - }, - _inputRef: (undefined: any), _focusSubscription: (undefined: ?Function), _lastNativeText: (undefined: ?string), @@ -652,12 +650,18 @@ const TextInput = createReactClass({ } }, - getChildContext: function(): Object { - return {isInAParentText: true}; + getChildContext(): ViewChildContext { + return { + isInAParentText: true, + }; }, - childContextTypes: { - isInAParentText: PropTypes.bool, + childContextTypes: ViewContextTypes, + + contextTypes: { + ...ViewContextTypes, + onFocusRequested: PropTypes.func, + focusEmitter: PropTypes.instanceOf(EventEmitter), }, /** diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index 87a8ca0884cc9c..2393f43526b709 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -14,17 +14,18 @@ const NativeMethodsMixin = require('NativeMethodsMixin'); const Platform = require('Platform'); -const PropTypes = require('prop-types'); const React = require('React'); const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes'); const ReactNativeViewAttributes = require('ReactNativeViewAttributes'); const ViewPropTypes = require('ViewPropTypes'); +const {ViewContextTypes} = require('ViewContext'); const createReactClass = require('create-react-class'); const invariant = require('fbjs/lib/invariant'); const requireNativeComponent = require('requireNativeComponent'); import type {ViewProps} from 'ViewPropTypes'; +import type {ViewChildContext} from 'ViewContext'; export type Props = ViewProps; @@ -56,8 +57,12 @@ const View = createReactClass({ validAttributes: ReactNativeViewAttributes.RCTView, }, - contextTypes: { - isInAParentText: PropTypes.bool, + childContextTypes: ViewContextTypes, + + getChildContext(): ViewChildContext { + return { + isInAParentText: false, + }; }, render() { diff --git a/Libraries/Components/View/ViewContext.js b/Libraries/Components/View/ViewContext.js new file mode 100644 index 00000000000000..ed73187b0bb8d6 --- /dev/null +++ b/Libraries/Components/View/ViewContext.js @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ViewContext + * @flow + * @format + */ +'use strict'; + +const PropTypes = require('prop-types'); + +export type ViewChildContext = {| + +isInAParentText: boolean, +|}; + +export const ViewContextTypes = { + isInAParentText: PropTypes.bool, +}; diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index a8cac24a513181..dc561bdb2bffee 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -22,17 +22,17 @@ var ReactNativeViewAttributes = require('ReactNativeViewAttributes'); var Set = require('Set'); var StyleSheet = require('StyleSheet'); var StyleSheetPropType = require('StyleSheetPropType'); -var View = require('View'); var ViewPropTypes = require('ViewPropTypes'); var ViewStylePropTypes = require('ViewStylePropTypes'); var createReactClass = require('create-react-class'); -var filterObject = require('fbjs/lib/filterObject'); var flattenStyle = require('flattenStyle'); var merge = require('merge'); var requireNativeComponent = require('requireNativeComponent'); var resolveAssetSource = require('resolveAssetSource'); +const {ViewContextTypes} = require('ViewContext'); + var {ImageLoader} = NativeModules; let _requestId = 1; @@ -261,9 +261,7 @@ var Image = createReactClass({ validAttributes: ReactNativeViewAttributes.RCTView, }, - contextTypes: { - isInAParentText: PropTypes.bool, - }, + contextTypes: ViewContextTypes, render: function() { const source = resolveAssetSource(this.props.source); diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 0f8fe1a1767b76..44b327da8943dc 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -26,9 +26,12 @@ const createReactClass = require('create-react-class'); const requireNativeComponent = require('requireNativeComponent'); const mergeFast = require('mergeFast'); const processColor = require('processColor'); +const {ViewContextTypes} = require('ViewContext'); const stylePropType = StyleSheetPropType(TextStylePropTypes); +import type {ViewChildContext} from 'ViewContext'; + /** * A React component for displaying text. * @@ -401,15 +404,13 @@ const Text = createReactClass({ }); }, mixins: [NativeMethodsMixin], - getChildContext(): Object { - return {isInAParentText: true}; - }, - childContextTypes: { - isInAParentText: PropTypes.bool, - }, - contextTypes: { - isInAParentText: PropTypes.bool, + getChildContext(): ViewChildContext { + return { + isInAParentText: true, + }; }, + childContextTypes: ViewContextTypes, + contextTypes: ViewContextTypes, /** * Only assigned if touch is needed. */ From ac1c8c265e6030c52434f99e882639c67c8c175d Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Mon, 15 Jan 2018 05:33:37 -0800 Subject: [PATCH 09/25] Refactored the flexbox step to determine available space in main and cross dim Reviewed By: emilsjolander Differential Revision: D6693777 fbshipit-source-id: d6c87670e74bdc22b32916c2d77fe423d831b378 --- ReactCommon/yoga/yoga/Yoga.cpp | 51 +++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index a25936c4a527ed..9c404515794041 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -1557,6 +1557,39 @@ static void YGZeroOutLayoutRecursivly(const YGNodeRef node) { } } +static float YGNodeCalculateAvailableInnerDim( + const YGNodeRef node, + YGFlexDirection axis, + float availableDim, + float parentDim) { + YGFlexDirection direction = + YGFlexDirectionIsRow(axis) ? YGFlexDirectionRow : YGFlexDirectionColumn; + YGDimension dimension = + YGFlexDirectionIsRow(axis) ? YGDimensionWidth : YGDimensionHeight; + + const float margin = YGNodeMarginForAxis(node, direction, parentDim); + const float paddingAndBorder = + YGNodePaddingAndBorderForAxis(node, direction, parentDim); + + float availableInnerDim = availableDim - margin - paddingAndBorder; + // Max dimension overrides predefined dimension value; Min dimension in turn + // overrides both of the above + if (!YGFloatIsUndefined(availableInnerDim)) { + // We want to make sure our available height does not violate min and max + // constraints + const float minInnerDim = + YGResolveValue(node->getStyle().minDimensions[dimension], parentDim) - + paddingAndBorder; + const float maxInnerDim = + YGResolveValue(node->getStyle().maxDimensions[dimension], parentDim) - + paddingAndBorder; + availableInnerDim = + fmaxf(fminf(availableInnerDim, maxInnerDim), minInnerDim); + } + + return availableInnerDim; +} + // // This is the main routine that implements a subset of the flexbox layout // algorithm @@ -1775,7 +1808,6 @@ static void YGNodelayoutImpl(const YGNodeRef node, const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow, parentWidth); const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn, parentWidth); - // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS const float minInnerWidth = YGResolveValue( node->getStyle().minDimensions[YGDimensionWidth], parentWidth) - @@ -1795,19 +1827,12 @@ static void YGNodelayoutImpl(const YGNodeRef node, const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight; const float maxInnerMainDim = isMainAxisRow ? maxInnerWidth : maxInnerHeight; - // Max dimension overrides predefined dimension value; Min dimension in turn overrides both of the - // above - float availableInnerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow; - if (!YGFloatIsUndefined(availableInnerWidth)) { - // We want to make sure our available width does not violate min and max constraints - availableInnerWidth = fmaxf(fminf(availableInnerWidth, maxInnerWidth), minInnerWidth); - } + // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS - float availableInnerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn; - if (!YGFloatIsUndefined(availableInnerHeight)) { - // We want to make sure our available height does not violate min and max constraints - availableInnerHeight = fmaxf(fminf(availableInnerHeight, maxInnerHeight), minInnerHeight); - } + float availableInnerWidth = YGNodeCalculateAvailableInnerDim( + node, YGFlexDirectionRow, availableWidth, parentWidth); + float availableInnerHeight = YGNodeCalculateAvailableInnerDim( + node, YGFlexDirectionColumn, availableHeight, parentHeight); float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight; const float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth; From fcf2c7cf61ca454f10d398d57b78b5b29ed05ae2 Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Mon, 15 Jan 2018 10:09:40 -0800 Subject: [PATCH 10/25] Refactored step3 of flexbox algorithm Reviewed By: emilsjolander Differential Revision: D6702749 fbshipit-source-id: 15dcc94ae30ac185e4d1c7d6e3744a40cfa47317 --- ReactCommon/yoga/yoga/Yoga.cpp | 185 ++++++++++++++++++++------------- 1 file changed, 111 insertions(+), 74 deletions(-) diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index 9c404515794041..d4171d619d7470 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -1590,6 +1590,87 @@ static float YGNodeCalculateAvailableInnerDim( return availableInnerDim; } +static void YGNodeComputeFlexBasisForChildren( + const YGNodeRef node, + const float availableInnerWidth, + const float availableInnerHeight, + YGMeasureMode widthMeasureMode, + YGMeasureMode heightMeasureMode, + YGDirection direction, + YGFlexDirection mainAxis, + const YGConfigRef config, + bool performLayout, + float& totalOuterFlexBasis) { + YGNodeRef singleFlexChild = nullptr; + YGVector children = node->getChildren(); + YGMeasureMode measureModeMainDim = + YGFlexDirectionIsRow(mainAxis) ? widthMeasureMode : heightMeasureMode; + // If there is only one child with flexGrow + flexShrink it means we can set + // the computedFlexBasis to 0 instead of measuring and shrinking / flexing the + // child to exactly match the remaining space + if (measureModeMainDim == YGMeasureModeExactly) { + for (auto child : children) { + if (singleFlexChild != nullptr) { + if (YGNodeIsFlex(child)) { + // There is already a flexible child, abort + singleFlexChild = nullptr; + break; + } + } else if ( + child->resolveFlexGrow() > 0.0f && + child->resolveFlexShrink() > 0.0f) { + singleFlexChild = child; + } + } + } + + for (auto child : children) { + child->resolveDimension(); + if (child->getStyle().display == YGDisplayNone) { + YGZeroOutLayoutRecursivly(child); + child->setHasNewLayout(true); + child->setDirty(false); + continue; + } + if (child->getStyle().positionType == YGPositionTypeAbsolute) { + continue; + } + if (performLayout) { + // Set the initial position (relative to the parent). + const YGDirection childDirection = + YGNodeResolveDirection(child, direction); + const float mainDim = YGFlexDirectionIsRow(mainAxis) + ? availableInnerWidth + : availableInnerHeight; + const float crossDim = YGFlexDirectionIsRow(mainAxis) + ? availableInnerHeight + : availableInnerWidth; + child->setPosition( + childDirection, mainDim, crossDim, availableInnerWidth); + } + if (child == singleFlexChild) { + child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount); + child->setLayoutComputedFlexBasis(0); + } else { + YGNodeComputeFlexBasisForChild( + node, + child, + availableInnerWidth, + widthMeasureMode, + availableInnerHeight, + availableInnerWidth, + availableInnerHeight, + heightMeasureMode, + direction, + config); + } + + totalOuterFlexBasis += child->getLayout().computedFlexBasis + + YGNodeMarginForAxis(child, mainAxis, availableInnerWidth); + ; + } +} + // // This is the main routine that implements a subset of the flexbox layout // algorithm @@ -1827,59 +1908,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight; const float maxInnerMainDim = isMainAxisRow ? maxInnerWidth : maxInnerHeight; - // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS - - float availableInnerWidth = YGNodeCalculateAvailableInnerDim( - node, YGFlexDirectionRow, availableWidth, parentWidth); - float availableInnerHeight = YGNodeCalculateAvailableInnerDim( - node, YGFlexDirectionColumn, availableHeight, parentHeight); - - float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight; - const float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth; - - // If there is only one child with flexGrow + flexShrink it means we can set the - // computedFlexBasis to 0 instead of measuring and shrinking / flexing the child to exactly - // match the remaining space - YGNodeRef singleFlexChild = nullptr; - if (measureModeMainDim == YGMeasureModeExactly) { - for (uint32_t i = 0; i < childCount; i++) { - const YGNodeRef child = YGNodeGetChild(node, i); - if (singleFlexChild) { - if (YGNodeIsFlex(child)) { - // There is already a flexible child, abort. - singleFlexChild = nullptr; - break; - } - } else if ( - child->resolveFlexGrow() > 0.0f && - child->resolveFlexShrink() > 0.0f) { - singleFlexChild = child; - } - } - } - - float totalOuterFlexBasis = 0; - - // STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM - for (uint32_t i = 0; i < childCount; i++) { - const YGNodeRef child = node->getChild(i); - if (child->getStyle().display == YGDisplayNone) { - YGZeroOutLayoutRecursivly(child); - child->setHasNewLayout(true); - child->setDirty(false); - continue; - } - child->resolveDimension(); - if (performLayout) { - // Set the initial position (relative to the parent). - const YGDirection childDirection = YGNodeResolveDirection(child, direction); - child->setPosition( - childDirection, - availableInnerMainDim, - availableInnerCrossDim, - availableInnerWidth); - } - + // Make a private linkedlist of absolutely positioned child + for (auto child : node->getChildren()) { // Absolute-positioned children don't participate in flex layout. Add them // to a list that we can process later. if (child->getStyle().positionType == YGPositionTypeAbsolute) { @@ -1893,36 +1923,43 @@ static void YGNodelayoutImpl(const YGNodeRef node, } currentAbsoluteChild = child; child->setNextChild(nullptr); - } else { - if (child == singleFlexChild) { - child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount); - child->setLayoutComputedFlexBasis(0); - } else { - YGNodeComputeFlexBasisForChild(node, - child, - availableInnerWidth, - widthMeasureMode, - availableInnerHeight, - availableInnerWidth, - availableInnerHeight, - heightMeasureMode, - direction, - config); - } } - - totalOuterFlexBasis += child->getLayout().computedFlexBasis + - YGNodeMarginForAxis(child, mainAxis, availableInnerWidth); - ; } + // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS + + float availableInnerWidth = YGNodeCalculateAvailableInnerDim( + node, YGFlexDirectionRow, availableWidth, parentWidth); + float availableInnerHeight = YGNodeCalculateAvailableInnerDim( + node, YGFlexDirectionColumn, availableHeight, parentHeight); + + float availableInnerMainDim = + isMainAxisRow ? availableInnerWidth : availableInnerHeight; + const float availableInnerCrossDim = + isMainAxisRow ? availableInnerHeight : availableInnerWidth; + + float totalOuterFlexBasis = 0; + + // STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM + + YGNodeComputeFlexBasisForChildren( + node, + availableInnerWidth, + availableInnerHeight, + widthMeasureMode, + heightMeasureMode, + direction, + mainAxis, + config, + performLayout, + totalOuterFlexBasis); + const bool flexBasisOverflows = measureModeMainDim == YGMeasureModeUndefined ? false : totalOuterFlexBasis > availableInnerMainDim; if (isNodeFlexWrap && flexBasisOverflows && measureModeMainDim == YGMeasureModeAtMost) { measureModeMainDim = YGMeasureModeExactly; } - // STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES // Indexes of children that represent the first and last items in the line. From 2b27f1aa1964eba749876100be1f3ac4c085fa8f Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Mon, 15 Jan 2018 10:09:43 -0800 Subject: [PATCH 11/25] Moved YGNodeIsFlex as a method on YGNode Reviewed By: emilsjolander Differential Revision: D6711536 fbshipit-source-id: e60be7da55e3e8d254eb253c141d219a37a76087 --- ReactCommon/yoga/yoga/YGNode.cpp | 6 ++++++ ReactCommon/yoga/yoga/YGNode.h | 13 ++++++------- ReactCommon/yoga/yoga/Yoga.cpp | 10 ++-------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/ReactCommon/yoga/yoga/YGNode.cpp b/ReactCommon/yoga/yoga/YGNode.cpp index caee38443c6d87..c5ddd2f82cbc6f 100644 --- a/ReactCommon/yoga/yoga/YGNode.cpp +++ b/ReactCommon/yoga/yoga/YGNode.cpp @@ -590,3 +590,9 @@ float YGNode::resolveFlexShrink() { } return config_->useWebDefaults ? kWebDefaultFlexShrink : kDefaultFlexShrink; } + +bool YGNode::isNodeFlexible() { + return ( + (style_.positionType == YGPositionTypeRelative) && + (resolveFlexGrow() != 0 || resolveFlexShrink() != 0)); +} diff --git a/ReactCommon/yoga/yoga/YGNode.h b/ReactCommon/yoga/yoga/YGNode.h index b90c0e33672f7b..0ac44d1b4f6249 100644 --- a/ReactCommon/yoga/yoga/YGNode.h +++ b/ReactCommon/yoga/yoga/YGNode.h @@ -111,7 +111,11 @@ struct YGNode { void setLayoutMeasuredDimension(float measuredDimension, int index); void setLayoutHadOverflow(bool hadOverflow); void setLayoutDimension(float dimension, int index); - + void setLayoutDirection(YGDirection direction); + void setLayoutMargin(float margin, int index); + void setLayoutBorder(float border, int index); + void setLayoutPadding(float padding, int index); + void setLayoutPosition(float position, int index); void setPosition( const YGDirection direction, const float mainSize, @@ -131,15 +135,10 @@ struct YGNode { /// Removes the first occurrence of child bool removeChild(YGNodeRef child); void removeChild(uint32_t index); - void setLayoutDirection(YGDirection direction); - void setLayoutMargin(float margin, int index); - void setLayoutBorder(float border, int index); - void setLayoutPadding(float padding, int index); - void setLayoutPosition(float position, int index); - // Other methods void cloneChildrenIfNeeded(); void markDirtyAndPropogate(); float resolveFlexGrow(); float resolveFlexShrink(); + bool isNodeFlexible(); }; diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index d4171d619d7470..275ccc6cf6f647 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -915,12 +915,6 @@ static float YGBaseline(const YGNodeRef node) { return baseline + baselineChild->getLayout().position[YGEdgeTop]; } -static inline bool YGNodeIsFlex(const YGNodeRef node) { - return ( - node->getStyle().positionType == YGPositionTypeRelative && - (node->resolveFlexGrow() != 0 || node->resolveFlexShrink() != 0)); -} - static bool YGIsBaselineLayout(const YGNodeRef node) { if (YGFlexDirectionIsColumn(node->getStyle().flexDirection)) { return false; @@ -1611,7 +1605,7 @@ static void YGNodeComputeFlexBasisForChildren( if (measureModeMainDim == YGMeasureModeExactly) { for (auto child : children) { if (singleFlexChild != nullptr) { - if (YGNodeIsFlex(child)) { + if (child->isNodeFlexible()) { // There is already a flexible child, abort singleFlexChild = nullptr; break; @@ -2033,7 +2027,7 @@ static void YGNodelayoutImpl(const YGNodeRef node, sizeConsumedOnCurrentLine += flexBasisWithMinAndMaxConstraints + childMarginMainAxis; itemsOnLine++; - if (YGNodeIsFlex(child)) { + if (child->isNodeFlexible()) { totalFlexGrowFactors += child->resolveFlexGrow(); // Unlike the grow factor, the shrink factor is scaled relative to the child dimension. From 210ae5b95a9c94194e95a21fdb93f88ddfdc5ce2 Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Mon, 15 Jan 2018 10:09:44 -0800 Subject: [PATCH 12/25] Move leading border function as a method on YGNode Reviewed By: emilsjolander Differential Revision: D6711523 fbshipit-source-id: 76e90083a9dd0728dc9557cc3b0a1f431f3afd5d --- ReactCommon/yoga/yoga/YGNode.cpp | 12 +++++++++++ ReactCommon/yoga/yoga/YGNode.h | 1 + ReactCommon/yoga/yoga/Yoga.cpp | 35 ++++++++------------------------ 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/ReactCommon/yoga/yoga/YGNode.cpp b/ReactCommon/yoga/yoga/YGNode.cpp index c5ddd2f82cbc6f..c7e01fd20c09ba 100644 --- a/ReactCommon/yoga/yoga/YGNode.cpp +++ b/ReactCommon/yoga/yoga/YGNode.cpp @@ -596,3 +596,15 @@ bool YGNode::isNodeFlexible() { (style_.positionType == YGPositionTypeRelative) && (resolveFlexGrow() != 0 || resolveFlexShrink() != 0)); } + +float YGNode::getLeadingBorder(const YGFlexDirection axis) { + if (YGFlexDirectionIsRow(axis) && + style_.border[YGEdgeStart].unit != YGUnitUndefined && + style_.border[YGEdgeStart].value >= 0.0f) { + return style_.border[YGEdgeStart].value; + } + + return fmaxf( + YGComputedEdgeValue(style_.border, leading[axis], &YGValueZero)->value, + 0.0f); +} diff --git a/ReactCommon/yoga/yoga/YGNode.h b/ReactCommon/yoga/yoga/YGNode.h index 0ac44d1b4f6249..1c4058780e3ccb 100644 --- a/ReactCommon/yoga/yoga/YGNode.h +++ b/ReactCommon/yoga/yoga/YGNode.h @@ -85,6 +85,7 @@ struct YGNode { float getTrailingPosition(const YGFlexDirection axis, const float axisSize); float getLeadingMargin(const YGFlexDirection axis, const float widthSize); float getTrailingMargin(const YGFlexDirection axis, const float widthSize); + float getLeadingBorder(const YGFlexDirection flexDirection); // Setters void setContext(void* context); diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index 275ccc6cf6f647..9ad8f22d457a5f 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -797,21 +797,6 @@ static float YGNodeTrailingPadding(const YGNodeRef node, 0.0f); } -static float YGNodeLeadingBorder( - const YGNodeRef node, - const YGFlexDirection axis) { - if (YGFlexDirectionIsRow(axis) && - node->getStyle().border[YGEdgeStart].unit != YGUnitUndefined && - node->getStyle().border[YGEdgeStart].value >= 0.0f) { - return node->getStyle().border[YGEdgeStart].value; - } - - return fmaxf( - YGComputedEdgeValue(node->getStyle().border, leading[axis], &YGValueZero) - ->value, - 0.0f); -} - static float YGNodeTrailingBorder( const YGNodeRef node, const YGFlexDirection axis) { @@ -832,7 +817,7 @@ static inline float YGNodeLeadingPaddingAndBorder( const YGFlexDirection axis, const float widthSize) { return YGNodeLeadingPadding(node, axis, widthSize) + - YGNodeLeadingBorder(node, axis); + node->getLeadingBorder(axis); } static inline float YGNodeTrailingPaddingAndBorder(const YGNodeRef node, @@ -1235,7 +1220,7 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, if (child->isLeadingPositionDefined(YGFlexDirectionRow) && child->isTrailingPosDefined(YGFlexDirectionRow)) { childWidth = node->getLayout().measuredDimensions[YGDimensionWidth] - - (YGNodeLeadingBorder(node, YGFlexDirectionRow) + + (node->getLeadingBorder(YGFlexDirectionRow) + YGNodeTrailingBorder(node, YGFlexDirectionRow)) - (child->getLeadingPosition(YGFlexDirectionRow, width) + child->getTrailingPosition(YGFlexDirectionRow, width)); @@ -1254,7 +1239,7 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, if (child->isLeadingPositionDefined(YGFlexDirectionColumn) && child->isTrailingPosDefined(YGFlexDirectionColumn)) { childHeight = node->getLayout().measuredDimensions[YGDimensionHeight] - - (YGNodeLeadingBorder(node, YGFlexDirectionColumn) + + (node->getLeadingBorder(YGFlexDirectionColumn) + YGNodeTrailingBorder(node, YGFlexDirectionColumn)) - (child->getLeadingPosition(YGFlexDirectionColumn, height) + child->getTrailingPosition(YGFlexDirectionColumn, height)); @@ -1789,12 +1774,10 @@ static void YGNodelayoutImpl(const YGNodeRef node, node->setLayoutMargin( node->getTrailingMargin(flexColumnDirection, parentWidth), YGEdgeBottom); - node->setLayoutBorder( - YGNodeLeadingBorder(node, flexRowDirection), YGEdgeStart); + node->setLayoutBorder(node->getLeadingBorder(flexRowDirection), YGEdgeStart); node->setLayoutBorder( YGNodeTrailingBorder(node, flexRowDirection), YGEdgeEnd); - node->setLayoutBorder( - YGNodeLeadingBorder(node, flexColumnDirection), YGEdgeTop); + node->setLayoutBorder(node->getLeadingBorder(flexColumnDirection), YGEdgeTop); node->setLayoutBorder( YGNodeTrailingBorder(node, flexColumnDirection), YGEdgeBottom); @@ -2459,7 +2442,7 @@ static void YGNodelayoutImpl(const YGNodeRef node, // (and margin/border). child->setLayoutPosition( child->getLeadingPosition(mainAxis, availableInnerMainDim) + - YGNodeLeadingBorder(node, mainAxis) + + node->getLeadingBorder(mainAxis) + child->getLeadingMargin(mainAxis, availableInnerWidth), pos[mainAxis]); } @@ -2501,7 +2484,7 @@ static void YGNodelayoutImpl(const YGNodeRef node, } else if (performLayout) { child->setLayoutPosition( child->getLayout().position[pos[mainAxis]] + - YGNodeLeadingBorder(node, mainAxis) + leadingMainDim, + node->getLeadingBorder(mainAxis) + leadingMainDim, pos[mainAxis]); } } @@ -2552,7 +2535,7 @@ static void YGNodelayoutImpl(const YGNodeRef node, if (isChildLeadingPosDefined) { child->setLayoutPosition( child->getLeadingPosition(crossAxis, availableInnerCrossDim) + - YGNodeLeadingBorder(node, crossAxis) + + node->getLeadingBorder(crossAxis) + child->getLeadingMargin(crossAxis, availableInnerWidth), pos[crossAxis]); } @@ -2560,7 +2543,7 @@ static void YGNodelayoutImpl(const YGNodeRef node, if (!isChildLeadingPosDefined || YGFloatIsUndefined(child->getLayout().position[pos[crossAxis]])) { child->setLayoutPosition( - YGNodeLeadingBorder(node, crossAxis) + + node->getLeadingBorder(crossAxis) + child->getLeadingMargin(crossAxis, availableInnerWidth), pos[crossAxis]); } From 82088580ab17417a51386722f98b83d6cad0a6a0 Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Mon, 15 Jan 2018 10:09:46 -0800 Subject: [PATCH 13/25] Move trailing border function as a method on YGNode Reviewed By: emilsjolander Differential Revision: D6711666 fbshipit-source-id: fe4fdfc2db59d03beb763317e1a6f9de52f851d4 --- ReactCommon/yoga/yoga/YGNode.cpp | 13 +++++++++++++ ReactCommon/yoga/yoga/YGNode.h | 1 + ReactCommon/yoga/yoga/Yoga.cpp | 31 ++++++++----------------------- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/ReactCommon/yoga/yoga/YGNode.cpp b/ReactCommon/yoga/yoga/YGNode.cpp index c7e01fd20c09ba..ebe733e760cc85 100644 --- a/ReactCommon/yoga/yoga/YGNode.cpp +++ b/ReactCommon/yoga/yoga/YGNode.cpp @@ -608,3 +608,16 @@ float YGNode::getLeadingBorder(const YGFlexDirection axis) { YGComputedEdgeValue(style_.border, leading[axis], &YGValueZero)->value, 0.0f); } + +float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) { + if (YGFlexDirectionIsRow(flexDirection) && + style_.border[YGEdgeEnd].unit != YGUnitUndefined && + style_.border[YGEdgeEnd].value >= 0.0f) { + return style_.border[YGEdgeEnd].value; + } + + return fmaxf( + YGComputedEdgeValue(style_.border, trailing[flexDirection], &YGValueZero) + ->value, + 0.0f); +} diff --git a/ReactCommon/yoga/yoga/YGNode.h b/ReactCommon/yoga/yoga/YGNode.h index 1c4058780e3ccb..503894c19ba8b6 100644 --- a/ReactCommon/yoga/yoga/YGNode.h +++ b/ReactCommon/yoga/yoga/YGNode.h @@ -86,6 +86,7 @@ struct YGNode { float getLeadingMargin(const YGFlexDirection axis, const float widthSize); float getTrailingMargin(const YGFlexDirection axis, const float widthSize); float getLeadingBorder(const YGFlexDirection flexDirection); + float getTrailingBorder(const YGFlexDirection flexDirection); // Setters void setContext(void* context); diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index 9ad8f22d457a5f..3b536141d1e343 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -797,21 +797,6 @@ static float YGNodeTrailingPadding(const YGNodeRef node, 0.0f); } -static float YGNodeTrailingBorder( - const YGNodeRef node, - const YGFlexDirection axis) { - if (YGFlexDirectionIsRow(axis) && - node->getStyle().border[YGEdgeEnd].unit != YGUnitUndefined && - node->getStyle().border[YGEdgeEnd].value >= 0.0f) { - return node->getStyle().border[YGEdgeEnd].value; - } - - return fmaxf( - YGComputedEdgeValue(node->getStyle().border, trailing[axis], &YGValueZero) - ->value, - 0.0f); -} - static inline float YGNodeLeadingPaddingAndBorder( const YGNodeRef node, const YGFlexDirection axis, @@ -823,7 +808,8 @@ static inline float YGNodeLeadingPaddingAndBorder( static inline float YGNodeTrailingPaddingAndBorder(const YGNodeRef node, const YGFlexDirection axis, const float widthSize) { - return YGNodeTrailingPadding(node, axis, widthSize) + YGNodeTrailingBorder(node, axis); + return YGNodeTrailingPadding(node, axis, widthSize) + + node->getTrailingBorder(axis); } static inline float YGNodeMarginForAxis(const YGNodeRef node, @@ -1221,7 +1207,7 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, child->isTrailingPosDefined(YGFlexDirectionRow)) { childWidth = node->getLayout().measuredDimensions[YGDimensionWidth] - (node->getLeadingBorder(YGFlexDirectionRow) + - YGNodeTrailingBorder(node, YGFlexDirectionRow)) - + node->getTrailingBorder(YGFlexDirectionRow)) - (child->getLeadingPosition(YGFlexDirectionRow, width) + child->getTrailingPosition(YGFlexDirectionRow, width)); childWidth = YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth, width, width); @@ -1240,7 +1226,7 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, child->isTrailingPosDefined(YGFlexDirectionColumn)) { childHeight = node->getLayout().measuredDimensions[YGDimensionHeight] - (node->getLeadingBorder(YGFlexDirectionColumn) + - YGNodeTrailingBorder(node, YGFlexDirectionColumn)) - + node->getTrailingBorder(YGFlexDirectionColumn)) - (child->getLeadingPosition(YGFlexDirectionColumn, height) + child->getTrailingPosition(YGFlexDirectionColumn, height)); childHeight = YGNodeBoundAxis(child, YGFlexDirectionColumn, childHeight, height, width); @@ -1311,7 +1297,7 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, child->setLayoutPosition( node->getLayout().measuredDimensions[dim[mainAxis]] - child->getLayout().measuredDimensions[dim[mainAxis]] - - YGNodeTrailingBorder(node, mainAxis) - + node->getTrailingBorder(mainAxis) - child->getTrailingMargin(mainAxis, width) - child->getTrailingPosition( mainAxis, isMainAxisRow ? width : height), @@ -1338,7 +1324,7 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, child->setLayoutPosition( node->getLayout().measuredDimensions[dim[crossAxis]] - child->getLayout().measuredDimensions[dim[crossAxis]] - - YGNodeTrailingBorder(node, crossAxis) - + node->getTrailingBorder(crossAxis) - child->getTrailingMargin(crossAxis, width) - child->getTrailingPosition( crossAxis, isMainAxisRow ? height : width), @@ -1775,11 +1761,10 @@ static void YGNodelayoutImpl(const YGNodeRef node, node->getTrailingMargin(flexColumnDirection, parentWidth), YGEdgeBottom); node->setLayoutBorder(node->getLeadingBorder(flexRowDirection), YGEdgeStart); - node->setLayoutBorder( - YGNodeTrailingBorder(node, flexRowDirection), YGEdgeEnd); + node->setLayoutBorder(node->getTrailingBorder(flexRowDirection), YGEdgeEnd); node->setLayoutBorder(node->getLeadingBorder(flexColumnDirection), YGEdgeTop); node->setLayoutBorder( - YGNodeTrailingBorder(node, flexColumnDirection), YGEdgeBottom); + node->getTrailingBorder(flexColumnDirection), YGEdgeBottom); node->setLayoutPadding( YGNodeLeadingPadding(node, flexRowDirection, parentWidth), YGEdgeStart); From 7f94bff89a09547e76b50ae4c96ec59de73a153a Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Mon, 15 Jan 2018 10:09:50 -0800 Subject: [PATCH 14/25] Resolve direction function is now as a method on YGNode Reviewed By: emilsjolander Differential Revision: D6711755 fbshipit-source-id: a0e80596e10f0c7fb7a31b75377da4db846c4bbb --- ReactCommon/yoga/yoga/YGNode.cpp | 9 +++++++++ ReactCommon/yoga/yoga/YGNode.h | 1 + ReactCommon/yoga/yoga/Yoga.cpp | 14 ++------------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ReactCommon/yoga/yoga/YGNode.cpp b/ReactCommon/yoga/yoga/YGNode.cpp index ebe733e760cc85..112fa280642c4a 100644 --- a/ReactCommon/yoga/yoga/YGNode.cpp +++ b/ReactCommon/yoga/yoga/YGNode.cpp @@ -510,6 +510,15 @@ void YGNode::resolveDimension() { } } +YGDirection YGNode::resolveDirection(const YGDirection parentDirection) { + if (style_.direction == YGDirectionInherit) { + return parentDirection > YGDirectionInherit ? parentDirection + : YGDirectionLTR; + } else { + return style_.direction; + } +} + void YGNode::clearChildren() { children_.clear(); children_.shrink_to_fit(); diff --git a/ReactCommon/yoga/yoga/YGNode.h b/ReactCommon/yoga/yoga/YGNode.h index 503894c19ba8b6..f116c3436e31fb 100644 --- a/ReactCommon/yoga/yoga/YGNode.h +++ b/ReactCommon/yoga/yoga/YGNode.h @@ -129,6 +129,7 @@ struct YGNode { YGValue marginTrailingValue(const YGFlexDirection axis) const; YGValue resolveFlexBasisPtr() const; void resolveDimension(); + YGDirection resolveDirection(const YGDirection parentDirection); void clearChildren(); /// Replaces the occurrences of oldChild with newChild void replaceChild(YGNodeRef oldChild, YGNodeRef newChild); diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index 3b536141d1e343..67db51bafb7d07 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -837,15 +837,6 @@ static inline YGAlign YGNodeAlignItem(const YGNodeRef node, const YGNodeRef chil return align; } -static inline YGDirection YGNodeResolveDirection(const YGNodeRef node, - const YGDirection parentDirection) { - if (node->getStyle().direction == YGDirectionInherit) { - return parentDirection > YGDirectionInherit ? parentDirection : YGDirectionLTR; - } else { - return node->getStyle().direction; - } -} - static float YGBaseline(const YGNodeRef node) { if (node->getBaseline() != nullptr) { const float baseline = node->getBaseline()( @@ -1602,8 +1593,7 @@ static void YGNodeComputeFlexBasisForChildren( } if (performLayout) { // Set the initial position (relative to the parent). - const YGDirection childDirection = - YGNodeResolveDirection(child, direction); + const YGDirection childDirection = child->resolveDirection(direction); const float mainDim = YGFlexDirectionIsRow(mainAxis) ? availableInnerWidth : availableInnerHeight; @@ -1744,7 +1734,7 @@ static void YGNodelayoutImpl(const YGNodeRef node, "YGMeasureModeUndefined"); // Set the resolved resolution in the node's layout. - const YGDirection direction = YGNodeResolveDirection(node, parentDirection); + const YGDirection direction = node->resolveDirection(parentDirection); node->setLayoutDirection(direction); const YGFlexDirection flexRowDirection = YGResolveFlexDirection(YGFlexDirectionRow, direction); From bd7bf94af9ddfc9221ac3f6f62821b7e53e9b0ea Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Mon, 15 Jan 2018 10:09:51 -0800 Subject: [PATCH 15/25] Moved leading padding function as a method on YGNode Reviewed By: emilsjolander Differential Revision: D6711830 fbshipit-source-id: d2f6f55ec23b007bb51f8a91385e02236f46dc7b --- ReactCommon/yoga/yoga/YGNode.cpp | 15 +++++++++++++++ ReactCommon/yoga/yoga/YGNode.h | 2 ++ ReactCommon/yoga/yoga/Yoga.cpp | 24 +++--------------------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/ReactCommon/yoga/yoga/YGNode.cpp b/ReactCommon/yoga/yoga/YGNode.cpp index 112fa280642c4a..90bff5de8b8229 100644 --- a/ReactCommon/yoga/yoga/YGNode.cpp +++ b/ReactCommon/yoga/yoga/YGNode.cpp @@ -630,3 +630,18 @@ float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) { ->value, 0.0f); } + +float YGNode::getLeadingPadding( + const YGFlexDirection axis, + const float widthSize) { + if (YGFlexDirectionIsRow(axis) && + style_.padding[YGEdgeStart].unit != YGUnitUndefined && + YGResolveValue(style_.padding[YGEdgeStart], widthSize) >= 0.0f) { + return YGResolveValue(style_.padding[YGEdgeStart], widthSize); + } + return fmaxf( + YGResolveValue( + *YGComputedEdgeValue(style_.padding, leading[axis], &YGValueZero), + widthSize), + 0.0f); +} diff --git a/ReactCommon/yoga/yoga/YGNode.h b/ReactCommon/yoga/yoga/YGNode.h index f116c3436e31fb..2966894162679c 100644 --- a/ReactCommon/yoga/yoga/YGNode.h +++ b/ReactCommon/yoga/yoga/YGNode.h @@ -79,6 +79,7 @@ struct YGNode { std::array getResolvedDimensions() const; YGValue getResolvedDimension(int index); + // Methods related to positions, margin, padding and border float getLeadingPosition(const YGFlexDirection axis, const float axisSize); bool isLeadingPositionDefined(const YGFlexDirection axis); bool isTrailingPosDefined(const YGFlexDirection axis); @@ -87,6 +88,7 @@ struct YGNode { float getTrailingMargin(const YGFlexDirection axis, const float widthSize); float getLeadingBorder(const YGFlexDirection flexDirection); float getTrailingBorder(const YGFlexDirection flexDirection); + float getLeadingPadding(const YGFlexDirection axis, const float widthSize); // Setters void setContext(void* context); diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index 67db51bafb7d07..bb1625616dd396 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -762,24 +762,6 @@ static const std::array pos = {{ static const std::array dim = { {YGDimensionHeight, YGDimensionHeight, YGDimensionWidth, YGDimensionWidth}}; -static float YGNodeLeadingPadding(const YGNodeRef node, - const YGFlexDirection axis, - const float widthSize) { - if (YGFlexDirectionIsRow(axis) && - node->getStyle().padding[YGEdgeStart].unit != YGUnitUndefined && - YGResolveValue(node->getStyle().padding[YGEdgeStart], widthSize) >= - 0.0f) { - return YGResolveValue(node->getStyle().padding[YGEdgeStart], widthSize); - } - - return fmaxf( - YGResolveValue( - *YGComputedEdgeValue( - node->getStyle().padding, leading[axis], &YGValueZero), - widthSize), - 0.0f); -} - static float YGNodeTrailingPadding(const YGNodeRef node, const YGFlexDirection axis, const float widthSize) { @@ -801,7 +783,7 @@ static inline float YGNodeLeadingPaddingAndBorder( const YGNodeRef node, const YGFlexDirection axis, const float widthSize) { - return YGNodeLeadingPadding(node, axis, widthSize) + + return node->getLeadingPadding(axis, widthSize) + node->getLeadingBorder(axis); } @@ -1757,11 +1739,11 @@ static void YGNodelayoutImpl(const YGNodeRef node, node->getTrailingBorder(flexColumnDirection), YGEdgeBottom); node->setLayoutPadding( - YGNodeLeadingPadding(node, flexRowDirection, parentWidth), YGEdgeStart); + node->getLeadingPadding(flexRowDirection, parentWidth), YGEdgeStart); node->setLayoutPadding( YGNodeTrailingPadding(node, flexRowDirection, parentWidth), YGEdgeEnd); node->setLayoutPadding( - YGNodeLeadingPadding(node, flexColumnDirection, parentWidth), YGEdgeTop); + node->getLeadingPadding(flexColumnDirection, parentWidth), YGEdgeTop); node->setLayoutPadding( YGNodeTrailingPadding(node, flexColumnDirection, parentWidth), YGEdgeBottom); From 2fe65b032e9ec3faf3cef31290372b9face2d3f1 Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Mon, 15 Jan 2018 10:09:53 -0800 Subject: [PATCH 16/25] Move trailing padding function as a method on YGNode Reviewed By: emilsjolander Differential Revision: D6711897 fbshipit-source-id: fa2e1a8e31242358a6e94aef51368e2c2c58b79d --- ReactCommon/yoga/yoga/YGNode.cpp | 15 +++++++++++++++ ReactCommon/yoga/yoga/YGNode.h | 1 + ReactCommon/yoga/yoga/Yoga.cpp | 24 +++--------------------- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/ReactCommon/yoga/yoga/YGNode.cpp b/ReactCommon/yoga/yoga/YGNode.cpp index 90bff5de8b8229..7b4d98e1c4d2fa 100644 --- a/ReactCommon/yoga/yoga/YGNode.cpp +++ b/ReactCommon/yoga/yoga/YGNode.cpp @@ -645,3 +645,18 @@ float YGNode::getLeadingPadding( widthSize), 0.0f); } + +float YGNode::getTrailingPadding( + const YGFlexDirection axis, + const float widthSize) { + if (YGFlexDirectionIsRow(axis) && + style_.padding[YGEdgeEnd].unit != YGUnitUndefined && + YGResolveValue(style_.padding[YGEdgeEnd], widthSize) >= 0.0f) { + return YGResolveValue(style_.padding[YGEdgeEnd], widthSize); + } + return fmaxf( + YGResolveValue( + *YGComputedEdgeValue(style_.padding, trailing[axis], &YGValueZero), + widthSize), + 0.0f); +} diff --git a/ReactCommon/yoga/yoga/YGNode.h b/ReactCommon/yoga/yoga/YGNode.h index 2966894162679c..8ae19decd2f23e 100644 --- a/ReactCommon/yoga/yoga/YGNode.h +++ b/ReactCommon/yoga/yoga/YGNode.h @@ -89,6 +89,7 @@ struct YGNode { float getLeadingBorder(const YGFlexDirection flexDirection); float getTrailingBorder(const YGFlexDirection flexDirection); float getLeadingPadding(const YGFlexDirection axis, const float widthSize); + float getTrailingPadding(const YGFlexDirection axis, const float widthSize); // Setters void setContext(void* context); diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index bb1625616dd396..a6b89f88d2cac1 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -762,23 +762,6 @@ static const std::array pos = {{ static const std::array dim = { {YGDimensionHeight, YGDimensionHeight, YGDimensionWidth, YGDimensionWidth}}; -static float YGNodeTrailingPadding(const YGNodeRef node, - const YGFlexDirection axis, - const float widthSize) { - if (YGFlexDirectionIsRow(axis) && - node->getStyle().padding[YGEdgeEnd].unit != YGUnitUndefined && - YGResolveValue(node->getStyle().padding[YGEdgeEnd], widthSize) >= 0.0f) { - return YGResolveValue(node->getStyle().padding[YGEdgeEnd], widthSize); - } - - return fmaxf( - YGResolveValue( - *YGComputedEdgeValue( - node->getStyle().padding, trailing[axis], &YGValueZero), - widthSize), - 0.0f); -} - static inline float YGNodeLeadingPaddingAndBorder( const YGNodeRef node, const YGFlexDirection axis, @@ -790,7 +773,7 @@ static inline float YGNodeLeadingPaddingAndBorder( static inline float YGNodeTrailingPaddingAndBorder(const YGNodeRef node, const YGFlexDirection axis, const float widthSize) { - return YGNodeTrailingPadding(node, axis, widthSize) + + return node->getTrailingPadding(axis, widthSize) + node->getTrailingBorder(axis); } @@ -1741,12 +1724,11 @@ static void YGNodelayoutImpl(const YGNodeRef node, node->setLayoutPadding( node->getLeadingPadding(flexRowDirection, parentWidth), YGEdgeStart); node->setLayoutPadding( - YGNodeTrailingPadding(node, flexRowDirection, parentWidth), YGEdgeEnd); + node->getTrailingPadding(flexRowDirection, parentWidth), YGEdgeEnd); node->setLayoutPadding( node->getLeadingPadding(flexColumnDirection, parentWidth), YGEdgeTop); node->setLayoutPadding( - YGNodeTrailingPadding(node, flexColumnDirection, parentWidth), - YGEdgeBottom); + node->getTrailingPadding(flexColumnDirection, parentWidth), YGEdgeBottom); if (node->getMeasure() != nullptr) { YGNodeWithMeasureFuncSetMeasuredDimensions(node, From 831a1bb4b1cc201b53685874a9dbdd6c3c1615ad Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Mon, 15 Jan 2018 10:09:55 -0800 Subject: [PATCH 17/25] Moved leadingpaddingnandborder function as a method on YGNode Reviewed By: emilsjolander Differential Revision: D6711991 fbshipit-source-id: 41ad7191bf8df6fe3131106436dc0c87e9dee297 --- ReactCommon/yoga/yoga/YGNode.cpp | 6 ++++++ ReactCommon/yoga/yoga/YGNode.h | 3 +++ ReactCommon/yoga/yoga/Yoga.cpp | 16 ++++------------ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/ReactCommon/yoga/yoga/YGNode.cpp b/ReactCommon/yoga/yoga/YGNode.cpp index 7b4d98e1c4d2fa..223dd919111977 100644 --- a/ReactCommon/yoga/yoga/YGNode.cpp +++ b/ReactCommon/yoga/yoga/YGNode.cpp @@ -660,3 +660,9 @@ float YGNode::getTrailingPadding( widthSize), 0.0f); } + +float YGNode::getLeadingPaddingAndBorder( + const YGFlexDirection axis, + const float widthSize) { + return getLeadingPadding(axis, widthSize) + getLeadingBorder(axis); +} diff --git a/ReactCommon/yoga/yoga/YGNode.h b/ReactCommon/yoga/yoga/YGNode.h index 8ae19decd2f23e..a639bf901c54e8 100644 --- a/ReactCommon/yoga/yoga/YGNode.h +++ b/ReactCommon/yoga/yoga/YGNode.h @@ -90,6 +90,9 @@ struct YGNode { float getTrailingBorder(const YGFlexDirection flexDirection); float getLeadingPadding(const YGFlexDirection axis, const float widthSize); float getTrailingPadding(const YGFlexDirection axis, const float widthSize); + float getLeadingPaddingAndBorder( + const YGFlexDirection axis, + const float widthSize); // Setters void setContext(void* context); diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index a6b89f88d2cac1..b4f30dd0f1a339 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -762,14 +762,6 @@ static const std::array pos = {{ static const std::array dim = { {YGDimensionHeight, YGDimensionHeight, YGDimensionWidth, YGDimensionWidth}}; -static inline float YGNodeLeadingPaddingAndBorder( - const YGNodeRef node, - const YGFlexDirection axis, - const float widthSize) { - return node->getLeadingPadding(axis, widthSize) + - node->getLeadingBorder(axis); -} - static inline float YGNodeTrailingPaddingAndBorder(const YGNodeRef node, const YGFlexDirection axis, const float widthSize) { @@ -787,8 +779,8 @@ static inline float YGNodeMarginForAxis(const YGNodeRef node, static inline float YGNodePaddingAndBorderForAxis(const YGNodeRef node, const YGFlexDirection axis, const float widthSize) { - return YGNodeLeadingPaddingAndBorder(node, axis, widthSize) + - YGNodeTrailingPaddingAndBorder(node, axis, widthSize); + return node->getLeadingPaddingAndBorder(axis, widthSize) + + YGNodeTrailingPaddingAndBorder(node, axis, widthSize); } static inline YGAlign YGNodeAlignItem(const YGNodeRef node, const YGNodeRef child) { @@ -1785,11 +1777,11 @@ static void YGNodelayoutImpl(const YGNodeRef node, YGNodeRef currentAbsoluteChild = nullptr; const float leadingPaddingAndBorderMain = - YGNodeLeadingPaddingAndBorder(node, mainAxis, parentWidth); + node->getLeadingPaddingAndBorder(mainAxis, parentWidth); const float trailingPaddingAndBorderMain = YGNodeTrailingPaddingAndBorder(node, mainAxis, parentWidth); const float leadingPaddingAndBorderCross = - YGNodeLeadingPaddingAndBorder(node, crossAxis, parentWidth); + node->getLeadingPaddingAndBorder(crossAxis, parentWidth); const float paddingAndBorderAxisMain = YGNodePaddingAndBorderForAxis(node, mainAxis, parentWidth); const float paddingAndBorderAxisCross = YGNodePaddingAndBorderForAxis(node, crossAxis, parentWidth); From ce3146a6f3162141c7dc06d2c91ec291d3756a92 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Mon, 15 Jan 2018 15:25:10 -0800 Subject: [PATCH 18/25] Removed unused core from Image.android.js Summary: Trivial. Reviewed By: sahrens Differential Revision: D6721449 fbshipit-source-id: 6ae001d4161167e0e86b1dc134c1621b3974b489 --- Libraries/Image/Image.android.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index dc561bdb2bffee..451ebc5b637d71 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -19,11 +19,9 @@ var NativeModules = require('NativeModules'); var React = require('React'); var PropTypes = require('prop-types'); var ReactNativeViewAttributes = require('ReactNativeViewAttributes'); -var Set = require('Set'); var StyleSheet = require('StyleSheet'); var StyleSheetPropType = require('StyleSheetPropType'); var ViewPropTypes = require('ViewPropTypes'); -var ViewStylePropTypes = require('ViewStylePropTypes'); var createReactClass = require('create-react-class'); var flattenStyle = require('flattenStyle'); @@ -63,21 +61,6 @@ function generateRequestId() { * More example code in ImageExample.js */ -var ImageViewAttributes = merge(ReactNativeViewAttributes.UIView, { - src: true, - loadingIndicatorSrc: true, - resizeMethod: true, - resizeMode: true, - progressiveRenderingEnabled: true, - fadeDuration: true, - shouldNotifyLoadEvents: true, -}); - -var ViewStyleKeys = new Set(Object.keys(ViewStylePropTypes)); -var ImageSpecificStyleKeys = new Set( - Object.keys(ImageStylePropTypes).filter(x => !ViewStyleKeys.has(x)), -); - var Image = createReactClass({ displayName: 'Image', propTypes: { From 6bb8617f3a2f3f80f89eb00595a621aec35aca83 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Mon, 15 Jan 2018 15:35:51 -0800 Subject: [PATCH 19/25] Exposing `setDirtiedFunc` as plain C function YGNodeSetDirtiedFunc Summary: Trivial. Those lines were lost during rebasing of the original commit. Reviewed By: priteshrnandgaonkar Differential Revision: D6717696 fbshipit-source-id: a5dce25427c8977352b3ae7ea01e546a540e0c13 --- RNTester/js/TextExample.ios.js | 12 ++++++++++++ ReactCommon/yoga/yoga/Yoga.cpp | 8 ++++++++ ReactCommon/yoga/yoga/Yoga.h | 2 ++ 3 files changed, 22 insertions(+) diff --git a/RNTester/js/TextExample.ios.js b/RNTester/js/TextExample.ios.js index 1980ced736bbb3..b4e2a84829fd0c 100644 --- a/RNTester/js/TextExample.ios.js +++ b/RNTester/js/TextExample.ios.js @@ -233,8 +233,20 @@ exports.examples = [ render: function() { return ( + The text + + Text Inside + Another text Inside + + Total inseption + + Insepted Text Inside + + + The text should wrap if it goes on multiple lines. See, this is going to the next line. + The text after. ); }, diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index b4f30dd0f1a339..f357eeaf201d0c 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -175,6 +175,14 @@ void YGNodeSetBaselineFunc(YGNodeRef node, YGBaselineFunc baselineFunc) { node->setBaseLineFunc(baselineFunc); } +YGDirtiedFunc YGNodeGetDirtiedFunc(YGNodeRef node) { + return node->getDirtied(); +} + +void YGNodeSetDirtiedFunc(YGNodeRef node, YGDirtiedFunc dirtiedFunc) { + node->setDirtiedFunc(dirtiedFunc); +} + YGPrintFunc YGNodeGetPrintFunc(YGNodeRef node) { return node->getPrintFunc(); } diff --git a/ReactCommon/yoga/yoga/Yoga.h b/ReactCommon/yoga/yoga/Yoga.h index 28326019fb7aad..df16fce4cb3002 100644 --- a/ReactCommon/yoga/yoga/Yoga.h +++ b/ReactCommon/yoga/yoga/Yoga.h @@ -166,6 +166,8 @@ YGMeasureFunc YGNodeGetMeasureFunc(YGNodeRef node); void YGNodeSetMeasureFunc(YGNodeRef node, YGMeasureFunc measureFunc); YGBaselineFunc YGNodeGetBaselineFunc(YGNodeRef node); void YGNodeSetBaselineFunc(YGNodeRef node, YGBaselineFunc baselineFunc); +YGDirtiedFunc YGNodeGetDirtiedFunc(YGNodeRef node); +void YGNodeSetDirtiedFunc(YGNodeRef node, YGDirtiedFunc dirtiedFunc); YGPrintFunc YGNodeGetPrintFunc(YGNodeRef node); void YGNodeSetPrintFunc(YGNodeRef node, YGPrintFunc printFunc); bool YGNodeGetHasNewLayout(YGNodeRef node); From 2b80cdf1bba3b756915117139474440c203cbd8d Mon Sep 17 00:00:00 2001 From: James Ide Date: Tue, 16 Jan 2018 03:22:32 -0800 Subject: [PATCH 20/25] Fix HMR syntax error messages (`message` instead of `description`) Summary: The code to display HMR errors on the client was reading the `description` field from Metro payloads. Metro does not include `description` in the body of its error payloads -- only in its `body.errors[]` items. This commit changes RN's HMR code to show `body.message` (set consistently with https://github.com/facebook/metro/pull/124) instead of the non-existent `body.description`. Open a test RN app, enable HMR, and then introduce a syntax error in an app source file. See that the redbox provides information about the syntax error instead of just saying "TransformError undefined". - https://github.com/facebook/metro/pull/124 [GENERAL][ENHANCEMENT][HMR] - Fix display of syntax error messages when HMR is enabled Closes https://github.com/facebook/react-native/pull/17619 Differential Revision: D6726516 Pulled By: mjesun fbshipit-source-id: b1d1008d6f1aa8f88ff8a2aa1374724a305c773b --- Libraries/Utilities/HMRClient.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/Utilities/HMRClient.js b/Libraries/Utilities/HMRClient.js index 53cb874c1dc3f8..4934c4ff4283b8 100644 --- a/Libraries/Utilities/HMRClient.js +++ b/Libraries/Utilities/HMRClient.js @@ -121,7 +121,7 @@ Error: ${e.message}` } case 'error': { HMRLoadingView.hide(); - throw new Error(data.body.type + ' ' + data.body.description); + throw new Error(`${data.body.type}: ${data.body.message}`); } default: { throw new Error(`Unexpected message: ${data}`); From 1f5bb374cd31795b31fe1ff895277aae3d1299d9 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Tue, 16 Jan 2018 08:10:27 -0800 Subject: [PATCH 21/25] Revert D6704701: Refactor ReactViewGroup to reuse ReactViewBackgroundManager Differential Revision: D6704701 fbshipit-source-id: 01feb61a9c2c263f88cca4fea5978957c5e4767f --- .../react/views/common/ViewHelper.java | 3 +- .../view/ReactViewBackgroundManager.java | 4 - .../react/views/view/ReactViewGroup.java | 92 ++++++++++++++----- 3 files changed, 72 insertions(+), 27 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/common/ViewHelper.java b/ReactAndroid/src/main/java/com/facebook/react/views/common/ViewHelper.java index acbcefd6d68c26..a560cafcb88cf4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/common/ViewHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/common/ViewHelper.java @@ -4,7 +4,6 @@ import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.annotation.Nullable; import android.view.View; /** Helper class for Views */ @@ -19,7 +18,7 @@ public class ViewHelper { * @param drawable {@link Drawable} The Drawable to use as the background, or null to remove the * background */ - public static void setBackground(View view, @Nullable Drawable drawable) { + public static void setBackground(View view, Drawable drawable) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { view.setBackground(drawable); } else { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java index 1076c9ba378919..0248b93c61a068 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java @@ -57,10 +57,6 @@ public void setBorderRadius(float borderRadius) { getOrCreateReactViewBackground().setRadius(borderRadius); } - public boolean hasRoundedBorders() { - return getOrCreateReactViewBackground().hasRoundedBorders(); - } - public void setBorderRadius(float borderRadius, int position) { getOrCreateReactViewBackground().setRadius(borderRadius, position); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 3351c28451947a..e0984f86e09cac 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -35,7 +35,6 @@ import com.facebook.react.uimanager.ReactPointerEventsView; import com.facebook.react.uimanager.ReactZIndexedViewGroup; import com.facebook.react.uimanager.ViewGroupDrawingOrderHelper; -import com.facebook.react.views.common.ViewHelper; import com.facebook.yoga.YogaConstants; import javax.annotation.Nullable; @@ -52,7 +51,6 @@ public class ReactViewGroup extends ViewGroup implements private static final LayoutParams sDefaultLayoutParam = new ViewGroup.LayoutParams(0, 0); /* should only be used in {@link #updateClippingToRect} */ private static final Rect sHelperRect = new Rect(); - private ReactViewBackgroundManager mReactBackgroundManager; /** * This listener will be set for child views when removeClippedSubview property is enabled. When @@ -113,7 +111,6 @@ public void onLayoutChange( public ReactViewGroup(Context context) { super(context); mDrawingOrderHelper = new ViewGroupDrawingOrderHelper(this); - mReactBackgroundManager = new ReactViewBackgroundManager(this); } @Override @@ -147,19 +144,17 @@ public void requestLayout() { @Override public void setBackgroundColor(int color) { - mReactBackgroundManager.setBackgroundColor(color); - } - - public void setBorderWidth(int position, float width) { - mReactBackgroundManager.setBorderWidth(position, width); - } - - public void setBorderColor(int position, float color, float alpha) { - mReactBackgroundManager.setBorderColor(position, color, alpha); + if (color == Color.TRANSPARENT && mReactBackgroundDrawable == null) { + // don't do anything, no need to allocate ReactBackgroundDrawable for transparent background + } else { + getOrCreateReactViewBackground().setColor(color); + } } - public void setBorderStyle(@Nullable String style) { - mReactBackgroundManager.setBorderStyle(style); + @Override + public void setBackground(Drawable drawable) { + throw new UnsupportedOperationException( + "This method is not supported for ReactViewGroup instances"); } public void setTranslucentBackgroundDrawable(@Nullable Drawable background) { @@ -167,13 +162,13 @@ public void setTranslucentBackgroundDrawable(@Nullable Drawable background) { // background to be a layer drawable that contains a drawable that has been previously setup // as a background previously. This will not work correctly as the drawable callback logic is // messed up in AOSP - ViewHelper.setBackground(this, null); + updateBackgroundDrawable(null); if (mReactBackgroundDrawable != null && background != null) { LayerDrawable layerDrawable = new LayerDrawable(new Drawable[] {mReactBackgroundDrawable, background}); - ViewHelper.setBackground(this, layerDrawable); + updateBackgroundDrawable(layerDrawable); } else if (background != null) { - ViewHelper.setBackground(this, background); + updateBackgroundDrawable(background); } } @@ -225,13 +220,22 @@ public void setNeedsOffscreenAlphaCompositing(boolean needsOffscreenAlphaComposi mNeedsOffscreenAlphaCompositing = needsOffscreenAlphaCompositing; } + public void setBorderWidth(int position, float width) { + getOrCreateReactViewBackground().setBorderWidth(position, width); + } + + public void setBorderColor(int position, float rgb, float alpha) { + getOrCreateReactViewBackground().setBorderColor(position, rgb, alpha); + } + public void setBorderRadius(float borderRadius) { - mReactBackgroundManager.setBorderRadius(borderRadius); + ReactViewBackgroundDrawable backgroundDrawable = getOrCreateReactViewBackground(); + backgroundDrawable.setRadius(borderRadius); if (Build.VERSION_CODES.HONEYCOMB < Build.VERSION.SDK_INT && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { final int UPDATED_LAYER_TYPE = - mReactBackgroundManager.hasRoundedBorders() + backgroundDrawable.hasRoundedBorders() ? View.LAYER_TYPE_SOFTWARE : View.LAYER_TYPE_HARDWARE; @@ -242,12 +246,13 @@ public void setBorderRadius(float borderRadius) { } public void setBorderRadius(float borderRadius, int position) { - mReactBackgroundManager.setBorderRadius(borderRadius, position); + ReactViewBackgroundDrawable backgroundDrawable = getOrCreateReactViewBackground(); + backgroundDrawable.setRadius(borderRadius, position); if (Build.VERSION_CODES.HONEYCOMB < Build.VERSION.SDK_INT && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { final int UPDATED_LAYER_TYPE = - mReactBackgroundManager.hasRoundedBorders() + backgroundDrawable.hasRoundedBorders() ? View.LAYER_TYPE_SOFTWARE : View.LAYER_TYPE_HARDWARE; @@ -257,6 +262,10 @@ public void setBorderRadius(float borderRadius, int position) { } } + public void setBorderStyle(@Nullable String style) { + getOrCreateReactViewBackground().setBorderStyle(style); + } + @Override public void setRemoveClippedSubviews(boolean removeClippedSubviews) { if (removeClippedSubviews == mRemoveClippedSubviews) { @@ -591,6 +600,32 @@ public int getBackgroundColor() { return DEFAULT_BACKGROUND_COLOR; } + private ReactViewBackgroundDrawable getOrCreateReactViewBackground() { + if (mReactBackgroundDrawable == null) { + mReactBackgroundDrawable = new ReactViewBackgroundDrawable(getContext()); + Drawable backgroundDrawable = getBackground(); + updateBackgroundDrawable( + null); // required so that drawable callback is cleared before we add the + // drawable back as a part of LayerDrawable + if (backgroundDrawable == null) { + updateBackgroundDrawable(mReactBackgroundDrawable); + } else { + LayerDrawable layerDrawable = + new LayerDrawable(new Drawable[] {mReactBackgroundDrawable, backgroundDrawable}); + updateBackgroundDrawable(layerDrawable); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + mLayoutDirection = + I18nUtil.getInstance().isRTL(getContext()) + ? LAYOUT_DIRECTION_RTL + : LAYOUT_DIRECTION_LTR; + mReactBackgroundDrawable.setResolvedLayoutDirection(mLayoutDirection); + } + } + return mReactBackgroundDrawable; + } + @Override public @Nullable Rect getHitSlopRect() { return mHitSlopRect; @@ -605,6 +640,21 @@ public void setOverflow(String overflow) { invalidate(); } + /** + * Set the background for the view or remove the background. It calls {@link + * #setBackground(Drawable)} or {@link #setBackgroundDrawable(Drawable)} based on the sdk version. + * + * @param drawable {@link Drawable} The Drawable to use as the background, or null to remove the + * background + */ + private void updateBackgroundDrawable(Drawable drawable) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + super.setBackground(drawable); + } else { + super.setBackgroundDrawable(drawable); + } + } + @Override protected void dispatchDraw(Canvas canvas) { if (mOverflow != null) { From fc6dd78935a41106aa6a44058c1abb7d0ba0fa24 Mon Sep 17 00:00:00 2001 From: Felix Oghina Date: Tue, 16 Jan 2018 08:55:05 -0800 Subject: [PATCH 22/25] Remove SoLoaderShim, use SoLoader Summary: SoLoader is more stable on older versions of Android. Switching to it should fix recurring issues that we get such as `UnsatisfiedLinkError` and so on. CI + run showcase app. Closes https://github.com/facebook/fresco/pull/1989 Reviewed By: erikandre Differential Revision: D6556420 Pulled By: foghina fbshipit-source-id: ffc3faef6452294b4d781258c64ef57e08d107b5 --- .../facebook/react/modules/fresco/FrescoModule.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java index 936a48a5ef6608..b4e0b997d4480d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java @@ -15,7 +15,6 @@ import android.support.annotation.Nullable; import com.facebook.common.logging.FLog; -import com.facebook.common.soloader.SoLoaderShim; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory; import com.facebook.imagepipeline.core.ImagePipelineConfig; @@ -100,9 +99,6 @@ public void initialize() { super.initialize(); getReactApplicationContext().addLifecycleEventListener(this); if (!hasBeenInitialized()) { - // Make sure the SoLoaderShim is configured to use our loader for native libraries. - // This code can be removed if using Fresco from Maven rather than from source - SoLoaderShim.setHandler(new FrescoHandler()); if (mConfig == null) { mConfig = getDefaultConfig(getReactApplicationContext()); } @@ -186,11 +182,4 @@ public void onHostDestroy() { Fresco.getImagePipeline().clearMemoryCaches(); } } - - private static class FrescoHandler implements SoLoaderShim.Handler { - @Override - public void loadLibrary(String libraryName) { - SoLoader.loadLibrary(libraryName); - } - } } From ee5c91c0317b0defbb8da21f7e6d8d3ac8967381 Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Tue, 16 Jan 2018 08:57:11 -0800 Subject: [PATCH 23/25] Fix for failing screenshot tests Reviewed By: emilsjolander Differential Revision: D6726745 fbshipit-source-id: 99f91aabe2337b23953724545f97695238f2124e --- ReactCommon/yoga/yoga/Yoga.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index f357eeaf201d0c..c5413af24b7a81 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -1553,9 +1553,6 @@ static void YGNodeComputeFlexBasisForChildren( child->setDirty(false); continue; } - if (child->getStyle().positionType == YGPositionTypeAbsolute) { - continue; - } if (performLayout) { // Set the initial position (relative to the parent). const YGDirection childDirection = child->resolveDirection(direction); @@ -1568,6 +1565,10 @@ static void YGNodeComputeFlexBasisForChildren( child->setPosition( childDirection, mainDim, crossDim, availableInnerWidth); } + + if (child->getStyle().positionType == YGPositionTypeAbsolute) { + continue; + } if (child == singleFlexChild) { child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount); child->setLayoutComputedFlexBasis(0); From b3a306a66709a0ab0ff29151a38eaa3f8f845c1f Mon Sep 17 00:00:00 2001 From: Ricky Dam Date: Tue, 16 Jan 2018 09:18:45 -0800 Subject: [PATCH 24/25] Removed broken link for 'Getting Help' in the README Summary: I was going through the README and came across a broken link, so I needed to fix it. [ DOCS ] [ BROKEN LINK ] [README.md] Closes https://github.com/facebook/react-native/pull/17620 Differential Revision: D6727943 Pulled By: hramos fbshipit-source-id: ef76d1e4847bc9b190a2076d64fa89a86ca9df93 --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 014138ab3e28cd..05aafba3ca7806 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ See the official [React Native website](https://facebook.github.io/react-native/ Supported operating systems are >= Android 4.1 (API 16) and >= iOS 8.0. - [Getting Started](#getting-started) -- [Getting Help](#getting-help) - [Documentation](#documentation) - [Upgrading](#upgrading) - [Contributing](#contributing) From d0f7d4d107a90fdfbf795d842f4bd4a81290ec62 Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Tue, 16 Jan 2018 09:31:21 -0800 Subject: [PATCH 25/25] Use vector instead of linked list Reviewed By: emilsjolander Differential Revision: D6722959 fbshipit-source-id: 4e81176802b9a9319bc5f385c824a06be14a83a2 --- ReactCommon/yoga/yoga/Yoga.cpp | 275 +++++++++++++++------------------ 1 file changed, 121 insertions(+), 154 deletions(-) diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index c5413af24b7a81..42b90033178483 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -1782,9 +1782,6 @@ static void YGNodelayoutImpl(const YGNodeRef node, const float mainAxisParentSize = isMainAxisRow ? parentWidth : parentHeight; const float crossAxisParentSize = isMainAxisRow ? parentHeight : parentWidth; - YGNodeRef firstAbsoluteChild = nullptr; - YGNodeRef currentAbsoluteChild = nullptr; - const float leadingPaddingAndBorderMain = node->getLeadingPaddingAndBorder(mainAxis, parentWidth); const float trailingPaddingAndBorderMain = @@ -1822,27 +1819,10 @@ static void YGNodelayoutImpl(const YGNodeRef node, YGResolveValue( node->getStyle().maxDimensions[YGDimensionHeight], parentHeight) - paddingAndBorderAxisColumn; + const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight; const float maxInnerMainDim = isMainAxisRow ? maxInnerWidth : maxInnerHeight; - // Make a private linkedlist of absolutely positioned child - for (auto child : node->getChildren()) { - // Absolute-positioned children don't participate in flex layout. Add them - // to a list that we can process later. - if (child->getStyle().positionType == YGPositionTypeAbsolute) { - // Store a private linked list of absolutely positioned children - // so that we can efficiently traverse them later. - if (firstAbsoluteChild == nullptr) { - firstAbsoluteChild = child; - } - if (currentAbsoluteChild != nullptr) { - currentAbsoluteChild->setNextChild(child); - } - currentAbsoluteChild = child; - child->setNextChild(nullptr); - } - } - // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS float availableInnerWidth = YGNodeCalculateAvailableInnerDim( @@ -1909,65 +1889,54 @@ static void YGNodelayoutImpl(const YGNodeRef node, float totalFlexGrowFactors = 0; float totalFlexShrinkScaledFactors = 0; - // Maintain a linked list of the child nodes that can shrink and/or grow. - YGNodeRef firstRelativeChild = nullptr; - YGNodeRef currentRelativeChild = nullptr; + // Maintain a vector of the child nodes that can shrink and/or grow. + std::vector relativeChildren; // Add items to the current line until it's full or we run out of items. for (uint32_t i = startOfLineIndex; i < childCount; i++, endOfLineIndex++) { const YGNodeRef child = node->getChild(i); - if (child->getStyle().display == YGDisplayNone) { + if (child->getStyle().display == YGDisplayNone || + child->getStyle().positionType == YGPositionTypeAbsolute) { continue; } child->setLineIndex(lineCount); + const float childMarginMainAxis = + YGNodeMarginForAxis(child, mainAxis, availableInnerWidth); + const float flexBasisWithMinAndMaxConstraints = + YGNodeBoundAxisWithinMinAndMax( + child, + mainAxis, + child->getLayout().computedFlexBasis, + mainAxisParentSize); + + // If this is a multi-line flow and this item pushes us over the + // available size, we've + // hit the end of the current line. Break out of the loop and lay out + // the current line. + if (sizeConsumedOnCurrentLineIncludingMinConstraint + + flexBasisWithMinAndMaxConstraints + childMarginMainAxis > + availableInnerMainDim && + isNodeFlexWrap && itemsOnLine > 0) { + break; + } - if (child->getStyle().positionType != YGPositionTypeAbsolute) { - const float childMarginMainAxis = YGNodeMarginForAxis(child, mainAxis, availableInnerWidth); - const float flexBasisWithMaxConstraints = fminf( - YGResolveValue( - child->getStyle().maxDimensions[dim[mainAxis]], - mainAxisParentSize), - child->getLayout().computedFlexBasis); - const float flexBasisWithMinAndMaxConstraints = fmaxf( - YGResolveValue( - child->getStyle().minDimensions[dim[mainAxis]], - mainAxisParentSize), - flexBasisWithMaxConstraints); - - // If this is a multi-line flow and this item pushes us over the - // available size, we've - // hit the end of the current line. Break out of the loop and lay out - // the current line. - if (sizeConsumedOnCurrentLineIncludingMinConstraint + flexBasisWithMinAndMaxConstraints + - childMarginMainAxis > - availableInnerMainDim && - isNodeFlexWrap && itemsOnLine > 0) { - break; - } - - sizeConsumedOnCurrentLineIncludingMinConstraint += - flexBasisWithMinAndMaxConstraints + childMarginMainAxis; - sizeConsumedOnCurrentLine += flexBasisWithMinAndMaxConstraints + childMarginMainAxis; - itemsOnLine++; + sizeConsumedOnCurrentLineIncludingMinConstraint += + flexBasisWithMinAndMaxConstraints + childMarginMainAxis; + sizeConsumedOnCurrentLine += + flexBasisWithMinAndMaxConstraints + childMarginMainAxis; + itemsOnLine++; - if (child->isNodeFlexible()) { - totalFlexGrowFactors += child->resolveFlexGrow(); + if (child->isNodeFlexible()) { + totalFlexGrowFactors += child->resolveFlexGrow(); - // Unlike the grow factor, the shrink factor is scaled relative to the child dimension. - totalFlexShrinkScaledFactors += -child->resolveFlexShrink() * - child->getLayout().computedFlexBasis; - } - - // Store a private linked list of children that need to be layed out. - if (firstRelativeChild == nullptr) { - firstRelativeChild = child; - } - if (currentRelativeChild != nullptr) { - currentRelativeChild->setNextChild(child); - } - currentRelativeChild = child; - child->setNextChild(nullptr); + // Unlike the grow factor, the shrink factor is scaled relative to the + // child dimension. + totalFlexShrinkScaledFactors += + -child->resolveFlexShrink() * child->getLayout().computedFlexBasis; } + + // Store a private linked list of children that need to be layed out. + relativeChildren.push_back(child); } // The total flex factor needs to be floored to 1. @@ -2060,18 +2029,13 @@ static void YGNodelayoutImpl(const YGNodeRef node, // First pass: detect the flex items whose min/max constraints trigger float deltaFlexShrinkScaledFactors = 0; float deltaFlexGrowFactors = 0; - currentRelativeChild = firstRelativeChild; - while (currentRelativeChild != nullptr) { - childFlexBasis = fminf( - YGResolveValue( - currentRelativeChild->getStyle().maxDimensions[dim[mainAxis]], - mainAxisParentSize), - fmaxf( - YGResolveValue( - currentRelativeChild->getStyle() - .minDimensions[dim[mainAxis]], - mainAxisParentSize), - currentRelativeChild->getLayout().computedFlexBasis)); + + for (auto currentRelativeChild : relativeChildren) { + childFlexBasis = YGNodeBoundAxisWithinMinAndMax( + currentRelativeChild, + mainAxis, + currentRelativeChild->getLayout().computedFlexBasis, + mainAxisParentSize); if (remainingFreeSpace < 0) { flexShrinkScaledFactor = @@ -2079,14 +2043,15 @@ static void YGNodelayoutImpl(const YGNodeRef node, // Is this child able to shrink? if (flexShrinkScaledFactor != 0) { - baseMainSize = - childFlexBasis + - remainingFreeSpace / totalFlexShrinkScaledFactors * flexShrinkScaledFactor; - boundMainSize = YGNodeBoundAxis(currentRelativeChild, - mainAxis, - baseMainSize, - availableInnerMainDim, - availableInnerWidth); + baseMainSize = childFlexBasis + + remainingFreeSpace / totalFlexShrinkScaledFactors * + flexShrinkScaledFactor; + boundMainSize = YGNodeBoundAxis( + currentRelativeChild, + mainAxis, + baseMainSize, + availableInnerMainDim, + availableInnerWidth); if (baseMainSize != boundMainSize) { // By excluding this item's size and flex factor from remaining, // this item's @@ -2103,13 +2068,14 @@ static void YGNodelayoutImpl(const YGNodeRef node, // Is this child able to grow? if (flexGrowFactor != 0) { - baseMainSize = - childFlexBasis + remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor; - boundMainSize = YGNodeBoundAxis(currentRelativeChild, - mainAxis, - baseMainSize, - availableInnerMainDim, - availableInnerWidth); + baseMainSize = childFlexBasis + + remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor; + boundMainSize = YGNodeBoundAxis( + currentRelativeChild, + mainAxis, + baseMainSize, + availableInnerMainDim, + availableInnerWidth); if (baseMainSize != boundMainSize) { // By excluding this item's size and flex factor from remaining, @@ -2133,18 +2099,12 @@ static void YGNodelayoutImpl(const YGNodeRef node, // Second pass: resolve the sizes of the flexible items deltaFreeSpace = 0; - currentRelativeChild = firstRelativeChild; - while (currentRelativeChild != nullptr) { - childFlexBasis = fminf( - YGResolveValue( - currentRelativeChild->getStyle().maxDimensions[dim[mainAxis]], - mainAxisParentSize), - fmaxf( - YGResolveValue( - currentRelativeChild->getStyle() - .minDimensions[dim[mainAxis]], - mainAxisParentSize), - currentRelativeChild->getLayout().computedFlexBasis)); + for (auto currentRelativeChild : relativeChildren) { + childFlexBasis = YGNodeBoundAxisWithinMinAndMax( + currentRelativeChild, + mainAxis, + currentRelativeChild->getLayout().computedFlexBasis, + mainAxisParentSize); float updatedMainSize = childFlexBasis; if (remainingFreeSpace < 0) { @@ -2157,38 +2117,39 @@ static void YGNodelayoutImpl(const YGNodeRef node, if (totalFlexShrinkScaledFactors == 0) { childSize = childFlexBasis + flexShrinkScaledFactor; } else { - childSize = - childFlexBasis + - (remainingFreeSpace / totalFlexShrinkScaledFactors) * flexShrinkScaledFactor; + childSize = childFlexBasis + + (remainingFreeSpace / totalFlexShrinkScaledFactors) * + flexShrinkScaledFactor; } - updatedMainSize = YGNodeBoundAxis(currentRelativeChild, - mainAxis, - childSize, - availableInnerMainDim, - availableInnerWidth); + updatedMainSize = YGNodeBoundAxis( + currentRelativeChild, + mainAxis, + childSize, + availableInnerMainDim, + availableInnerWidth); } } else if (remainingFreeSpace > 0) { flexGrowFactor = currentRelativeChild->resolveFlexGrow(); // Is this child able to grow? if (flexGrowFactor != 0) { - updatedMainSize = - YGNodeBoundAxis(currentRelativeChild, - mainAxis, - childFlexBasis + - remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor, - availableInnerMainDim, - availableInnerWidth); + updatedMainSize = YGNodeBoundAxis( + currentRelativeChild, + mainAxis, + childFlexBasis + + remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor, + availableInnerMainDim, + availableInnerWidth); } } deltaFreeSpace -= updatedMainSize - childFlexBasis; - const float marginMain = - YGNodeMarginForAxis(currentRelativeChild, mainAxis, availableInnerWidth); - const float marginCross = - YGNodeMarginForAxis(currentRelativeChild, crossAxis, availableInnerWidth); + const float marginMain = YGNodeMarginForAxis( + currentRelativeChild, mainAxis, availableInnerWidth); + const float marginCross = YGNodeMarginForAxis( + currentRelativeChild, crossAxis, availableInnerWidth); float childCrossSize; float childMainSize = updatedMainSize + marginMain; @@ -2216,12 +2177,14 @@ static void YGNodelayoutImpl(const YGNodeRef node, YGUnitAuto) { childCrossSize = availableInnerCrossDim; childCrossMeasureMode = YGMeasureModeExactly; - } else if (!YGNodeIsStyleDimDefined(currentRelativeChild, - crossAxis, - availableInnerCrossDim)) { + } else if (!YGNodeIsStyleDimDefined( + currentRelativeChild, + crossAxis, + availableInnerCrossDim)) { childCrossSize = availableInnerCrossDim; - childCrossMeasureMode = - YGFloatIsUndefined(childCrossSize) ? YGMeasureModeUndefined : YGMeasureModeAtMost; + childCrossMeasureMode = YGFloatIsUndefined(childCrossSize) + ? YGMeasureModeUndefined + : YGMeasureModeAtMost; } else { childCrossSize = YGResolveValue( @@ -2263,7 +2226,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, YGUnitAuto; const float childWidth = isMainAxisRow ? childMainSize : childCrossSize; - const float childHeight = !isMainAxisRow ? childMainSize : childCrossSize; + const float childHeight = + !isMainAxisRow ? childMainSize : childCrossSize; const YGMeasureMode childWidthMeasureMode = isMainAxisRow ? childMainMeasureMode : childCrossMeasureMode; @@ -2272,17 +2236,18 @@ static void YGNodelayoutImpl(const YGNodeRef node, // Recursively call the layout algorithm for this child with the updated // main size. - YGLayoutNodeInternal(currentRelativeChild, - childWidth, - childHeight, - direction, - childWidthMeasureMode, - childHeightMeasureMode, - availableInnerWidth, - availableInnerHeight, - performLayout && !requiresStretchLayout, - "flex", - config); + YGLayoutNodeInternal( + currentRelativeChild, + childWidth, + childHeight, + direction, + childWidthMeasureMode, + childHeightMeasureMode, + availableInnerWidth, + availableInnerHeight, + performLayout && !requiresStretchLayout, + "flex", + config); node->setLayoutHadOverflow( node->getLayout().hadOverflow | currentRelativeChild->getLayout().hadOverflow); @@ -2866,16 +2831,18 @@ static void YGNodelayoutImpl(const YGNodeRef node, if (performLayout) { // STEP 10: SIZING AND POSITIONING ABSOLUTE CHILDREN - for (currentAbsoluteChild = firstAbsoluteChild; - currentAbsoluteChild != nullptr; - currentAbsoluteChild = currentAbsoluteChild->getNextChild()) { - YGNodeAbsoluteLayoutChild(node, - currentAbsoluteChild, - availableInnerWidth, - isMainAxisRow ? measureModeMainDim : measureModeCrossDim, - availableInnerHeight, - direction, - config); + for (auto child : node->getChildren()) { + if (child->getStyle().positionType != YGPositionTypeAbsolute) { + continue; + } + YGNodeAbsoluteLayoutChild( + node, + child, + availableInnerWidth, + isMainAxisRow ? measureModeMainDim : measureModeCrossDim, + availableInnerHeight, + direction, + config); } // STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN