From b283dcdd3e315fdb3f81caec327a645efc8efe0d Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Fri, 29 Jun 2018 12:06:49 -0700 Subject: [PATCH 01/65] RNTester: Cleanup ViewExample.js Summary: Minor cleanup of ViewExample.js in the RNTester. Reviewed By: sahrens Differential Revision: D8690133 fbshipit-source-id: d034f6d215679dac7f19fab90729bb7e7ef39edd --- RNTester/js/ViewExample.js | 267 +++++++++++++++++++++---------------- 1 file changed, 151 insertions(+), 116 deletions(-) diff --git a/RNTester/js/ViewExample.js b/RNTester/js/ViewExample.js index 1cc4ad686772e3..ffa5bd3d2bdee8 100644 --- a/RNTester/js/ViewExample.js +++ b/RNTester/js/ViewExample.js @@ -10,110 +10,11 @@ 'use strict'; -var React = require('react'); -var ReactNative = require('react-native'); -var {StyleSheet, Text, View} = ReactNative; -var TouchableWithoutFeedback = require('TouchableWithoutFeedback'); +/* eslint-disable react-native/no-inline-styles */ -var styles = StyleSheet.create({ - box: { - backgroundColor: '#527FE4', - borderColor: '#000033', - borderWidth: 1, - }, - zIndex: { - justifyContent: 'space-around', - width: 100, - height: 50, - marginTop: -10, - }, -}); - -class ViewBorderStyleExample extends React.Component<{}, $FlowFixMeState> { - state = { - showBorder: true, - }; - - render() { - return ( - - - - Dashed border style - - - Dotted border style - - - - ); - } - - _handlePress = () => { - this.setState({showBorder: !this.state.showBorder}); - }; -} - -class ZIndexExample extends React.Component<{}, $FlowFixMeState> { - state = { - flipped: false, - }; - - render() { - const indices = this.state.flipped ? [-1, 0, 1, 2] : [2, 1, 0, -1]; - return ( - - - Tap to flip sorting order - - ZIndex {indices[0]} - - - ZIndex {indices[1]} - - - ZIndex {indices[2]} - - - ZIndex {indices[3]} - - - - ); - } - - _handlePress = () => { - this.setState({flipped: !this.state.flipped}); - }; -} +const React = require('react'); +const {StyleSheet, Text, View} = require('react-native'); +const TouchableWithoutFeedback = require('TouchableWithoutFeedback'); exports.title = ''; exports.description = @@ -124,7 +25,7 @@ exports.displayName = 'ViewExample'; exports.examples = [ { title: 'Background Color', - render: function() { + render() { return ( Blue background @@ -134,7 +35,7 @@ exports.examples = [ }, { title: 'Border', - render: function() { + render() { return ( 5px blue border @@ -144,7 +45,14 @@ exports.examples = [ }, { title: 'Padding/Margin', - render: function() { + render() { + const styles = StyleSheet.create({ + box: { + backgroundColor: '#527FE4', + borderColor: '#000033', + borderWidth: 1, + }, + }); return ( @@ -167,7 +75,7 @@ exports.examples = [ }, { title: 'Border Radius', - render: function() { + render() { return ( @@ -180,13 +88,54 @@ exports.examples = [ }, { title: 'Border Style', - render: function() { + render() { + type Props = $ReadOnly<{||}>; + type State = {| + showBorder: boolean, + |}; + + class ViewBorderStyleExample extends React.Component { + state = { + showBorder: true, + }; + + render() { + return ( + + + + Dashed border style + + + Dotted border style + + + + ); + } + + _handlePress = () => { + this.setState({showBorder: !this.state.showBorder}); + }; + } return ; }, }, { title: 'Circle with Border Radius', - render: function() { + render() { return ( Overflow hidden + style={{ + borderWidth: 0.5, + height: 10, + marginBottom: 5, + marginRight: 10, + width: 95, + }}> Overflow visible @@ -224,7 +179,7 @@ exports.examples = [ }, { title: 'Opacity', - render: function() { + render() { return ( @@ -254,7 +209,87 @@ exports.examples = [ }, { title: 'ZIndex', - render: function() { + render() { + type Props = $ReadOnly<{||}>; + type State = {| + flipped: boolean, + |}; + + const styles = StyleSheet.create({ + zIndex: { + justifyContent: 'space-around', + width: 100, + height: 50, + marginTop: -10, + }, + }); + + class ZIndexExample extends React.Component { + state = { + flipped: false, + }; + + render() { + const indices = this.state.flipped ? [-1, 0, 1, 2] : [2, 1, 0, -1]; + return ( + + + + Tap to flip sorting order + + + ZIndex {indices[0]} + + + ZIndex {indices[1]} + + + ZIndex {indices[2]} + + + ZIndex {indices[3]} + + + + ); + } + + _handlePress = () => { + this.setState({flipped: !this.state.flipped}); + }; + } return ; }, }, From d9fa1d70dcf70764f0e308353fbac344c515db74 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Fri, 29 Jun 2018 12:06:52 -0700 Subject: [PATCH 02/65] RNTester: Better View Overflow Example Summary: Improves the examples in `ViewExample.js` that tests overflow behavior. Notable: - Test view flattening behavior by setting `overflow` on views that only have other layout-only styles. - Test the default behavior when `overflow` is not set at all. Reviewed By: achen1 Differential Revision: D8690560 fbshipit-source-id: 6320ef51305952d13bf5724b369651fdfd32ff21 --- RNTester/js/ViewExample.js | 48 +++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/RNTester/js/ViewExample.js b/RNTester/js/ViewExample.js index ffa5bd3d2bdee8..5115a08d5ac785 100644 --- a/RNTester/js/ViewExample.js +++ b/RNTester/js/ViewExample.js @@ -146,31 +146,37 @@ exports.examples = [ { title: 'Overflow', render() { + const styles = StyleSheet.create({ + container: { + borderWidth: StyleSheet.hairlineWidth, + height: 12, + marginBottom: 8, + marginEnd: 16, + width: 95, + }, + content: { + height: 20, + width: 200, + }, + }); + + // NOTE: The that sets `overflow` should only have other layout + // styles so that we can accurately test view flattening optimizations. return ( - - - Overflow hidden + + + undefined - - - Overflow visible + + + hidden + + + + + visible From f090840f452a0fb8ddb9d7cdd657c419ca627c1c Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Fri, 29 Jun 2018 12:06:54 -0700 Subject: [PATCH 03/65] RN: Revert D8666509 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Reverts D8666509. Unfortunately, I misunderstood `setClipChildren` on Android. When set on a `ViewGroup`, `setClipChildren` configures whether its //children// — not itself — are clipped to their bounds. This is unlike `overflow` (as it behaves on iOS) which configures whether the view itself is clipped to its bounds. But they are definitely related. In theory, I think we could implement `overflow` using `setClipChildren` by: - Setting `setClipChildren(false)` by default. (This part, I got right.) - When `overflow` is set to `hidden` on a `View`, we create an extra `ViewGroup` (child) within the normal `ViewGroup` (parent). Then, we can set `setClipChildren(true)` on the parent `ViewGroup` which will cause the child `ViewGroup` to be clipped to its bounds. However, I think the tricky thing will be to create the child `ViewGroup` without incurring unintentional side effects. I need to decide whether or not this is worth trying. The alternative is to add a new `clipChildren` boolean prop that is Android-only, but I really hate further bifurcating the platform. But for now, I am reverting my mistake. Reviewed By: achen1 Differential Revision: D8690551 fbshipit-source-id: 1ba3bbcc5458ffbd5c475430ea0382b3fd0916b2 --- .../src/main/java/com/facebook/react/uimanager/ViewProps.java | 4 ++-- .../java/com/facebook/react/views/view/ReactViewGroup.java | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java index 15ea0c6d40ea0f..f85236d4842dc1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java @@ -254,8 +254,8 @@ public static boolean isLayoutOnly(ReadableMap map, String prop) { return map.isNull(BORDER_RIGHT_WIDTH) || map.getDouble(BORDER_RIGHT_WIDTH) == 0d; case BORDER_BOTTOM_WIDTH: return map.isNull(BORDER_BOTTOM_WIDTH) || map.getDouble(BORDER_BOTTOM_WIDTH) == 0d; - case OVERFLOW: - return map.isNull(OVERFLOW) || map.getString(OVERFLOW) == "visible"; + case OVERFLOW: // We do nothing with this right now. + return true; default: return false; } 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 74b14bae8cc5e7..1915b6eb48fb26 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 @@ -112,7 +112,6 @@ public void onLayoutChange( public ReactViewGroup(Context context) { super(context); - setClipChildren(false); mDrawingOrderHelper = new ViewGroupDrawingOrderHelper(this); } @@ -639,7 +638,6 @@ public void setHitSlopRect(@Nullable Rect rect) { } public void setOverflow(String overflow) { - setClipChildren(mOverflow == "hidden"); mOverflow = overflow; invalidate(); } From cfce6ee9d7002da6803eeeb297c5e288470c4e84 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Fri, 29 Jun 2018 12:07:00 -0700 Subject: [PATCH 04/65] RN: Android Constants for Overflow Style Summary: Tidies up the hardcoded strings for referencing the `overflow` style values. Also, the `OVERFLOW` case in the optimized view flattening code path is unnecessary because `OVERFLOW` is already in the `LAYOUT_ONLY_PROPS` set. Reviewed By: achen1 Differential Revision: D8690804 fbshipit-source-id: 3befbe93ed761e57e45f9b50e59bffc8a29a407f --- .../main/java/com/facebook/react/uimanager/ViewProps.java | 5 +++-- .../java/com/facebook/react/views/view/ReactViewGroup.java | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java index f85236d4842dc1..11f09b0b68053d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java @@ -74,6 +74,9 @@ public class ViewProps { public static final String MIN_HEIGHT = "minHeight"; public static final String MAX_HEIGHT = "maxHeight"; + public static final String HIDDEN = "hidden"; + public static final String VISIBLE = "visible"; + public static final String ASPECT_RATIO = "aspectRatio"; // Props that sometimes may prevent us from collapsing views @@ -254,8 +257,6 @@ public static boolean isLayoutOnly(ReadableMap map, String prop) { return map.isNull(BORDER_RIGHT_WIDTH) || map.getDouble(BORDER_RIGHT_WIDTH) == 0d; case BORDER_BOTTOM_WIDTH: return map.isNull(BORDER_BOTTOM_WIDTH) || map.getDouble(BORDER_BOTTOM_WIDTH) == 0d; - case OVERFLOW: // We do nothing with this right now. - return true; default: return false; } 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 1915b6eb48fb26..8d6a2abea8c114 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 @@ -37,6 +37,7 @@ import com.facebook.react.uimanager.RootView; import com.facebook.react.uimanager.RootViewUtil; import com.facebook.react.uimanager.ViewGroupDrawingOrderHelper; +import com.facebook.react.uimanager.ViewProps; import com.facebook.yoga.YogaConstants; import javax.annotation.Nullable; @@ -682,12 +683,12 @@ protected void dispatchDraw(Canvas canvas) { private void dispatchOverflowDraw(Canvas canvas) { if (mOverflow != null) { switch (mOverflow) { - case "visible": + case ViewProps.VISIBLE: if (mPath != null) { mPath.rewind(); } break; - case "hidden": + case ViewProps.HIDDEN: if (mReactBackgroundDrawable != null) { float left = 0f; float top = 0f; From b81c8b51fc6fe3c2dece72e3fe500e175613c5d4 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Fri, 29 Jun 2018 12:07:02 -0700 Subject: [PATCH 05/65] RN: Add Support for `overflow` on Android (Take 2) Summary: Adds support for the `overflow` style property on React Native for Android. This is the second attempt to do this. See https://github.com/facebook/react-native/commit/6110a4cc75bf8f285ff091cc175b9ebf737f88fc (D8666509) for the first attempt. Similar to the first attempt, this sets `setClipChildren(false)` by default on all `ViewGroup` instances. However, this differs in how it implements `overflow: hidden`. Instead of conditionally setting `setClipChildren`, this manually clips children to the `ViewGroup`'s bounds (which was incidentally what we were doing for background + border radius already). Reviewed By: achen1 Differential Revision: D8690805 fbshipit-source-id: 58757825cd9d138c18c8758918d85b4ca1915f87 --- .../facebook/react/uimanager/ViewProps.java | 11 +++++----- .../react/views/view/ReactViewGroup.java | 20 ++++++++++++------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java index 11f09b0b68053d..29ed6e96c0e0d0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java @@ -24,7 +24,6 @@ public class ViewProps { public static final String ALIGN_ITEMS = "alignItems"; public static final String ALIGN_SELF = "alignSelf"; public static final String ALIGN_CONTENT = "alignContent"; - public static final String OVERFLOW = "overflow"; public static final String DISPLAY = "display"; public static final String BOTTOM = "bottom"; public static final String COLLAPSABLE = "collapsable"; @@ -74,9 +73,6 @@ public class ViewProps { public static final String MIN_HEIGHT = "minHeight"; public static final String MAX_HEIGHT = "maxHeight"; - public static final String HIDDEN = "hidden"; - public static final String VISIBLE = "visible"; - public static final String ASPECT_RATIO = "aspectRatio"; // Props that sometimes may prevent us from collapsing views @@ -103,6 +99,10 @@ public class ViewProps { public static final String TEXT_DECORATION_LINE = "textDecorationLine"; public static final String TEXT_BREAK_STRATEGY = "textBreakStrategy"; public static final String OPACITY = "opacity"; + public static final String OVERFLOW = "overflow"; + + public static final String HIDDEN = "hidden"; + public static final String VISIBLE = "visible"; public static final String ALLOW_FONT_SCALING = "allowFontScaling"; public static final String INCLUDE_FONT_PADDING = "includeFontPadding"; @@ -169,7 +169,6 @@ public class ViewProps { FLEX_SHRINK, FLEX_WRAP, JUSTIFY_CONTENT, - OVERFLOW, ALIGN_CONTENT, DISPLAY, @@ -257,6 +256,8 @@ public static boolean isLayoutOnly(ReadableMap map, String prop) { return map.isNull(BORDER_RIGHT_WIDTH) || map.getDouble(BORDER_RIGHT_WIDTH) == 0d; case BORDER_BOTTOM_WIDTH: return map.isNull(BORDER_BOTTOM_WIDTH) || map.getDouble(BORDER_BOTTOM_WIDTH) == 0d; + case OVERFLOW: + return map.isNull(OVERFLOW) || VISIBLE.equals(map.getString(OVERFLOW)); default: return false; } 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 8d6a2abea8c114..bdd522bd2a60ad 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 @@ -113,6 +113,7 @@ public void onLayoutChange( public ReactViewGroup(Context context) { super(context); + setClipChildren(false); mDrawingOrderHelper = new ViewGroupDrawingOrderHelper(this); } @@ -689,12 +690,14 @@ private void dispatchOverflowDraw(Canvas canvas) { } break; case ViewProps.HIDDEN: - if (mReactBackgroundDrawable != null) { - float left = 0f; - float top = 0f; - float right = getWidth(); - float bottom = getHeight(); + float left = 0f; + float top = 0f; + float right = getWidth(); + float bottom = getHeight(); + + boolean hasClipPath = false; + if (mReactBackgroundDrawable != null) { final RectF borderWidth = mReactBackgroundDrawable.getDirectionAwareBorderInsets(); if (borderWidth.top > 0 @@ -817,10 +820,13 @@ private void dispatchOverflowDraw(Canvas canvas) { }, Path.Direction.CW); canvas.clipPath(mPath); - } else { - canvas.clipRect(new RectF(left, top, right, bottom)); + hasClipPath = true; } } + + if (!hasClipPath) { + canvas.clipRect(new RectF(left, top, right, bottom)); + } break; default: break; From 712c2ed5d2f0e2988c3cff276b05c50b7f408ce2 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Fri, 29 Jun 2018 12:09:57 -0700 Subject: [PATCH 06/65] Fabric: Getting rid of `std::to_string()` Summary: @public Suddenly, it is not supported on Android. Luckelly `folly:to()` is as good as `std::to_string()`. Reviewed By: mdvacca Differential Revision: D8655538 fbshipit-source-id: 2b3b970f6a261253aaa6b22dba8338dc66b7195d --- ReactCommon/fabric/attributedstring/conversions.h | 2 +- ReactCommon/fabric/core/shadownode/ShadowNode.cpp | 4 ++-- ReactCommon/fabric/uimanager/TreeMutationInstruction.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ReactCommon/fabric/attributedstring/conversions.h b/ReactCommon/fabric/attributedstring/conversions.h index 478d423517f092..7e63dc1a431c0f 100644 --- a/ReactCommon/fabric/attributedstring/conversions.h +++ b/ReactCommon/fabric/attributedstring/conversions.h @@ -50,7 +50,7 @@ inline void fromDynamic(const folly::dynamic &value, FontWeight &result) { } inline std::string toString(const FontWeight &fontWeight) { - return std::to_string((int)fontWeight); + return folly::to((int)fontWeight); } inline void fromDynamic(const folly::dynamic &value, FontStyle &result) { diff --git a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp index 54e1465eb19e94..ccb7fc1cdd0a09 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp +++ b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp @@ -162,7 +162,7 @@ std::string ShadowNode::getDebugName() const { } std::string ShadowNode::getDebugValue() const { - return "r" + std::to_string(revision_) + (getSealed() ? "/sealed" : ""); + return "r" + folly::to(revision_) + (getSealed() ? "/sealed" : ""); } SharedDebugStringConvertibleList ShadowNode::getDebugChildren() const { @@ -181,7 +181,7 @@ SharedDebugStringConvertibleList ShadowNode::getDebugChildren() const { SharedDebugStringConvertibleList ShadowNode::getDebugProps() const { SharedDebugStringConvertibleList list = {}; - list.push_back(std::make_shared("tag", std::to_string(tag_))); + list.push_back(std::make_shared("tag", folly::to(tag_))); SharedShadowNode sourceNode = getSourceNode(); if (sourceNode) { diff --git a/ReactCommon/fabric/uimanager/TreeMutationInstruction.cpp b/ReactCommon/fabric/uimanager/TreeMutationInstruction.cpp index fd728dd7a41706..c5f07453749c52 100644 --- a/ReactCommon/fabric/uimanager/TreeMutationInstruction.cpp +++ b/ReactCommon/fabric/uimanager/TreeMutationInstruction.cpp @@ -166,20 +166,20 @@ SharedDebugStringConvertibleList TreeMutationInstruction::getDebugProps() const return SharedDebugStringConvertibleList { std::make_shared("parentNode", parentNode_->getDebugDescription(options)), std::make_shared("childNode", newChildNode_->getDebugDescription(options)), - std::make_shared("index", std::to_string(index_)) + std::make_shared("index", folly::to(index_)) }; case Removal: return SharedDebugStringConvertibleList { std::make_shared("parentNode", parentNode_->getDebugDescription(options)), std::make_shared("childNode", oldChildNode_->getDebugDescription(options)), - std::make_shared("index", std::to_string(index_)) + std::make_shared("index", folly::to(index_)) }; case Replacement: return SharedDebugStringConvertibleList { std::make_shared("parentNode", parentNode_->getDebugDescription(options)), std::make_shared("oldChildNode", oldChildNode_->getDebugDescription(options)), std::make_shared("newChildNode", newChildNode_->getDebugDescription(options)), - std::make_shared("index", std::to_string(index_)) + std::make_shared("index", folly::to(index_)) }; } } From 62f9ced099fee68cac7bed6d6e3516acd826508a Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Fri, 29 Jun 2018 12:09:59 -0700 Subject: [PATCH 07/65] Fabric: Subtle changes that make GCC compiler happy Summary: @public Most of them are legit issues which should not be compilable anyways (but Clang tolerates thems). Reviewed By: mdvacca Differential Revision: D8655539 fbshipit-source-id: 645729fb9d6a120ce1ab2b07542abcdacd72320d --- ReactCommon/fabric/core/layout/LayoutableShadowNode.h | 3 ++- ReactCommon/fabric/core/shadownode/ShadowNode.cpp | 2 ++ ReactCommon/fabric/debug/DebugStringConvertible.h | 3 ++- ReactCommon/fabric/debug/DebugStringConvertibleItem.h | 2 ++ ReactCommon/fabric/text/basetext/BaseTextShadowNode.cpp | 9 ++++----- ReactCommon/fabric/uimanager/Differentiator.cpp | 2 +- ReactCommon/fabric/uimanager/ShadowTree.h | 3 +-- ReactCommon/fabric/view/root/RootProps.cpp | 3 +-- ReactCommon/fabric/view/yoga/YogaLayoutableShadowNode.h | 2 +- 9 files changed, 16 insertions(+), 13 deletions(-) diff --git a/ReactCommon/fabric/core/layout/LayoutableShadowNode.h b/ReactCommon/fabric/core/layout/LayoutableShadowNode.h index d664498779dca3..3958f6c5ce525e 100644 --- a/ReactCommon/fabric/core/layout/LayoutableShadowNode.h +++ b/ReactCommon/fabric/core/layout/LayoutableShadowNode.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -23,7 +24,7 @@ struct LayoutContext; class LayoutableShadowNode; using SharedLayoutableShadowNode = std::shared_ptr; -using SharedLayoutableShadowNodeList = std::vector; +using SharedLayoutableShadowNodeList = std::vector; using LayoutableShadowNodeIterator = std::iterator; /* diff --git a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp index ccb7fc1cdd0a09..b2182bcd570d89 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp +++ b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp @@ -7,6 +7,8 @@ #include "ShadowNode.h" +#include + #include #include diff --git a/ReactCommon/fabric/debug/DebugStringConvertible.h b/ReactCommon/fabric/debug/DebugStringConvertible.h index 8ef96d8882fdae..d911072987a721 100644 --- a/ReactCommon/fabric/debug/DebugStringConvertible.h +++ b/ReactCommon/fabric/debug/DebugStringConvertible.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include namespace facebook { @@ -16,7 +17,7 @@ namespace react { class DebugStringConvertible; using SharedDebugStringConvertible = std::shared_ptr; -using SharedDebugStringConvertibleList = std::vector; +using SharedDebugStringConvertibleList = std::vector; struct DebugStringConvertibleOptions { bool format {true}; diff --git a/ReactCommon/fabric/debug/DebugStringConvertibleItem.h b/ReactCommon/fabric/debug/DebugStringConvertibleItem.h index 257ea1db2bc04a..e0499cff0502ad 100644 --- a/ReactCommon/fabric/debug/DebugStringConvertibleItem.h +++ b/ReactCommon/fabric/debug/DebugStringConvertibleItem.h @@ -7,6 +7,8 @@ #pragma once +#include + #include namespace facebook { diff --git a/ReactCommon/fabric/text/basetext/BaseTextShadowNode.cpp b/ReactCommon/fabric/text/basetext/BaseTextShadowNode.cpp index 61e4c65f3fdb44..f2f2d08a7ee80e 100644 --- a/ReactCommon/fabric/text/basetext/BaseTextShadowNode.cpp +++ b/ReactCommon/fabric/text/basetext/BaseTextShadowNode.cpp @@ -8,11 +8,10 @@ #include "BaseTextShadowNode.h" #include - -#include "RawTextShadowNode.h" -#include "RawTextProps.h" -#include "TextShadowNode.h" -#include "TextProps.h" +#include +#include +#include +#include namespace facebook { namespace react { diff --git a/ReactCommon/fabric/uimanager/Differentiator.cpp b/ReactCommon/fabric/uimanager/Differentiator.cpp index 6e27fa75352715..7a2c9a4f613a12 100644 --- a/ReactCommon/fabric/uimanager/Differentiator.cpp +++ b/ReactCommon/fabric/uimanager/Differentiator.cpp @@ -30,7 +30,7 @@ static void calculateMutationInstructions( return; } - std::unordered_set insertedTags = {}; + std::unordered_set insertedTags; int index = 0; TreeMutationInstructionList createInstructions = {}; diff --git a/ReactCommon/fabric/uimanager/ShadowTree.h b/ReactCommon/fabric/uimanager/ShadowTree.h index d056e4b562240b..3bb6af8b44dc6d 100644 --- a/ReactCommon/fabric/uimanager/ShadowTree.h +++ b/ReactCommon/fabric/uimanager/ShadowTree.h @@ -7,7 +7,6 @@ #include #include -#include #include #include @@ -84,7 +83,7 @@ class ShadowTree final: const Tag rootTag_; SharedRootShadowNode rootShadowNode_; ShadowTreeDelegate *delegate_; - mutable std::mutex commitMutex_ {}; + mutable std::mutex commitMutex_; }; } // namespace react diff --git a/ReactCommon/fabric/view/root/RootProps.cpp b/ReactCommon/fabric/view/root/RootProps.cpp index ec7260b539efde..fe9f711d3ac2cc 100644 --- a/ReactCommon/fabric/view/root/RootProps.cpp +++ b/ReactCommon/fabric/view/root/RootProps.cpp @@ -8,8 +8,7 @@ #include "RootProps.h" #include - -#include "YogaLayoutableShadowNode.h" +#include namespace facebook { namespace react { diff --git a/ReactCommon/fabric/view/yoga/YogaLayoutableShadowNode.h b/ReactCommon/fabric/view/yoga/YogaLayoutableShadowNode.h index 2da836d8a99c34..c35b812af77eb9 100644 --- a/ReactCommon/fabric/view/yoga/YogaLayoutableShadowNode.h +++ b/ReactCommon/fabric/view/yoga/YogaLayoutableShadowNode.h @@ -26,7 +26,7 @@ class YogaLayoutableShadowNode; using SharedYogaConfig = std::shared_ptr; using SharedYogaLayoutableShadowNode = std::shared_ptr; -using SharedYogaLayoutableShadowNodeList = std::vector; +using SharedYogaLayoutableShadowNodeList = std::vector; using SharedYogaLayoutableShadowNodeSharedList = std::shared_ptr; class YogaLayoutableShadowNode: From 7b1bd4d4f3169de5777c953cb16c40fc844136c6 Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Fri, 29 Jun 2018 12:48:38 -0700 Subject: [PATCH 08/65] remove useless config in circle ci (#19980) Summary: The gradle path is unnecessary. pass all current ci. none [GENERAL] [INTERNAL] [CI] - remove useless config in circle ci. Closes https://github.com/facebook/react-native/pull/19980 Differential Revision: D8700298 Pulled By: hramos fbshipit-source-id: ed50cab035f0d78dc482023460692a2ce137fb48 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4803f45845c7c1..336b4dbf200818 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -176,7 +176,7 @@ aliases: - &configure-android-path name: Configure Environment Variables command: | - echo 'export PATH=${ANDROID_NDK}:~/react-native/gradle-2.9/bin:~/buck/bin:$PATH' >> $BASH_ENV + echo 'export PATH=${ANDROID_NDK}:~/buck/bin:$PATH' >> $BASH_ENV source $BASH_ENV - &install-android-packages From 5d9326be29be8688f2238c72c18a9037f983c77d Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Fri, 29 Jun 2018 15:30:30 -0700 Subject: [PATCH 09/65] Remove instanceHandle, pass event target instead + add dispatchToEmptyTarget Summary: Removes the concept of instance handle. Instead we pass the event target to createNode and don't pass it to subsequent clones. The life time of the event target is managed by native (the event emitter). It has to be released manually. Reviewed By: shergin Differential Revision: D8688330 fbshipit-source-id: e11b61f147ea9ca4dfb453fe07063ed06f24b7ac --- .../facebook/react/fabric/FabricBinding.java | 9 ++- .../react/fabric/FabricUIManager.java | 31 ++++---- .../fabric/events/FabricEventEmitter.java | 7 +- .../react/fabric/jsc/FabricJSCBinding.java | 11 ++- .../react/fabric/jsc/jni/FabricJSCBinding.cpp | 72 +++++++++++-------- .../react/fabric/jsc/jni/FabricJSCBinding.h | 9 ++- .../react/fabric/FabricUIManagerTest.java | 31 +++----- .../componentdescriptor/ComponentDescriptor.h | 2 +- .../ConcreteComponentDescriptor.h | 4 +- .../fabric/core/events/EventDispatcher.h | 2 - .../fabric/core/events/EventEmitter.cpp | 13 +--- ReactCommon/fabric/core/events/EventEmitter.h | 7 +- .../fabric/uimanager/FabricUIManager.cpp | 40 ++++++----- .../fabric/uimanager/FabricUIManager.h | 26 +++---- .../uimanager/SchedulerEventDispatcher.cpp | 10 +-- .../uimanager/SchedulerEventDispatcher.h | 2 - 16 files changed, 134 insertions(+), 142 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricBinding.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricBinding.java index 0636c17c24efb6..4db39a42522fe9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricBinding.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricBinding.java @@ -14,12 +14,17 @@ public interface FabricBinding { void installFabric(JavaScriptContextHolder jsContext, FabricUIManager fabricModule); - long createEventTarget(long jsContextNativePointer, long instanceHandlePointer); - void releaseEventTarget(long jsContextNativePointer, long eventTargetPointer); void releaseEventHandler(long jsContextNativePointer, long eventHandlerPointer); + void dispatchEventToEmptyTarget( + long jsContextNativePointer, + long eventHandlerPointer, + String type, + NativeMap payload + ); + void dispatchEventToTarget( long jsContextNativePointer, long eventHandlerPointer, diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index 05ce4025e3ad04..87d1850e674226 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -106,7 +106,7 @@ public void setBinding(FabricBinding binding) { @Nullable @DoNotStrip public ReactShadowNode createNode( - int reactTag, String viewName, int rootTag, ReadableNativeMap props, long instanceHandle) { + int reactTag, String viewName, int rootTag, ReadableNativeMap props, long eventTarget) { if (DEBUG) { FLog.d(TAG, "createNode \n\ttag: " + reactTag + "\n\tviewName: " + viewName + @@ -119,7 +119,7 @@ public ReactShadowNode createNode( ReactShadowNode rootNode = getRootNode(rootTag); node.setRootTag(rootNode.getReactTag()); node.setViewClassName(viewName); - node.setInstanceHandle(instanceHandle); + node.setInstanceHandle(eventTarget); node.setReactTag(reactTag); node.setThemedContext(rootNode.getThemedContext()); @@ -157,7 +157,7 @@ private ReactStylesDiffMap updateProps(ReactShadowNode node, @Nullable ReadableN */ @Nullable @DoNotStrip - public ReactShadowNode cloneNode(ReactShadowNode node, long instanceHandle) { + public ReactShadowNode cloneNode(ReactShadowNode node) { if (DEBUG) { FLog.d(TAG, "cloneNode \n\tnode: " + node); } @@ -166,7 +166,7 @@ public ReactShadowNode cloneNode(ReactShadowNode node, long instanceHandle) { "FabricUIManager.cloneNode") .flush(); try { - ReactShadowNode clone = node.mutableCopy(instanceHandle); + ReactShadowNode clone = node.mutableCopy(node.getInstanceHandle()); assertReactShadowNodeCopy(node, clone); return clone; } catch (Throwable t) { @@ -184,7 +184,7 @@ public ReactShadowNode cloneNode(ReactShadowNode node, long instanceHandle) { */ @Nullable @DoNotStrip - public ReactShadowNode cloneNodeWithNewChildren(ReactShadowNode node, long instanceHandle) { + public ReactShadowNode cloneNodeWithNewChildren(ReactShadowNode node) { if (DEBUG) { FLog.d(TAG, "cloneNodeWithNewChildren \n\tnode: " + node); } @@ -193,7 +193,7 @@ public ReactShadowNode cloneNodeWithNewChildren(ReactShadowNode node, long insta "FabricUIManager.cloneNodeWithNewChildren") .flush(); try { - ReactShadowNode clone = node.mutableCopyWithNewChildren(instanceHandle); + ReactShadowNode clone = node.mutableCopyWithNewChildren(node.getInstanceHandle()); assertReactShadowNodeCopy(node, clone); return clone; } catch (Throwable t) { @@ -212,7 +212,7 @@ public ReactShadowNode cloneNodeWithNewChildren(ReactShadowNode node, long insta @Nullable @DoNotStrip public ReactShadowNode cloneNodeWithNewProps( - ReactShadowNode node, @Nullable ReadableNativeMap newProps, long instanceHandle) { + ReactShadowNode node, @Nullable ReadableNativeMap newProps) { if (DEBUG) { FLog.d(TAG, "cloneNodeWithNewProps \n\tnode: " + node + "\n\tprops: " + newProps); } @@ -221,7 +221,7 @@ public ReactShadowNode cloneNodeWithNewProps( "FabricUIManager.cloneNodeWithNewProps") .flush(); try { - ReactShadowNode clone = node.mutableCopyWithNewProps(instanceHandle, + ReactShadowNode clone = node.mutableCopyWithNewProps(node.getInstanceHandle(), newProps == null ? null : new ReactStylesDiffMap(newProps)); assertReactShadowNodeCopy(node, clone); return clone; @@ -242,7 +242,7 @@ public ReactShadowNode cloneNodeWithNewProps( @Nullable @DoNotStrip public ReactShadowNode cloneNodeWithNewChildrenAndProps( - ReactShadowNode node, ReadableNativeMap newProps, long instanceHandle) { + ReactShadowNode node, ReadableNativeMap newProps) { if (DEBUG) { FLog.d(TAG, "cloneNodeWithNewChildrenAndProps \n\tnode: " + node + "\n\tnewProps: " + newProps); } @@ -252,7 +252,7 @@ public ReactShadowNode cloneNodeWithNewChildrenAndProps( .flush(); try { ReactShadowNode clone = - node.mutableCopyWithNewChildrenAndProps(instanceHandle, + node.mutableCopyWithNewChildrenAndProps(node.getInstanceHandle(), newProps == null ? null : new ReactStylesDiffMap(newProps)); assertReactShadowNodeCopy(node, clone); return clone; @@ -610,16 +610,9 @@ private void handleException(ReactShadowNode node, Throwable t) { @Nullable @DoNotStrip - public long createEventTarget(int reactTag) { + public long getEventTarget(int reactTag) { long instanceHandle = mNativeViewHierarchyManager.getInstanceHandle(reactTag); - long context = mJSContext.get(); - long eventTarget = mBinding.createEventTarget(context, instanceHandle); - if (DEBUG) { - FLog.d( - TAG, - "Created EventTarget: " + eventTarget + " for tag: " + reactTag + " with instanceHandle: " + instanceHandle); - } - return eventTarget; + return instanceHandle; } @DoNotStrip diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/events/FabricEventEmitter.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/events/FabricEventEmitter.java index 4a705bb7505580..2d1c01d8692226 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/events/FabricEventEmitter.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/events/FabricEventEmitter.java @@ -49,7 +49,7 @@ public FabricEventEmitter(ReactApplicationContext context, FabricUIManager fabri @Override public void receiveEvent(int reactTag, String eventName, @Nullable WritableMap params) { try { - long eventTarget = mFabricUIManager.createEventTarget(reactTag); + long eventTarget = mFabricUIManager.getEventTarget(reactTag); mScheduler.scheduleWork(new FabricUIManagerWork(eventTarget, eventName, params)); } catch (IllegalViewOperationException e) { FLog.e(TAG, "Unable to emmit event for tag " + reactTag, e); @@ -80,7 +80,10 @@ public void run() { FLog.e(TAG, "Error sending event " + mEventName, t); //TODO: manage exception properly } finally{ - mFabricUIManager.releaseEventTarget(mEventTarget); + // TODO(dvacca): We need to only release this after all shadow nodes + // have been released. The easiest way would be to adopt the event + // emitter approach from the C++ Fabric. For now, we'll just leak. + // mFabricUIManager.releaseEventTarget(mEventTarget); } } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/FabricJSCBinding.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/FabricJSCBinding.java index 38bbbfe636fa1a..92e82d41e51ea6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/FabricJSCBinding.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/FabricJSCBinding.java @@ -28,15 +28,20 @@ public class FabricJSCBinding implements FabricBinding { private static native HybridData initHybrid(); - @Override - public native long createEventTarget(long jsContextNativePointer, long instanceHandlePointer); - @Override public native void releaseEventTarget(long jsContextNativePointer, long eventTargetPointer); @Override public native void releaseEventHandler(long jsContextNativePointer, long eventHandlerPointer); + @Override + public native void dispatchEventToEmptyTarget( + long jsContextNativePointer, + long eventHandlerPointer, + String type, + NativeMap payload + ); + @Override public native void dispatchEventToTarget( long jsContextNativePointer, diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.cpp index 9b18298562c6ca..5717c930b6821e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.cpp @@ -103,9 +103,9 @@ JSValueRef createNode(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb int rootTag = (int)JSC_JSValueToNumber(ctx, arguments[2], NULL); auto props = JSC_JSValueIsNull(ctx, arguments[3]) ? local_ref(nullptr) : JSValueToReadableMapViaJSON(ctx, arguments[3]);; - auto instanceHandle = (void *)arguments[4]; + auto eventTarget = (void *)arguments[4]; - auto node = createNode(manager, reactTag, viewName.get(), rootTag, props.get(), (jlong)instanceHandle); + auto node = createNode(manager, reactTag, viewName.get(), rootTag, props.get(), (jlong)eventTarget); return JSC_JSObjectMake(ctx, classRef, makePlainGlobalRef(node.get())); } @@ -117,11 +117,10 @@ JSValueRef cloneNode(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj static auto cloneNode = jni::findClassStatic("com/facebook/react/fabric/FabricUIManager") - ->getMethod(JShadowNode::javaobject, jlong)>("cloneNode"); + ->getMethod(JShadowNode::javaobject)>("cloneNode"); auto previousNode = JSValueToJShadowNode(ctx, arguments[0]); - auto instanceHandle = (void *)arguments[1]; - auto newNode = cloneNode(manager, previousNode.get(), (jlong)instanceHandle); + auto newNode = cloneNode(manager, previousNode.get()); return JSC_JSObjectMake(ctx, classRef, makePlainGlobalRef(newNode.get())); } @@ -133,11 +132,10 @@ JSValueRef cloneNodeWithNewChildren(JSContextRef ctx, JSObjectRef function, JSOb static auto cloneNodeWithNewChildren = jni::findClassStatic("com/facebook/react/fabric/FabricUIManager") - ->getMethod(JShadowNode::javaobject, jlong)>("cloneNodeWithNewChildren"); + ->getMethod(JShadowNode::javaobject)>("cloneNodeWithNewChildren"); auto previousNode = JSValueToJShadowNode(ctx, arguments[0]); - auto instanceHandle = (void *)arguments[1]; - auto newNode = cloneNodeWithNewChildren(manager, previousNode.get(), (jlong)instanceHandle); + auto newNode = cloneNodeWithNewChildren(manager, previousNode.get()); return JSC_JSObjectMake(ctx, classRef, makePlainGlobalRef(newNode.get())); } @@ -149,12 +147,11 @@ JSValueRef cloneNodeWithNewProps(JSContextRef ctx, JSObjectRef function, JSObjec static auto cloneNodeWithNewProps = jni::findClassStatic("com/facebook/react/fabric/FabricUIManager") - ->getMethod(JShadowNode::javaobject, ReadableNativeMap::javaobject, jlong)>("cloneNodeWithNewProps"); + ->getMethod(JShadowNode::javaobject, ReadableNativeMap::javaobject)>("cloneNodeWithNewProps"); auto previousNode = JSValueToJShadowNode(ctx, arguments[0]); auto props = JSValueToReadableMapViaJSON(ctx, arguments[1]); - auto instanceHandle = (void *)arguments[2]; - auto newNode = cloneNodeWithNewProps(manager, previousNode.get(), props.get(), (jlong)instanceHandle); + auto newNode = cloneNodeWithNewProps(manager, previousNode.get(), props.get()); return JSC_JSObjectMake(ctx, classRef, makePlainGlobalRef(newNode.get())); } @@ -166,12 +163,11 @@ JSValueRef cloneNodeWithNewChildrenAndProps(JSContextRef ctx, JSObjectRef functi static auto cloneNodeWithNewChildrenAndProps = jni::findClassStatic("com/facebook/react/fabric/FabricUIManager") - ->getMethod(JShadowNode::javaobject, ReadableNativeMap::javaobject, jlong)>("cloneNodeWithNewChildrenAndProps"); + ->getMethod(JShadowNode::javaobject, ReadableNativeMap::javaobject)>("cloneNodeWithNewChildrenAndProps"); auto previousNode = JSValueToJShadowNode(ctx, arguments[0]); auto props = JSValueToReadableMapViaJSON(ctx, arguments[1]); - auto instanceHandle = (void *)arguments[2]; - auto newNode = cloneNodeWithNewChildrenAndProps(manager, previousNode.get(), props.get(), (jlong)instanceHandle); + auto newNode = cloneNodeWithNewChildrenAndProps(manager, previousNode.get(), props.get()); return JSC_JSObjectMake(ctx, classRef, makePlainGlobalRef(newNode.get())); } @@ -293,25 +289,11 @@ jni::local_ref FabricJSCBinding::initHybrid( return makeCxxInstance(); } -jlong FabricJSCBinding::createEventTarget( - jlong jsContextNativePointer, - jlong instanceHandlePointer -) { - JSContextRef context = (JSContextRef)jsContextNativePointer; - JSValueRef value = (JSValueRef)instanceHandlePointer; - // Retain a strong reference to this object. - JSC_JSValueProtect(context, value); - return (jlong)((void *)value); -} - void FabricJSCBinding::releaseEventTarget( jlong jsContextNativePointer, jlong eventTargetPointer ) { - JSContextRef context = (JSContextRef)jsContextNativePointer; - JSValueRef value = (JSValueRef)((void *)eventTargetPointer); - // Release this object. - JSC_JSValueUnprotect(context, value); + // This is now a noop. } void FabricJSCBinding::releaseEventHandler( @@ -324,6 +306,36 @@ void FabricJSCBinding::releaseEventHandler( JSC_JSValueUnprotect(context, value); } +void FabricJSCBinding::dispatchEventToEmptyTarget( + jlong jsContextNativePointer, + jlong eventHandlerPointer, + std::string type, + NativeMap *payloadMap +) { + JSContextRef context = (JSContextRef)jsContextNativePointer; + JSObjectRef eventHandler = (JSObjectRef)((void *)eventHandlerPointer); + JSValueRef eventTarget = JSC_JSValueMakeNull(context); + + JSObjectRef thisArg = (JSObjectRef)JSC_JSValueMakeUndefined(context); + JSStringRef typeStr = JSC_JSStringCreateWithUTF8CString(context, type.c_str()); + JSValueRef typeRef = JSC_JSValueMakeString(context, typeStr); + JSC_JSStringRelease(context, typeStr); + JSValueRef payloadRef = ReadableMapToJSValueViaJSON(context, payloadMap); + JSValueRef args[] = {eventTarget, typeRef, payloadRef}; + JSValueRef exn; + JSValueRef result = JSC_JSObjectCallAsFunction( + context, + eventHandler, + thisArg, + 3, + args, + &exn + ); + if (!result) { + // TODO: Handle error in exn + } +} + void FabricJSCBinding::dispatchEventToTarget( jlong jsContextNativePointer, jlong eventHandlerPointer, @@ -392,9 +404,9 @@ void FabricJSCBinding::registerNatives() { registerHybrid({ makeNativeMethod("initHybrid", FabricJSCBinding::initHybrid), makeNativeMethod("installFabric", FabricJSCBinding::installFabric), - makeNativeMethod("createEventTarget", FabricJSCBinding::createEventTarget), makeNativeMethod("releaseEventTarget", FabricJSCBinding::releaseEventTarget), makeNativeMethod("releaseEventHandler", FabricJSCBinding::releaseEventHandler), + makeNativeMethod("dispatchEventToEmptyTarget", FabricJSCBinding::dispatchEventToEmptyTarget), makeNativeMethod("dispatchEventToTarget", FabricJSCBinding::dispatchEventToTarget), }); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.h b/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.h index 40b7cbd1681fcc..d47a0bb584d8cb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.h +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.h @@ -27,12 +27,17 @@ class FabricJSCBinding : public jni::HybridClass { static jni::local_ref initHybrid(jni::alias_ref); - jlong createEventTarget(jlong jsContextNativePointer, jlong instanceHandlePointer); - void releaseEventTarget(jlong jsContextNativePointer, jlong eventTargetPointer); void releaseEventHandler(jlong jsContextNativePointer, jlong eventHandlerPointer); + void dispatchEventToEmptyTarget( + jlong jsContextNativePointer, + jlong eventHandlerPointer, + std::string type, + NativeMap *payload + ); + void dispatchEventToTarget( jlong jsContextNativePointer, jlong eventHandlerPointer, diff --git a/ReactAndroid/src/test/java/com/facebook/react/fabric/FabricUIManagerTest.java b/ReactAndroid/src/test/java/com/facebook/react/fabric/FabricUIManagerTest.java index ee7e96fb2f0687..93f601c5ffafbe 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/fabric/FabricUIManagerTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/fabric/FabricUIManagerTest.java @@ -103,7 +103,7 @@ public void testCloneNode() { ReactShadowNode child = createViewNode(); node.addChildAt(child, 0); - ReactShadowNode clonedNode = mFabricUIManager.cloneNode(node, 0); + ReactShadowNode clonedNode = mFabricUIManager.cloneNode(node); assertThat(clonedNode).isNotSameAs(node); assertThat(clonedNode.getOriginalReactShadowNode()).isSameAs(node); @@ -112,27 +112,12 @@ public void testCloneNode() { assertThat(clonedNode.getChildAt(0)).isEqualTo(child); } - - @Test - public void testCloneWithInstanceHandle() { - ReactShadowNode node = createViewNode(); - - long oldInstanceHandle = node.getInstanceHandle(); - long newInstanceHandle = oldInstanceHandle + 1; - ReactShadowNode clonedNode = mFabricUIManager.cloneNode(node, newInstanceHandle); - - assertThat(clonedNode).isNotSameAs(node); - assertThat(clonedNode.getInstanceHandle()).isSameAs(newInstanceHandle); - assertThat(node.getInstanceHandle()).isSameAs(oldInstanceHandle); - } - - @Test public void testDefaultSpacingCloning() { ReactShadowNode node = createViewNode(); node.setDefaultPadding(Spacing.LEFT, 10); - ReactShadowNode clonedNode = mFabricUIManager.cloneNode(node, 0); + ReactShadowNode clonedNode = mFabricUIManager.cloneNode(node); node.setDefaultPadding(Spacing.LEFT, 20); assertThat(clonedNode.getStylePadding(Spacing.LEFT).value).isEqualTo(10f, Offset.offset(0.01f)); @@ -165,7 +150,7 @@ public void testCloneNodeWithNewChildren() { ReactShadowNode child = createViewNode(); node.addChildAt(child, 0); - ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewChildren(node, randomInstanceHandle()); + ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewChildren(node); assertThat(clonedNode.getChildCount()).isZero(); assertSameFields(clonedNode, node); @@ -176,7 +161,7 @@ public void testCloneNodeWithNewProps() { ReactShadowNode node = createViewNode(); ReadableNativeMap props = null; // TODO(ayc): Figure out how to create a Native map from tests. - ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewProps(node, props, randomInstanceHandle()); + ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewProps(node, props); } @Test @@ -184,7 +169,7 @@ public void testCloneNodeWithNewChildrenAndProps() { ReactShadowNode node = createViewNode(); ReadableNativeMap props = null; - ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewChildrenAndProps(node, props, randomInstanceHandle()); + ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewChildrenAndProps(node, props); assertThat(clonedNode.getChildCount()).isZero(); } @@ -299,10 +284,10 @@ public void testRemoveOriginalNodeReferences() { mFabricUIManager.appendChildToSet(childSet, container); mFabricUIManager.completeRoot(rootTag, childSet); - ReactShadowNode aaClone = mFabricUIManager.cloneNodeWithNewProps(aa, null, 0); - ReactShadowNode aClone = mFabricUIManager.cloneNodeWithNewChildren(a, 0); + ReactShadowNode aaClone = mFabricUIManager.cloneNodeWithNewProps(aa, null); + ReactShadowNode aClone = mFabricUIManager.cloneNodeWithNewChildren(a); mFabricUIManager.appendChild(aClone, aaClone); - ReactShadowNode containerClone = mFabricUIManager.cloneNodeWithNewChildren(container, 0); + ReactShadowNode containerClone = mFabricUIManager.cloneNodeWithNewChildren(container); mFabricUIManager.appendChild(containerClone, b); mFabricUIManager.appendChild(containerClone, aClone); List childSet2 = mFabricUIManager.createChildSet(rootTag); diff --git a/ReactCommon/fabric/core/componentdescriptor/ComponentDescriptor.h b/ReactCommon/fabric/core/componentdescriptor/ComponentDescriptor.h index 1718860b43430e..53312ed2fb9551 100644 --- a/ReactCommon/fabric/core/componentdescriptor/ComponentDescriptor.h +++ b/ReactCommon/fabric/core/componentdescriptor/ComponentDescriptor.h @@ -85,7 +85,7 @@ class ComponentDescriptor { * shadow nodes. */ virtual SharedEventEmitter createEventEmitter( - const InstanceHandle &instanceHandle, + const EventTarget &eventTarget, const Tag &tag ) const = 0; }; diff --git a/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h b/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h index 2f1f7fcd9e033e..82801a7753f346 100644 --- a/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h +++ b/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h @@ -113,10 +113,10 @@ class ConcreteComponentDescriptor: public ComponentDescriptor { }; virtual SharedEventEmitter createEventEmitter( - const InstanceHandle &instanceHandle, + const EventTarget &eventTarget, const Tag &tag ) const override { - return std::make_shared(instanceHandle, tag, eventDispatcher_); + return std::make_shared(eventTarget, tag, eventDispatcher_); } protected: diff --git a/ReactCommon/fabric/core/events/EventDispatcher.h b/ReactCommon/fabric/core/events/EventDispatcher.h index 0f61a010eb1562..11ba3580850e11 100644 --- a/ReactCommon/fabric/core/events/EventDispatcher.h +++ b/ReactCommon/fabric/core/events/EventDispatcher.h @@ -28,8 +28,6 @@ class EventDispatcher { public: - virtual EventTarget createEventTarget(const InstanceHandle &instanceHandle) const = 0; - /* * Dispatches "raw" event using some event-delivery infrastructure. */ diff --git a/ReactCommon/fabric/core/events/EventEmitter.cpp b/ReactCommon/fabric/core/events/EventEmitter.cpp index 9c61be13f0a00a..2e99199eea7035 100644 --- a/ReactCommon/fabric/core/events/EventEmitter.cpp +++ b/ReactCommon/fabric/core/events/EventEmitter.cpp @@ -12,13 +12,10 @@ namespace facebook { namespace react { -EventEmitter::EventEmitter(const InstanceHandle &instanceHandle, const Tag &tag, const SharedEventDispatcher &eventDispatcher): - instanceHandle_(instanceHandle), +EventEmitter::EventEmitter(const EventTarget &eventTarget, const Tag &tag, const SharedEventDispatcher &eventDispatcher): + eventTarget_(eventTarget), tag_(tag), eventDispatcher_(eventDispatcher) { - if (eventDispatcher) { - eventTarget_ = createEventTarget(); - } } EventEmitter::~EventEmitter() { @@ -49,11 +46,5 @@ void EventEmitter::dispatchEvent( eventDispatcher->dispatchEvent(eventTarget_, type, extendedPayload, priority); } -EventTarget EventEmitter::createEventTarget() const { - const auto &eventDispatcher = eventDispatcher_.lock(); - assert(eventDispatcher); - return eventDispatcher->createEventTarget(instanceHandle_); -} - } // namespace react } // namespace facebook diff --git a/ReactCommon/fabric/core/events/EventEmitter.h b/ReactCommon/fabric/core/events/EventEmitter.h index d854b00ba1010a..3876be111c095f 100644 --- a/ReactCommon/fabric/core/events/EventEmitter.h +++ b/ReactCommon/fabric/core/events/EventEmitter.h @@ -31,7 +31,7 @@ using SharedEventEmitter = std::shared_ptr; class EventEmitter { public: - EventEmitter(const InstanceHandle &instanceHandle, const Tag &tag, const SharedEventDispatcher &eventDispatcher); + EventEmitter(const EventTarget &eventTarget, const Tag &tag, const SharedEventDispatcher &eventDispatcher); virtual ~EventEmitter(); protected: @@ -48,12 +48,9 @@ class EventEmitter { private: - EventTarget createEventTarget() const; - - InstanceHandle instanceHandle_; + mutable EventTarget eventTarget_ {nullptr}; Tag tag_; std::weak_ptr eventDispatcher_; - mutable EventTarget eventTarget_ {nullptr}; }; } // namespace react diff --git a/ReactCommon/fabric/uimanager/FabricUIManager.cpp b/ReactCommon/fabric/uimanager/FabricUIManager.cpp index 06bbeb94449308..463c537bcdbf84 100644 --- a/ReactCommon/fabric/uimanager/FabricUIManager.cpp +++ b/ReactCommon/fabric/uimanager/FabricUIManager.cpp @@ -97,12 +97,12 @@ UIManagerDelegate *FabricUIManager::getDelegate() { return delegate_; } -void FabricUIManager::setCreateEventTargetFunction(std::function createEventTargetFunction) { - createEventTargetFunction_ = createEventTargetFunction; +void FabricUIManager::setDispatchEventToEmptyTargetFunction(std::function dispatchEventFunction) { + dispatchEventToEmptyTargetFunction_ = dispatchEventFunction; } -void FabricUIManager::setDispatchEventFunction(std::function dispatchEventFunction) { - dispatchEventFunction_ = dispatchEventFunction; +void FabricUIManager::setDispatchEventToTargetFunction(std::function dispatchEventFunction) { + dispatchEventToTargetFunction_ = dispatchEventFunction; } void FabricUIManager::setReleaseEventHandlerFunction(std::function releaseEventHandlerFunction) { @@ -113,12 +113,16 @@ void FabricUIManager::setReleaseEventTargetFunction(std::function(type), + const_cast(payload) + ); } -void FabricUIManager::dispatchEvent(const EventTarget &eventTarget, const std::string &type, const folly::dynamic &payload) const { - dispatchEventFunction_( +void FabricUIManager::dispatchEventToTarget(const EventTarget &eventTarget, const std::string &type, const folly::dynamic &payload) const { + dispatchEventToTargetFunction_( eventHandler_, eventTarget, const_cast(type), @@ -130,7 +134,7 @@ void FabricUIManager::releaseEventTarget(const EventTarget &eventTarget) const { releaseEventTargetFunction_(eventTarget); } -SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int rootTag, folly::dynamic props, InstanceHandle instanceHandle) { +SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int rootTag, folly::dynamic props, EventTarget eventTarget) { isLoggingEnabled && LOG(INFO) << "FabricUIManager::createNode(tag: " << tag << ", name: " << viewName << ", rootTag: " << rootTag << ", props: " << props << ")"; ComponentName componentName = componentNameByReactViewName(viewName); @@ -141,7 +145,7 @@ SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int componentDescriptor->createShadowNode( tag, rootTag, - componentDescriptor->createEventEmitter(instanceHandle, tag), + componentDescriptor->createEventEmitter(eventTarget, tag), componentDescriptor->cloneProps(nullptr, rawProps) ); @@ -154,7 +158,7 @@ SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int return shadowNode; } -SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode, InstanceHandle instanceHandle) { +SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode) { isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNode(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")"; const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode]; @@ -162,7 +166,7 @@ SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode, componentDescriptor->cloneShadowNode( shadowNode, nullptr, - componentDescriptor->createEventEmitter(instanceHandle, shadowNode->getTag()), + componentDescriptor->createEventEmitter(nullptr /*TODO(shergin)*/, shadowNode->getTag()), nullptr ); @@ -170,7 +174,7 @@ SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode, return clonedShadowNode; } -SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNode &shadowNode, InstanceHandle instanceHandle) { +SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNode &shadowNode) { isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildren(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")"; // Assuming semantic: Cloning with same props but empty children. const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode]; @@ -179,7 +183,7 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNod componentDescriptor->cloneShadowNode( shadowNode, nullptr, - componentDescriptor->createEventEmitter(instanceHandle, shadowNode->getTag()), + componentDescriptor->createEventEmitter(nullptr /*TODO(shergin)*/, shadowNode->getTag()), ShadowNode::emptySharedShadowNodeSharedList() ); @@ -187,7 +191,7 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNod return clonedShadowNode; } -SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode &shadowNode, folly::dynamic props, InstanceHandle instanceHandle) { +SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode &shadowNode, folly::dynamic props) { isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNodeWithNewProps(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", props: " << props << ")"; // Assuming semantic: Cloning with same children and specified props. const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode]; @@ -197,7 +201,7 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode & componentDescriptor->cloneShadowNode( shadowNode, componentDescriptor->cloneProps(shadowNode->getProps(), rawProps), - componentDescriptor->createEventEmitter(instanceHandle, shadowNode->getTag()), + componentDescriptor->createEventEmitter(nullptr /*TODO(shergin)*/, shadowNode->getTag()), nullptr ); @@ -205,7 +209,7 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode & return clonedShadowNode; } -SharedShadowNode FabricUIManager::cloneNodeWithNewChildrenAndProps(const SharedShadowNode &shadowNode, folly::dynamic props, InstanceHandle instanceHandle) { +SharedShadowNode FabricUIManager::cloneNodeWithNewChildrenAndProps(const SharedShadowNode &shadowNode, folly::dynamic props) { isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildrenAndProps(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", props: " << props << ")"; // Assuming semantic: Cloning with empty children and specified props. const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode]; @@ -215,7 +219,7 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewChildrenAndProps(const SharedS componentDescriptor->cloneShadowNode( shadowNode, componentDescriptor->cloneProps(shadowNode->getProps(), rawProps), - componentDescriptor->createEventEmitter(instanceHandle, shadowNode->getTag()), + componentDescriptor->createEventEmitter(nullptr /*TODO(shergin)*/, shadowNode->getTag()), ShadowNode::emptySharedShadowNodeSharedList() ); diff --git a/ReactCommon/fabric/uimanager/FabricUIManager.h b/ReactCommon/fabric/uimanager/FabricUIManager.h index 3f66913332f3d1..e33501e3197a6e 100644 --- a/ReactCommon/fabric/uimanager/FabricUIManager.h +++ b/ReactCommon/fabric/uimanager/FabricUIManager.h @@ -18,8 +18,8 @@ namespace facebook { namespace react { -using CreateEventTargetFunction = EventTarget (InstanceHandle instanceHandle); -using DispatchEventFunction = void (EventHandler eventHandler, EventTarget eventTarget, std::string type, folly::dynamic payload); +using DispatchEventToEmptyTargetFunction = void (EventHandler eventHandler, std::string type, folly::dynamic payload); +using DispatchEventToTargetFunction = void (EventHandler eventHandler, EventTarget eventTarget, std::string type, folly::dynamic payload); using ReleaseEventHandlerFunction = void (EventHandler eventHandler); using ReleaseEventTargetFunction = void (EventTarget eventTarget); @@ -44,24 +44,24 @@ class FabricUIManager { /* * Registers callback functions. */ - void setCreateEventTargetFunction(std::function createEventTargetFunction); - void setDispatchEventFunction(std::function dispatchEventFunction); + void setDispatchEventToEmptyTargetFunction(std::function dispatchEventFunction); + void setDispatchEventToTargetFunction(std::function dispatchEventFunction); void setReleaseEventHandlerFunction(std::function releaseEventHandlerFunction); void setReleaseEventTargetFunction(std::function releaseEventTargetFunction); #pragma mark - Native-facing Interface - EventTarget createEventTarget(const InstanceHandle &instanceHandle) const; - void dispatchEvent(const EventTarget &eventTarget, const std::string &type, const folly::dynamic &payload) const; + void dispatchEventToEmptyTarget(const std::string &type, const folly::dynamic &payload) const; + void dispatchEventToTarget(const EventTarget &eventTarget, const std::string &type, const folly::dynamic &payload) const; void releaseEventTarget(const EventTarget &eventTarget) const; #pragma mark - JavaScript/React-facing Interface - SharedShadowNode createNode(Tag reactTag, std::string viewName, Tag rootTag, folly::dynamic props, InstanceHandle instanceHandle); - SharedShadowNode cloneNode(const SharedShadowNode &node, InstanceHandle instanceHandle); - SharedShadowNode cloneNodeWithNewChildren(const SharedShadowNode &node, InstanceHandle instanceHandle); - SharedShadowNode cloneNodeWithNewProps(const SharedShadowNode &node, folly::dynamic props, InstanceHandle instanceHandle); - SharedShadowNode cloneNodeWithNewChildrenAndProps(const SharedShadowNode &node, folly::dynamic newProps, InstanceHandle instanceHandle); + SharedShadowNode createNode(Tag reactTag, std::string viewName, Tag rootTag, folly::dynamic props, EventTarget eventTarget); + SharedShadowNode cloneNode(const SharedShadowNode &node); + SharedShadowNode cloneNodeWithNewChildren(const SharedShadowNode &node); + SharedShadowNode cloneNodeWithNewProps(const SharedShadowNode &node, folly::dynamic props); + SharedShadowNode cloneNodeWithNewChildrenAndProps(const SharedShadowNode &node, folly::dynamic newProps); void appendChild(const SharedShadowNode &parentNode, const SharedShadowNode &childNode); SharedShadowNodeUnsharedList createChildSet(Tag rootTag); void appendChildToSet(const SharedShadowNodeUnsharedList &childSet, const SharedShadowNode &childNode); @@ -73,8 +73,8 @@ class FabricUIManager { SharedComponentDescriptorRegistry componentDescriptorRegistry_; UIManagerDelegate *delegate_; EventHandler eventHandler_; - std::function createEventTargetFunction_; - std::function dispatchEventFunction_; + std::function dispatchEventToEmptyTargetFunction_; + std::function dispatchEventToTargetFunction_; std::function releaseEventHandlerFunction_; std::function releaseEventTargetFunction_; }; diff --git a/ReactCommon/fabric/uimanager/SchedulerEventDispatcher.cpp b/ReactCommon/fabric/uimanager/SchedulerEventDispatcher.cpp index 77d6942535fbab..f261499326ba83 100644 --- a/ReactCommon/fabric/uimanager/SchedulerEventDispatcher.cpp +++ b/ReactCommon/fabric/uimanager/SchedulerEventDispatcher.cpp @@ -26,11 +26,6 @@ void SchedulerEventDispatcher::setUIManager(std::shared_ptrcreateEventTarget(instanceHandle); -} - void SchedulerEventDispatcher::dispatchEvent( const EventTarget &eventTarget, const std::string &type, @@ -41,14 +36,15 @@ void SchedulerEventDispatcher::dispatchEvent( return; } // TODO: Schedule the event based on priority. - uiManager_->dispatchEvent(eventTarget, normalizeEventType(type), payload); + uiManager_->dispatchEventToTarget(eventTarget, normalizeEventType(type), payload); } void SchedulerEventDispatcher::releaseEventTarget(const EventTarget &eventTarget) const { if (!uiManager_) { return; } - uiManager_->releaseEventTarget(eventTarget); + // TODO(shergin): This needs to move to the destructor of EventEmitter. For now we'll leak. + // uiManager_->releaseEventTarget(eventTarget); } } // namespace react diff --git a/ReactCommon/fabric/uimanager/SchedulerEventDispatcher.h b/ReactCommon/fabric/uimanager/SchedulerEventDispatcher.h index 847946b57b014c..e89735ad9981ce 100644 --- a/ReactCommon/fabric/uimanager/SchedulerEventDispatcher.h +++ b/ReactCommon/fabric/uimanager/SchedulerEventDispatcher.h @@ -31,8 +31,6 @@ class SchedulerEventDispatcher final: #pragma mark - EventDispatcher - EventTarget createEventTarget(const InstanceHandle &instanceHandle) const override; - void dispatchEvent( const EventTarget &eventTarget, const std::string &type, From 2166d2bb797d2c5fcbff6d3b96f6530989c2e96f Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Fri, 29 Jun 2018 19:57:43 -0700 Subject: [PATCH 10/65] Fabric: Trivial implementation of prelumiary view allocation on iOS Summary: @public We have this feature in the current version of RN, so it would be nice to support that in Fabric as well. This should save us tens of ms of views creation during mounting. And that's quite easy to do! Reviewed By: fkgozali Differential Revision: D8701992 fbshipit-source-id: 4e3049df009ffd65bb43043de388e81795e5e559 --- React/Fabric/Mounting/RCTComponentViewRegistry.h | 5 +++++ React/Fabric/Mounting/RCTComponentViewRegistry.mm | 9 ++++++++- React/Fabric/Mounting/RCTMountingManager.h | 8 ++++++++ React/Fabric/Mounting/RCTMountingManager.mm | 7 +++++++ React/Fabric/RCTScheduler.h | 2 +- React/Fabric/RCTSurfacePresenter.mm | 7 +++++-- 6 files changed, 34 insertions(+), 4 deletions(-) diff --git a/React/Fabric/Mounting/RCTComponentViewRegistry.h b/React/Fabric/Mounting/RCTComponentViewRegistry.h index 1e747b124da12c..a563270999cefa 100644 --- a/React/Fabric/Mounting/RCTComponentViewRegistry.h +++ b/React/Fabric/Mounting/RCTComponentViewRegistry.h @@ -43,6 +43,11 @@ NS_ASSUME_NONNULL_BEGIN */ - (ReactTag)tagByComponentView:(UIView *)componentView; +/** + * Creates a component view with a given type and puts it to the recycle pool. + */ +- (void)preliminaryCreateComponentViewWithName:(NSString *)componentName; + @end NS_ASSUME_NONNULL_END diff --git a/React/Fabric/Mounting/RCTComponentViewRegistry.mm b/React/Fabric/Mounting/RCTComponentViewRegistry.mm index 81816f1ea30b93..6edbeb75d59b46 100644 --- a/React/Fabric/Mounting/RCTComponentViewRegistry.mm +++ b/React/Fabric/Mounting/RCTComponentViewRegistry.mm @@ -64,7 +64,7 @@ + (void)unregisterView:(UIView *)view #endif -const NSInteger RCTComponentViewRegistryRecyclePoolMaxSize = 256; +const NSInteger RCTComponentViewRegistryRecyclePoolMaxSize = 1024; @implementation RCTComponentViewRegistry { NSMapTable *> *_registry; @@ -121,6 +121,13 @@ - (void)enqueueComponentViewWithName:(NSString *)componentName [self _enqueueComponentViewWithName:componentName componentView:componentView]; } +- (void)preliminaryCreateComponentViewWithName:(NSString *)componentName +{ + RCTAssertMainQueue(); + [self _enqueueComponentViewWithName:componentName + componentView:[self _createComponentViewWithName:componentName]]; +} + - (UIView *)componentViewByTag:(ReactTag)tag { RCTAssertMainQueue(); diff --git a/React/Fabric/Mounting/RCTMountingManager.h b/React/Fabric/Mounting/RCTMountingManager.h index bf66ac7f5757a6..89a90ccb7160a4 100644 --- a/React/Fabric/Mounting/RCTMountingManager.h +++ b/React/Fabric/Mounting/RCTMountingManager.h @@ -26,10 +26,18 @@ NS_ASSUME_NONNULL_BEGIN /** * Transfroms mutation insturctions to mount items and execute them. * The order of mutation tnstructions matters. + * Can be called from any thread. */ - (void)mutateComponentViewTreeWithMutationInstructions:(facebook::react::TreeMutationInstructionList)instructions rootTag:(ReactTag)rootTag; +/** + * Suggests preliminary creation of a component view of given type. + * The receiver is free to ignore the request. + * Can be called from any thread. + */ +- (void)preliminaryCreateComponentViewWithName:(NSString *)componentName; + @end NS_ASSUME_NONNULL_END diff --git a/React/Fabric/Mounting/RCTMountingManager.mm b/React/Fabric/Mounting/RCTMountingManager.mm index 5aa0fa5012399b..90366db3490295 100644 --- a/React/Fabric/Mounting/RCTMountingManager.mm +++ b/React/Fabric/Mounting/RCTMountingManager.mm @@ -181,4 +181,11 @@ - (void)_performMountItems:(NSArray *)mountItems [self.delegate mountingManager:self didMountComponentsWithRootTag:rootTag]; } +- (void)preliminaryCreateComponentViewWithName:(NSString *)componentName +{ + RCTExecuteOnMainQueue(^{ + [self->_componentViewRegistry preliminaryCreateComponentViewWithName:componentName]; + }); +} + @end diff --git a/React/Fabric/RCTScheduler.h b/React/Fabric/RCTScheduler.h index e6a730b788caec..6814046871d7e7 100644 --- a/React/Fabric/RCTScheduler.h +++ b/React/Fabric/RCTScheduler.h @@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN @class RCTMountingManager; /** - * Exacly same semantic as `facebook::react::SchedulerDelegate`. + * Exactly same semantic as `facebook::react::SchedulerDelegate`. */ @protocol RCTSchedulerDelegate diff --git a/React/Fabric/RCTSurfacePresenter.mm b/React/Fabric/RCTSurfacePresenter.mm index 99703c2389aca7..e3223804d2c05c 100644 --- a/React/Fabric/RCTSurfacePresenter.mm +++ b/React/Fabric/RCTSurfacePresenter.mm @@ -67,7 +67,10 @@ - (void)dealloc [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (void)schedulerDidComputeMutationInstructions:(facebook::react::TreeMutationInstructionList)instructions rootTag:(ReactTag)rootTag +#pragma mark - RCTSchedulerDelegate + +- (void)schedulerDidComputeMutationInstructions:(facebook::react::TreeMutationInstructionList)instructions + rootTag:(ReactTag)rootTag { [_mountingManager mutateComponentViewTreeWithMutationInstructions:instructions rootTag:rootTag]; @@ -75,7 +78,7 @@ - (void)schedulerDidComputeMutationInstructions:(facebook::react::TreeMutationIn - (void)schedulerDidRequestPreliminaryViewAllocationWithComponentName:(NSString *)componentName { - // TODO: To be implemeted. + [_mountingManager preliminaryCreateComponentViewWithName:componentName]; } #pragma mark - Internal Surface-dedicated Interface From 6dcadca71282a9a4cbe58e2ea50c0ba0e946a814 Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Sun, 1 Jul 2018 16:16:52 -0700 Subject: [PATCH 11/65] Add back ImageEditingExample example (#19972) Summary: add back missing file. pass all current ci. none [GENERAL] [INTERNAL] [RNTester] - Add back ImageEditingExample example. Closes https://github.com/facebook/react-native/pull/19972 Differential Revision: D8711888 Pulled By: TheSavior fbshipit-source-id: 14070bfbf747f7f59c4039981a9bc83c1c10862b --- RNTester/js/ImageEditingExample.js | 303 ++++++++++++++++++++++++++++- 1 file changed, 302 insertions(+), 1 deletion(-) diff --git a/RNTester/js/ImageEditingExample.js b/RNTester/js/ImageEditingExample.js index 830e1276ef6ec8..0bc25ce26d7743 100644 --- a/RNTester/js/ImageEditingExample.js +++ b/RNTester/js/ImageEditingExample.js @@ -5,5 +5,306 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ +'use strict'; + +var React = require('react'); +var ReactNative = require('react-native'); +var { + CameraRoll, + Image, + ImageEditor, + Platform, + ScrollView, + StyleSheet, + Text, + TouchableHighlight, + View, +} = ReactNative; + +var PAGE_SIZE = 20; + +type ImageOffset = { + x: number, + y: number, +}; + +type ImageSize = { + width: number, + height: number, +}; + +type ImageCropData = { + offset: ImageOffset, + size: ImageSize, + displaySize?: ?ImageSize, + resizeMode?: ?any, +}; + +class SquareImageCropper extends React.Component<$FlowFixMeProps, $FlowFixMeState> { + state: any; + _isMounted: boolean; + _transformData: ImageCropData; + + constructor(props) { + super(props); + this._isMounted = true; + this.state = { + randomPhoto: null, + measuredSize: null, + croppedImageURI: null, + cropError: null, + }; + this._fetchRandomPhoto(); + } + + async _fetchRandomPhoto() { + try { + const data = await CameraRoll.getPhotos({first: PAGE_SIZE}); + if (!this._isMounted) { + return; + } + var edges = data.edges; + var edge = edges[Math.floor(Math.random() * edges.length)]; + var randomPhoto = edge && edge.node && edge.node.image; + if (randomPhoto) { + this.setState({randomPhoto}); + } + } catch (error) { + console.warn("Can't get a photo from camera roll", error); + } + } + + componentWillUnmount() { + this._isMounted = false; + } + + render() { + if (!this.state.measuredSize) { + return ( + { + var measuredWidth = event.nativeEvent.layout.width; + if (!measuredWidth) { + return; + } + this.setState({ + measuredSize: {width: measuredWidth, height: measuredWidth}, + }); + }} + /> + ); + } + + if (!this.state.croppedImageURI) { + return this._renderImageCropper(); + } + return this._renderCroppedImage(); + } + + _renderImageCropper() { + if (!this.state.randomPhoto) { + return ; + } + var error = null; + if (this.state.cropError) { + error = {this.state.cropError.message}; + } + return ( + + Drag the image within the square to crop: + (this._transformData = data)} + /> + + + Crop + + + {error} + + ); + } + + _renderCroppedImage() { + return ( + + Here is the cropped image: + + + + Try again + + + + ); + } + + _crop() { + ImageEditor.cropImage( + this.state.randomPhoto.uri, + this._transformData, + croppedImageURI => this.setState({croppedImageURI}), + cropError => this.setState({cropError}), + ); + } + + _reset() { + this.setState({ + randomPhoto: null, + croppedImageURI: null, + cropError: null, + }); + this._fetchRandomPhoto(); + } +} + +class ImageCropper extends React.Component<$FlowFixMeProps, $FlowFixMeState> { + _contentOffset: ImageOffset; + _maximumZoomScale: number; + _minimumZoomScale: number; + _scaledImageSize: ImageSize; + _horizontal: boolean; + + componentWillMount() { + // Scale an image to the minimum size that is large enough to completely + // fill the crop box. + var widthRatio = this.props.image.width / this.props.size.width; + var heightRatio = this.props.image.height / this.props.size.height; + this._horizontal = widthRatio > heightRatio; + if (this._horizontal) { + this._scaledImageSize = { + width: this.props.image.width / heightRatio, + height: this.props.size.height, + }; + } else { + this._scaledImageSize = { + width: this.props.size.width, + height: this.props.image.height / widthRatio, + }; + if (Platform.OS === 'android') { + // hack to work around Android ScrollView a) not supporting zoom, and + // b) not supporting vertical scrolling when nested inside another + // vertical ScrollView (which it is, when displayed inside UIExplorer) + this._scaledImageSize.width *= 2; + this._scaledImageSize.height *= 2; + this._horizontal = true; + } + } + this._contentOffset = { + x: (this._scaledImageSize.width - this.props.size.width) / 2, + y: (this._scaledImageSize.height - this.props.size.height) / 2, + }; + this._maximumZoomScale = Math.min( + this.props.image.width / this._scaledImageSize.width, + this.props.image.height / this._scaledImageSize.height, + ); + this._minimumZoomScale = Math.max( + this.props.size.width / this._scaledImageSize.width, + this.props.size.height / this._scaledImageSize.height, + ); + this._updateTransformData( + this._contentOffset, + this._scaledImageSize, + this.props.size, + ); + } + + _onScroll(event) { + this._updateTransformData( + event.nativeEvent.contentOffset, + event.nativeEvent.contentSize, + event.nativeEvent.layoutMeasurement, + ); + } + + _updateTransformData(offset, scaledImageSize, croppedImageSize) { + var offsetRatioX = offset.x / scaledImageSize.width; + var offsetRatioY = offset.y / scaledImageSize.height; + var sizeRatioX = croppedImageSize.width / scaledImageSize.width; + var sizeRatioY = croppedImageSize.height / scaledImageSize.height; + + var cropData: ImageCropData = { + offset: { + x: this.props.image.width * offsetRatioX, + y: this.props.image.height * offsetRatioY, + }, + size: { + width: this.props.image.width * sizeRatioX, + height: this.props.image.height * sizeRatioY, + }, + }; + this.props.onTransformDataChange && + this.props.onTransformDataChange(cropData); + } + + render() { + return ( + + + + ); + } +} + +exports.framework = 'React'; +exports.title = 'ImageEditor'; +exports.description = 'Cropping and scaling with ImageEditor'; +exports.examples = [ + { + title: 'Image Cropping', + render() { + return ; + }, + }, +]; + +var styles = StyleSheet.create({ + container: { + flex: 1, + alignSelf: 'stretch', + }, + imageCropper: { + alignSelf: 'center', + marginTop: 12, + }, + cropButtonTouchable: { + alignSelf: 'center', + marginTop: 12, + }, + cropButton: { + padding: 12, + backgroundColor: 'blue', + borderRadius: 4, + }, + cropButtonLabel: { + color: 'white', + fontSize: 16, + fontWeight: '500', + }, +}); From 6a16bec882cba809bdf9027367b76f6543b6617d Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Sun, 1 Jul 2018 16:30:40 -0700 Subject: [PATCH 12/65] RN: Fix Drawing Rect for ReactScrollView Summary: Fixes `ReactScrollView` so that it respects the drawing rect (i.e. the bounding box of the element). In JavaScript, this is the backing view for `ScrollView` (vertical) on Android. Reviewed By: fadinghorse Differential Revision: D8710256 fbshipit-source-id: f3bd96e39b8569cfcb21e486944b70fdb57c12b6 --- .../src/main/java/com/facebook/react/uimanager/ViewProps.java | 1 + .../java/com/facebook/react/views/scroll/ReactScrollView.java | 3 +++ 2 files changed, 4 insertions(+) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java index 29ed6e96c0e0d0..0a353a6b0f242a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java @@ -102,6 +102,7 @@ public class ViewProps { public static final String OVERFLOW = "overflow"; public static final String HIDDEN = "hidden"; + public static final String SCROLL = "scroll"; public static final String VISIBLE = "visible"; public static final String ALLOW_FONT_SCALING = "allowFontScaling"; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index acf3458ef5f023..57b401cd6fbf5c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -47,6 +47,7 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou private final OnScrollDispatchHelper mOnScrollDispatchHelper = new OnScrollDispatchHelper(); private final @Nullable OverScroller mScroller; private final VelocityHelper mVelocityHelper = new VelocityHelper(); + private final Rect mRect = new Rect(); // for reuse to avoid allocation private @Nullable Rect mClippingRect; private boolean mDoneFlinging; @@ -351,6 +352,8 @@ public void draw(Canvas canvas) { mEndBackground.draw(canvas); } } + getDrawingRect(mRect); + canvas.clipRect(mRect); super.draw(canvas); } From 5786db3a26c2d28863901a354602290aa4af7f77 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sun, 1 Jul 2018 21:22:21 -0700 Subject: [PATCH 13/65] Fabric: Making `fabric/graphics` compilable on Android Summary: @public This compiles but this does not work. To make it actually work we have to implement all missing functions in `Color.cpp` and co. Reviewed By: fkgozali Differential Revision: D8655537 fbshipit-source-id: 564fb7131445af81cf05407239dc6ba870cf6b83 --- ReactCommon/fabric/graphics/BUCK | 40 ++++++++++++++++--- ReactCommon/fabric/graphics/ColorComponents.h | 21 ++++++++++ ReactCommon/fabric/graphics/Geometry.h | 16 +------- .../graphics/platform/android/Color.cpp | 24 +++++++++++ .../fabric/graphics/platform/android/Color.h | 24 +++++++++++ .../fabric/graphics/platform/android/Float.h | 28 +++++++++++++ .../graphics/{ => platform/ios}/Color.cpp | 3 -- .../graphics/{ => platform/ios}/Color.h | 12 ++---- .../fabric/graphics/platform/ios/Float.h | 29 ++++++++++++++ 9 files changed, 166 insertions(+), 31 deletions(-) create mode 100644 ReactCommon/fabric/graphics/ColorComponents.h create mode 100644 ReactCommon/fabric/graphics/platform/android/Color.cpp create mode 100644 ReactCommon/fabric/graphics/platform/android/Color.h create mode 100644 ReactCommon/fabric/graphics/platform/android/Float.h rename ReactCommon/fabric/graphics/{ => platform/ios}/Color.cpp (91%) rename ReactCommon/fabric/graphics/{ => platform/ios}/Color.h (77%) create mode 100644 ReactCommon/fabric/graphics/platform/ios/Float.h diff --git a/ReactCommon/fabric/graphics/BUCK b/ReactCommon/fabric/graphics/BUCK index e0b337da1cd7d6..78061adc618bd1 100644 --- a/ReactCommon/fabric/graphics/BUCK +++ b/ReactCommon/fabric/graphics/BUCK @@ -12,12 +12,15 @@ if not IS_OSS_BUILD: rn_xplat_cxx_library( name = "graphics", srcs = glob( - ["**/*.cpp"], - exclude = glob(["tests/**/*.cpp"]), + [ + "*.cpp", + ], ), - headers = glob( - ["**/*.h"], - exclude = glob(["tests/**/*.h"]), + headers = subdir_glob( + [ + ("", "*.h"), + ], + prefix = "", ), header_namespace = "", exported_headers = subdir_glob( @@ -32,6 +35,17 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_exported_headers = subdir_glob( + [ + ("platform/android", "**/*.h"), + ], + prefix = "fabric/graphics", + ), + fbandroid_srcs = glob( + [ + "platform/android/**/*.cpp", + ], + ), fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_preprocessor_flags = get_debug_preprocessor_flags() + get_apple_inspector_flags(), fbobjc_tests = [ @@ -43,6 +57,22 @@ rn_xplat_cxx_library( "$SDKROOT/System/Library/Frameworks/Foundation.framework", "$SDKROOT/System/Library/Frameworks/UIKit.framework", ], + ios_deps = [ + "xplat//js:RCTImage", + "xplat//js/react-native-github:RCTCxxBridge", + ], + ios_exported_headers = subdir_glob( + [ + ("platform/ios", "*.h"), + ], + prefix = "fabric/graphics", + ), + ios_srcs = glob( + [ + "platform/ios/**/*.cpp", + "platform/ios/**/*.mm", + ], + ), macosx_tests_override = [], platforms = (ANDROID, APPLE), preprocessor_flags = [ diff --git a/ReactCommon/fabric/graphics/ColorComponents.h b/ReactCommon/fabric/graphics/ColorComponents.h new file mode 100644 index 00000000000000..489e1888668f2e --- /dev/null +++ b/ReactCommon/fabric/graphics/ColorComponents.h @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +namespace facebook { +namespace react { + +struct ColorComponents { + float red {0}; + float green {0}; + float blue {0}; + float alpha {0}; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/graphics/Geometry.h b/ReactCommon/fabric/graphics/Geometry.h index 6e97ae851af2fb..3db79088609d80 100644 --- a/ReactCommon/fabric/graphics/Geometry.h +++ b/ReactCommon/fabric/graphics/Geometry.h @@ -8,25 +8,11 @@ #include #include -#include +#include namespace facebook { namespace react { -/* - * Exact type of float numbers which ideally should match a type behing - * platform- and chip-architecture-specific float type. - */ -using Float = CGFloat; - -/* - * Large positive number signifies that the `Float` values is `undefined`. - */ -const Float kFloatUndefined = CGFLOAT_MAX; - -const Float kFloatMax = CGFLOAT_MAX; -const Float kFloatMin = CGFLOAT_MIN; - /* * Point */ diff --git a/ReactCommon/fabric/graphics/platform/android/Color.cpp b/ReactCommon/fabric/graphics/platform/android/Color.cpp new file mode 100644 index 00000000000000..3511eeb3be86eb --- /dev/null +++ b/ReactCommon/fabric/graphics/platform/android/Color.cpp @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "Color.h" + +namespace facebook { +namespace react { + +SharedColor colorFromComponents(ColorComponents components) { + // Not implemented. + return {}; +} + +ColorComponents colorComponentsFromColor(SharedColor color) { + // Not implemented. + return {}; +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/graphics/platform/android/Color.h b/ReactCommon/fabric/graphics/platform/android/Color.h new file mode 100644 index 00000000000000..761af1d2de05fa --- /dev/null +++ b/ReactCommon/fabric/graphics/platform/android/Color.h @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#include + +namespace facebook { +namespace react { + +using Color = float; +using SharedColor = std::shared_ptr; + +SharedColor colorFromComponents(ColorComponents components); +ColorComponents colorComponentsFromColor(SharedColor color); + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/graphics/platform/android/Float.h b/ReactCommon/fabric/graphics/platform/android/Float.h new file mode 100644 index 00000000000000..8351a892322377 --- /dev/null +++ b/ReactCommon/fabric/graphics/platform/android/Float.h @@ -0,0 +1,28 @@ +// Copyright (c) 2004-present, Facebook, Inc. + +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include + +namespace facebook { +namespace react { + +/* + * Exact type of float numbers which ideally should match a type behing + * platform- and chip-architecture-specific float type. + */ +using Float = float; + +/* + * Large positive number signifies that the `Float` values is `undefined`. + */ +const Float kFloatUndefined = std::numeric_limits::max(); + +const Float kFloatMax = std::numeric_limits::max(); +const Float kFloatMin = std::numeric_limits::min(); + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/graphics/Color.cpp b/ReactCommon/fabric/graphics/platform/ios/Color.cpp similarity index 91% rename from ReactCommon/fabric/graphics/Color.cpp rename to ReactCommon/fabric/graphics/platform/ios/Color.cpp index 151e2923a403ed..db03a0f4af2936 100644 --- a/ReactCommon/fabric/graphics/Color.cpp +++ b/ReactCommon/fabric/graphics/platform/ios/Color.cpp @@ -6,9 +6,6 @@ */ #include "Color.h" -#include -#include -#include namespace facebook { namespace react { diff --git a/ReactCommon/fabric/graphics/Color.h b/ReactCommon/fabric/graphics/platform/ios/Color.h similarity index 77% rename from ReactCommon/fabric/graphics/Color.h rename to ReactCommon/fabric/graphics/platform/ios/Color.h index f7622d213bae40..019663e734cc2a 100644 --- a/ReactCommon/fabric/graphics/Color.h +++ b/ReactCommon/fabric/graphics/platform/ios/Color.h @@ -7,22 +7,18 @@ #pragma once -#include #include +#include + +#include + namespace facebook { namespace react { using Color = CGColor; using SharedColor = std::shared_ptr; -struct ColorComponents { - float red {0}; - float green {0}; - float blue {0}; - float alpha {0}; -}; - SharedColor colorFromComponents(ColorComponents components); ColorComponents colorComponentsFromColor(SharedColor color); diff --git a/ReactCommon/fabric/graphics/platform/ios/Float.h b/ReactCommon/fabric/graphics/platform/ios/Float.h new file mode 100644 index 00000000000000..fec03a6846d166 --- /dev/null +++ b/ReactCommon/fabric/graphics/platform/ios/Float.h @@ -0,0 +1,29 @@ +// Copyright (c) 2004-present, Facebook, Inc. + +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include + +namespace facebook { +namespace react { + +/* + * Exact type of float numbers which ideally should match a type behing + * platform- and chip-architecture-specific float type. + */ +using Float = CGFloat; + +/* + * Large positive number signifies that the `Float` values is `undefined`. + */ +const Float kFloatUndefined = std::numeric_limits::max(); + +const Float kFloatMax = std::numeric_limits::max(); +const Float kFloatMin = std::numeric_limits::min(); + +} // namespace react +} // namespace facebook From ee535fafe3edc6026928a5ebbdda78147f8992a0 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sun, 1 Jul 2018 21:22:22 -0700 Subject: [PATCH 14/65] Fabric: Making `fabric/textlayoutmanager` compilable on Android Summary: @public This compiles, but it works only on iOS for now. Reviewed By: mdvacca Differential Revision: D8655540 fbshipit-source-id: 7e9a73fadb317dd62298af6f347344ac4229a8a5 --- ReactCommon/fabric/textlayoutmanager/BUCK | 50 ++++++++++++++--- .../platform/android/TextLayoutManager.cpp | 33 ++++++++++++ .../platform/android/TextLayoutManager.h | 54 +++++++++++++++++++ .../ios}/NSTextStorage+FontScaling.h | 0 .../ios}/NSTextStorage+FontScaling.m | 0 .../ios}/RCTAttributedTextUtils.h | 0 .../ios}/RCTAttributedTextUtils.mm | 0 .../{ => platform/ios}/RCTFontProperties.h | 0 .../{ => platform/ios}/RCTFontUtils.h | 0 .../{ => platform/ios}/RCTFontUtils.mm | 0 .../{ => platform/ios}/RCTTextLayoutManager.h | 0 .../ios}/RCTTextLayoutManager.mm | 0 .../ios}/RCTTextPrimitivesConversions.h | 0 .../{ => platform/ios}/TextLayoutManager.h | 0 .../{ => platform/ios}/TextLayoutManager.mm | 0 15 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 ReactCommon/fabric/textlayoutmanager/platform/android/TextLayoutManager.cpp create mode 100644 ReactCommon/fabric/textlayoutmanager/platform/android/TextLayoutManager.h rename ReactCommon/fabric/textlayoutmanager/{ => platform/ios}/NSTextStorage+FontScaling.h (100%) rename ReactCommon/fabric/textlayoutmanager/{ => platform/ios}/NSTextStorage+FontScaling.m (100%) rename ReactCommon/fabric/textlayoutmanager/{ => platform/ios}/RCTAttributedTextUtils.h (100%) rename ReactCommon/fabric/textlayoutmanager/{ => platform/ios}/RCTAttributedTextUtils.mm (100%) rename ReactCommon/fabric/textlayoutmanager/{ => platform/ios}/RCTFontProperties.h (100%) rename ReactCommon/fabric/textlayoutmanager/{ => platform/ios}/RCTFontUtils.h (100%) rename ReactCommon/fabric/textlayoutmanager/{ => platform/ios}/RCTFontUtils.mm (100%) rename ReactCommon/fabric/textlayoutmanager/{ => platform/ios}/RCTTextLayoutManager.h (100%) rename ReactCommon/fabric/textlayoutmanager/{ => platform/ios}/RCTTextLayoutManager.mm (100%) rename ReactCommon/fabric/textlayoutmanager/{ => platform/ios}/RCTTextPrimitivesConversions.h (100%) rename ReactCommon/fabric/textlayoutmanager/{ => platform/ios}/TextLayoutManager.h (100%) rename ReactCommon/fabric/textlayoutmanager/{ => platform/ios}/TextLayoutManager.mm (100%) diff --git a/ReactCommon/fabric/textlayoutmanager/BUCK b/ReactCommon/fabric/textlayoutmanager/BUCK index 0095affa737f48..3ea41084b11dd5 100644 --- a/ReactCommon/fabric/textlayoutmanager/BUCK +++ b/ReactCommon/fabric/textlayoutmanager/BUCK @@ -13,14 +13,14 @@ rn_xplat_cxx_library( name = "textlayoutmanager", srcs = glob( [ - "**/*.cpp", - "**/*.mm", + "*.cpp", ], - exclude = glob(["tests/**/*.cpp"]), ), - headers = glob( - ["**/*.h"], - exclude = glob(["tests/**/*.h"]), + headers = subdir_glob( + [ + ("", "*.h"), + ], + prefix = "", ), header_namespace = "", exported_headers = subdir_glob( @@ -35,6 +35,24 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_exported_headers = subdir_glob( + [ + ("", "*.h"), + ("platform/android", "*.h"), + ], + prefix = "fabric/textlayoutmanager", + ), + fbandroid_headers = subdir_glob( + [ + ("platform/android", "**/*.h"), + ], + prefix = "", + ), + fbandroid_srcs = glob( + [ + "platform/android/**/*.cpp", + ], + ), fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_preprocessor_flags = get_debug_preprocessor_flags() + get_apple_inspector_flags(), fbobjc_tests = [ @@ -46,6 +64,26 @@ rn_xplat_cxx_library( "$SDKROOT/System/Library/Frameworks/Foundation.framework", "$SDKROOT/System/Library/Frameworks/UIKit.framework", ], + ios_deps = [ + ], + ios_exported_headers = subdir_glob( + [ + ("platform/ios", "*.h"), + ], + prefix = "fabric/textlayoutmanager", + ), + ios_headers = subdir_glob( + [ + ("platform/ios", "**/*.h"), + ], + prefix = "", + ), + ios_srcs = glob( + [ + "platform/ios/**/*.cpp", + "platform/ios/**/*.mm", + ], + ), macosx_tests_override = [], platforms = (ANDROID, APPLE), preprocessor_flags = [ diff --git a/ReactCommon/fabric/textlayoutmanager/platform/android/TextLayoutManager.cpp b/ReactCommon/fabric/textlayoutmanager/platform/android/TextLayoutManager.cpp new file mode 100644 index 00000000000000..fd98bfa6b708df --- /dev/null +++ b/ReactCommon/fabric/textlayoutmanager/platform/android/TextLayoutManager.cpp @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "TextLayoutManager.h" + +namespace facebook { +namespace react { + +TextLayoutManager::TextLayoutManager() { +} + +TextLayoutManager::~TextLayoutManager() { +} + +void *TextLayoutManager::getNativeTextLayoutManager() const { + return self_; +} + +Size TextLayoutManager::measure( + AttributedString attributedString, + ParagraphAttributes paragraphAttributes, + LayoutConstraints layoutConstraints +) const { + // Not implemented. + return {}; +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/textlayoutmanager/platform/android/TextLayoutManager.h b/ReactCommon/fabric/textlayoutmanager/platform/android/TextLayoutManager.h new file mode 100644 index 00000000000000..9da164f30f84ce --- /dev/null +++ b/ReactCommon/fabric/textlayoutmanager/platform/android/TextLayoutManager.h @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#include +#include +#include + +namespace facebook { +namespace react { + +class TextLayoutManager; + +using SharedTextLayoutManager = std::shared_ptr; + +/* + * Cross platform facade for Android-specific TextLayoutManager. + */ +class TextLayoutManager { + +public: + + TextLayoutManager(); + ~TextLayoutManager(); + + /* + * Measures `attributedString` using native text rendering infrastructure. + */ + Size measure( + AttributedString attributedString, + ParagraphAttributes paragraphAttributes, + LayoutConstraints layoutConstraints + ) const; + + /* + * Returns an opaque pointer to platform-specific TextLayoutManager. + * Is used on a native views layer to delegate text rendering to the manager. + */ + void *getNativeTextLayoutManager() const; + +private: + + void *self_; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/textlayoutmanager/NSTextStorage+FontScaling.h b/ReactCommon/fabric/textlayoutmanager/platform/ios/NSTextStorage+FontScaling.h similarity index 100% rename from ReactCommon/fabric/textlayoutmanager/NSTextStorage+FontScaling.h rename to ReactCommon/fabric/textlayoutmanager/platform/ios/NSTextStorage+FontScaling.h diff --git a/ReactCommon/fabric/textlayoutmanager/NSTextStorage+FontScaling.m b/ReactCommon/fabric/textlayoutmanager/platform/ios/NSTextStorage+FontScaling.m similarity index 100% rename from ReactCommon/fabric/textlayoutmanager/NSTextStorage+FontScaling.m rename to ReactCommon/fabric/textlayoutmanager/platform/ios/NSTextStorage+FontScaling.m diff --git a/ReactCommon/fabric/textlayoutmanager/RCTAttributedTextUtils.h b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h similarity index 100% rename from ReactCommon/fabric/textlayoutmanager/RCTAttributedTextUtils.h rename to ReactCommon/fabric/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h diff --git a/ReactCommon/fabric/textlayoutmanager/RCTAttributedTextUtils.mm b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm similarity index 100% rename from ReactCommon/fabric/textlayoutmanager/RCTAttributedTextUtils.mm rename to ReactCommon/fabric/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm diff --git a/ReactCommon/fabric/textlayoutmanager/RCTFontProperties.h b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTFontProperties.h similarity index 100% rename from ReactCommon/fabric/textlayoutmanager/RCTFontProperties.h rename to ReactCommon/fabric/textlayoutmanager/platform/ios/RCTFontProperties.h diff --git a/ReactCommon/fabric/textlayoutmanager/RCTFontUtils.h b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTFontUtils.h similarity index 100% rename from ReactCommon/fabric/textlayoutmanager/RCTFontUtils.h rename to ReactCommon/fabric/textlayoutmanager/platform/ios/RCTFontUtils.h diff --git a/ReactCommon/fabric/textlayoutmanager/RCTFontUtils.mm b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTFontUtils.mm similarity index 100% rename from ReactCommon/fabric/textlayoutmanager/RCTFontUtils.mm rename to ReactCommon/fabric/textlayoutmanager/platform/ios/RCTFontUtils.mm diff --git a/ReactCommon/fabric/textlayoutmanager/RCTTextLayoutManager.h b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTTextLayoutManager.h similarity index 100% rename from ReactCommon/fabric/textlayoutmanager/RCTTextLayoutManager.h rename to ReactCommon/fabric/textlayoutmanager/platform/ios/RCTTextLayoutManager.h diff --git a/ReactCommon/fabric/textlayoutmanager/RCTTextLayoutManager.mm b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTTextLayoutManager.mm similarity index 100% rename from ReactCommon/fabric/textlayoutmanager/RCTTextLayoutManager.mm rename to ReactCommon/fabric/textlayoutmanager/platform/ios/RCTTextLayoutManager.mm diff --git a/ReactCommon/fabric/textlayoutmanager/RCTTextPrimitivesConversions.h b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTTextPrimitivesConversions.h similarity index 100% rename from ReactCommon/fabric/textlayoutmanager/RCTTextPrimitivesConversions.h rename to ReactCommon/fabric/textlayoutmanager/platform/ios/RCTTextPrimitivesConversions.h diff --git a/ReactCommon/fabric/textlayoutmanager/TextLayoutManager.h b/ReactCommon/fabric/textlayoutmanager/platform/ios/TextLayoutManager.h similarity index 100% rename from ReactCommon/fabric/textlayoutmanager/TextLayoutManager.h rename to ReactCommon/fabric/textlayoutmanager/platform/ios/TextLayoutManager.h diff --git a/ReactCommon/fabric/textlayoutmanager/TextLayoutManager.mm b/ReactCommon/fabric/textlayoutmanager/platform/ios/TextLayoutManager.mm similarity index 100% rename from ReactCommon/fabric/textlayoutmanager/TextLayoutManager.mm rename to ReactCommon/fabric/textlayoutmanager/platform/ios/TextLayoutManager.mm From c4a66a89a28152cd4b81e2b0f80ab3aac34d6872 Mon Sep 17 00:00:00 2001 From: Alexey Kureev Date: Mon, 2 Jul 2018 09:33:08 -0700 Subject: [PATCH 15/65] Code clean-ups and createServer migration Summary: Scope of the diff: 1. Middleware `react-native-github/local-cli` and `react-native-internal-cli` uses a very similar set of middlewares (internal cli extends github version), so I decided to move it to a standalone file (middleware manager) in order to remove duplications and increase readability. 2. Types Seems that after Flow upgrade to version 0.68 there were many type issues to resolve, so all of them were auto-mocked. This is fine, but I'd like to see Flow assists me with `Metro.createServer` -> `Metro.runServer` migration. Hence, I decided to resolve flow mocks, related to runServer. 3. `runServer` signature In `react-native-github` repo I cleaned up `runServer` signature by removing `startCallback` and `readyCallback` from the function parameters and moved them to `runServer` instead. 4. Replace `createServer` by `runServer` In `react-native-github` repo, `createServer` has been replaced by `runServer`. __Some of arguments are not mapped__. Note that this diff will partially break argument mapping. This is intentional. @[100000044482482:ives] will fix it with a new config package. Reviewed By: mjesun Differential Revision: D8711717 fbshipit-source-id: a843ab576360ff7242099910d8f25a9cb0a388c0 --- .../server/middleware/MiddlewareManager.js | 70 +++++++ .../middleware/getDevToolsMiddleware.js | 4 +- local-cli/server/runServer.js | 190 ++++-------------- local-cli/server/server.js | 28 +-- 4 files changed, 113 insertions(+), 179 deletions(-) create mode 100644 local-cli/server/middleware/MiddlewareManager.js diff --git a/local-cli/server/middleware/MiddlewareManager.js b/local-cli/server/middleware/MiddlewareManager.js new file mode 100644 index 00000000000000..78b69c777ab2a9 --- /dev/null +++ b/local-cli/server/middleware/MiddlewareManager.js @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @strict + * @flow + */ + +const compression = require('compression'); +const connect = require('connect'); +const errorhandler = require('errorhandler'); +const morgan = require('morgan'); +const path = require('path'); +const serveStatic = require('serve-static'); +const WebSocketServer = require('ws').Server; + +const indexPageMiddleware = require('./indexPage'); +const copyToClipBoardMiddleware = require('./copyToClipBoardMiddleware'); +const loadRawBodyMiddleware = require('./loadRawBodyMiddleware'); +const openStackFrameInEditorMiddleware = require('./openStackFrameInEditorMiddleware'); +const statusPageMiddleware = require('./statusPageMiddleware.js'); +const systraceProfileMiddleware = require('./systraceProfileMiddleware.js'); +const getDevToolsMiddleware = require('./getDevToolsMiddleware'); + +type Options = { + +watchFolders: $ReadOnlyArray, + +host?: string, +} + +type WebSocketProxy = { + server: WebSocketServer, + isChromeConnected: () => boolean, +}; +type Connect = any; + +module.exports = class MiddlewareManager { + app: Connect; + options: Options; + + constructor(options: Options) { + const debuggerUIFolder = path.join(__dirname, 'util', 'debugger-ui'); + + this.options = options; + this.app = connect() + .use(loadRawBodyMiddleware) + .use(compression()) + .use('/debugger-ui', serveStatic(debuggerUIFolder)) + .use(openStackFrameInEditorMiddleware(this.options)) + .use(copyToClipBoardMiddleware) + .use(statusPageMiddleware) + .use(systraceProfileMiddleware) + .use(indexPageMiddleware) + .use(morgan('combined')) + .use(errorhandler()); + } + + serveStatic = (folder: string) => { + this.app.use(serveStatic(folder)); + }; + + getConnectInstance = () => this.app; + + attachDevToolsSocket = (socket: WebSocketProxy) => { + this.app.use( + getDevToolsMiddleware(this.options, () => socket.isChromeConnected()), + ); + }; +}; diff --git a/local-cli/server/middleware/getDevToolsMiddleware.js b/local-cli/server/middleware/getDevToolsMiddleware.js index 23ca15ee5a38a8..77aab8df9578df 100644 --- a/local-cli/server/middleware/getDevToolsMiddleware.js +++ b/local-cli/server/middleware/getDevToolsMiddleware.js @@ -27,8 +27,8 @@ function launchDevTools({host, watchFolders}, isChromeConnected) { // Explicit config always wins var customDebugger = process.env.REACT_DEBUGGER; if (customDebugger) { - var projects = watchFolders.map(escapePath).join(' '); - var command = customDebugger + ' ' + projects; + var folders = watchFolders.map(escapePath).join(' '); + var command = customDebugger + ' ' + folders; console.log('Starting custom debugger by executing: ' + command); exec(command, function(error, stdout, stderr) { if (error !== null) { diff --git a/local-cli/server/runServer.js b/local-cli/server/runServer.js index e2d57d4b1ebc84..59f822f44dad68 100644 --- a/local-cli/server/runServer.js +++ b/local-cli/server/runServer.js @@ -14,132 +14,69 @@ require('../../setupBabel')(); const Metro = require('metro'); -const HmrServer = require('metro/src/HmrServer'); - const {Terminal} = require('metro-core'); -const attachWebsocketServer = require('metro/src/lib/attachWebsocketServer'); -const compression = require('compression'); -const connect = require('connect'); -const copyToClipBoardMiddleware = require('./middleware/copyToClipBoardMiddleware'); -const defaultAssetExts = Metro.defaults.assetExts; -const defaultSourceExts = Metro.defaults.sourceExts; -const defaultPlatforms = Metro.defaults.platforms; -const defaultProvidesModuleNodeModules = - Metro.defaults.providesModuleNodeModules; -const errorhandler = require('errorhandler'); -const fs = require('fs'); -const getDevToolsMiddleware = require('./middleware/getDevToolsMiddleware'); -const http = require('http'); -const https = require('https'); -const indexPageMiddleware = require('./middleware/indexPage'); -const loadRawBodyMiddleware = require('./middleware/loadRawBodyMiddleware'); -const messageSocket = require('./util/messageSocket.js'); -const morgan = require('morgan'); -const openStackFrameInEditorMiddleware = require('./middleware/openStackFrameInEditorMiddleware'); const path = require('path'); -const serveStatic = require('serve-static'); -const statusPageMiddleware = require('./middleware/statusPageMiddleware.js'); -const systraceProfileMiddleware = require('./middleware/systraceProfileMiddleware.js'); -const webSocketProxy = require('./util/webSocketProxy.js'); - -const {ASSET_REGISTRY_PATH} = require('../core/Constants'); +const MiddlewareManager = require('./middleware/MiddlewareManager'); import type {ConfigT} from 'metro'; -/* $FlowFixMe(site=react_native_oss) */ -import type {Reporter} from 'metro/src/lib/reporting'; export type Args = {| +assetExts: $ReadOnlyArray, + +cert: string, + +customLogReporterPath?: string, +host: string, + +https: boolean, +maxWorkers: number, + +key: string, +nonPersistent: boolean, +platforms: $ReadOnlyArray, +port: number, +projectRoot: string, + +providesModuleNodeModules: Array, +resetCache: boolean, +sourceExts: $ReadOnlyArray, + +transformer?: string, +verbose: boolean, +watchFolders: $ReadOnlyArray, |}; -function runServer( - args: Args, - config: ConfigT, - // FIXME: this is weird design. The top-level should pass down a custom - // reporter rather than passing it up as argument to an event. - startedCallback: (reporter: Reporter) => mixed, - readyCallback: (reporter: Reporter) => mixed, -) { - var wsProxy = null; - var ms = null; - +async function runServer(args: Args, config: ConfigT) { const terminal = new Terminal(process.stdout); - /* $FlowFixMe(>=0.68.0 site=react_native_fb) This comment suppresses an error - * found when Flow v0.68 was deployed. To see the error delete this comment - * and run Flow. */ const ReporterImpl = getReporterImpl(args.customLogReporterPath || null); const reporter = new ReporterImpl(terminal); - const packagerServer = getPackagerServer(args, config, reporter); - startedCallback(reporter); - - const app = connect() - .use(loadRawBodyMiddleware) - .use(compression()) - .use( - '/debugger-ui', - serveStatic(path.join(__dirname, 'util', 'debugger-ui')), - ) - .use( - getDevToolsMiddleware(args, () => wsProxy && wsProxy.isChromeConnected()), - ) - .use(getDevToolsMiddleware(args, () => ms && ms.isChromeConnected())) - .use(openStackFrameInEditorMiddleware(args)) - .use(copyToClipBoardMiddleware) - .use(statusPageMiddleware) - .use(systraceProfileMiddleware) - .use(indexPageMiddleware) - .use(packagerServer.processRequest.bind(packagerServer)); - - args.watchFolders.forEach(root => app.use(serveStatic(root))); - - app.use(morgan('combined')).use(errorhandler()); - - /* $FlowFixMe(>=0.68.0 site=react_native_fb) This comment suppresses an error - * found when Flow v0.68 was deployed. To see the error delete this comment - * and run Flow. */ - if (args.https && (!args.key || !args.cert)) { - throw new Error('Cannot use https without specifying key and cert options'); - } - - /* $FlowFixMe(>=0.68.0 site=react_native_fb) This comment suppresses an error - * found when Flow v0.68 was deployed. To see the error delete this comment - * and run Flow. */ - const serverInstance = args.https - ? https.createServer( - { - key: fs.readFileSync(args.key), - cert: fs.readFileSync(args.cert), - }, - app, - ) - : http.createServer(app); - - serverInstance.listen(args.port, args.host, 511, function() { - attachWebsocketServer({ - httpServer: serverInstance, - path: '/hot', - websocketServer: new HmrServer(packagerServer), - }); - - wsProxy = webSocketProxy.attachToServer(serverInstance, '/debugger-proxy'); - ms = messageSocket.attachToServer(serverInstance, '/message'); - readyCallback(reporter); + const middlewareManager = new MiddlewareManager(args); + + args.watchFolders.forEach(middlewareManager.serveStatic); + + const serverInstance = await Metro.runServer({ + config: { + ...config, + hmrEnabled: true, + maxWorkers: args.maxWorkers, + reporter, + secure: args.https, + secureKey: args.key, + secureCert: args.cert, + transformModulePath: args.transformer + ? path.resolve(args.transformer) + : config.getTransformModulePath(), + watch: !args.nonPersistent, + }, }); - // Disable any kind of automatic timeout behavior for incoming - // requests in case it takes the packager more than the default - // timeout of 120 seconds to respond to a request. - serverInstance.timeout = 0; + + // In Node 8, the default keep-alive for an HTTP connection is 5 seconds. In + // early versions of Node 8, this was implemented in a buggy way which caused + // some HTTP responses (like those containing large JS bundles) to be + // terminated early. + // + // As a workaround, arbitrarily increase the keep-alive from 5 to 30 seconds, + // which should be enough to send even the largest of JS bundles. + // + // For more info: https://github.com/nodejs/node/issues/13391 + // + // $FlowFixMe + serverInstance.keepAliveTimeout = 30000; } function getReporterImpl(customLogReporterPath: ?string) { @@ -162,53 +99,4 @@ function getReporterImpl(customLogReporterPath: ?string) { } } -function getPackagerServer(args, config, reporter) { - /* $FlowFixMe(>=0.68.0 site=react_native_fb) This comment suppresses an error - * found when Flow v0.68 was deployed. To see the error delete this comment - * and run Flow. */ - const transformModulePath = args.transformer - ? path.resolve(args.transformer) - : config.getTransformModulePath(); - - const providesModuleNodeModules = - /* $FlowFixMe(>=0.68.0 site=react_native_fb) This comment suppresses an - * error found when Flow v0.68 was deployed. To see the error delete this - * comment and run Flow. */ - args.providesModuleNodeModules || defaultProvidesModuleNodeModules; - - return Metro.createServer({ - asyncRequireModulePath: config.getAsyncRequireModulePath(), - assetExts: defaultAssetExts.concat(args.assetExts), - assetRegistryPath: ASSET_REGISTRY_PATH, - blacklistRE: config.getBlacklistRE(), - cacheStores: config.cacheStores, - cacheVersion: '3', - enableBabelRCLookup: config.getEnableBabelRCLookup(), - extraNodeModules: config.extraNodeModules, - dynamicDepsInPackages: config.dynamicDepsInPackages, - getModulesRunBeforeMainModule: config.getModulesRunBeforeMainModule, - getPolyfills: config.getPolyfills, - getResolverMainFields: config.getResolverMainFields, - getRunModuleStatement: config.getRunModuleStatement, - getTransformOptions: config.getTransformOptions, - hasteImplModulePath: config.hasteImplModulePath, - maxWorkers: args.maxWorkers, - platforms: defaultPlatforms.concat(args.platforms), - polyfillModuleNames: config.getPolyfillModuleNames(), - postMinifyProcess: config.postMinifyProcess, - postProcessBundleSourcemap: config.postProcessBundleSourcemap, - projectRoot: args.projectRoot, - providesModuleNodeModules: providesModuleNodeModules, - reporter, - resetCache: args.resetCache, - resolveRequest: config.resolveRequest, - sourceExts: args.sourceExts.concat(defaultSourceExts), - transformModulePath: transformModulePath, - verbose: args.verbose, - watch: !args.nonPersistent, - watchFolders: args.watchFolders, - workerPath: config.getWorkerPath(), - }); -} - module.exports = runServer; diff --git a/local-cli/server/server.js b/local-cli/server/server.js index f74f7f16a79bc9..42423f5583759a 100644 --- a/local-cli/server/server.js +++ b/local-cli/server/server.js @@ -19,34 +19,10 @@ import type {Args as RunServerArgs} from './runServer'; /** * Starts the React Native Packager Server. */ -function server(argv: mixed, config: RNConfig, args: Object) { - const startedCallback = logReporter => { - logReporter.update({ - type: 'initialize_started', - port: args.port, - projectRoots: args.watchFolders, - }); - - process.on('uncaughtException', error => { - logReporter.update({ - type: 'initialize_failed', - port: args.port, - error, - }); - - process.exit(11); - }); - }; - - const readyCallback = logReporter => { - logReporter.update({ - type: 'initialize_done', - }); - }; - const runServerArgs: RunServerArgs = args; +function server(argv: mixed, config: RNConfig, args: RunServerArgs) { /* $FlowFixMe(site=react_native_fb) ConfigT shouldn't be extendable. */ const configT: ConfigT = config; - runServer(runServerArgs, configT, startedCallback, readyCallback); + runServer(args, configT); } module.exports = { From 27a38dedf1af3295a535c5f72e3e7443c07c1075 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Mon, 2 Jul 2018 09:52:04 -0700 Subject: [PATCH 16/65] Enable View flatening optimization by default Summary: This diff enables view flattening optimizations by default Reviewed By: wwjholmes, yungsters Differential Revision: D8699050 fbshipit-source-id: d37d06fe330e223c49a0788e85f6338fd056fd19 --- .../facebook/react/uimanager/ViewProps.java | 78 +++++++++---------- 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java index 0a353a6b0f242a..58e67ccb752434 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java @@ -212,8 +212,6 @@ public class ViewProps { PADDING_START, PADDING_END)); - public static boolean sIsOptimizationsEnabled; - public static boolean isLayoutOnly(ReadableMap map, String prop) { if (LAYOUT_ONLY_PROPS.contains(prop)) { return true; @@ -222,47 +220,43 @@ public static boolean isLayoutOnly(ReadableMap map, String prop) { return AUTO.equals(value) || BOX_NONE.equals(value); } - - if (sIsOptimizationsEnabled) { - switch (prop) { - case OPACITY: - // null opacity behaves like opacity = 1 - // Ignore if explicitly set to default opacity. - return map.isNull(OPACITY) || map.getDouble(OPACITY) == 1d; - case BORDER_RADIUS: // Without a background color or border width set, a border won't show. - if (map.hasKey(BACKGROUND_COLOR) && map.getInt(BACKGROUND_COLOR) != Color.TRANSPARENT) { - return false; - } - if (map.hasKey(BORDER_WIDTH) - && !map.isNull(BORDER_WIDTH) - && map.getDouble(BORDER_WIDTH) != 0d) { - return false; - } - return true; - case BORDER_LEFT_COLOR: - return map.getInt(BORDER_LEFT_COLOR) == Color.TRANSPARENT; - case BORDER_RIGHT_COLOR: - return map.getInt(BORDER_RIGHT_COLOR) == Color.TRANSPARENT; - case BORDER_TOP_COLOR: - return map.getInt(BORDER_TOP_COLOR) == Color.TRANSPARENT; - case BORDER_BOTTOM_COLOR: - return map.getInt(BORDER_BOTTOM_COLOR) == Color.TRANSPARENT; - case BORDER_WIDTH: - return map.isNull(BORDER_WIDTH) || map.getDouble(BORDER_WIDTH) == 0d; - case BORDER_LEFT_WIDTH: - return map.isNull(BORDER_LEFT_WIDTH) || map.getDouble(BORDER_LEFT_WIDTH) == 0d; - case BORDER_TOP_WIDTH: - return map.isNull(BORDER_TOP_WIDTH) || map.getDouble(BORDER_TOP_WIDTH) == 0d; - case BORDER_RIGHT_WIDTH: - return map.isNull(BORDER_RIGHT_WIDTH) || map.getDouble(BORDER_RIGHT_WIDTH) == 0d; - case BORDER_BOTTOM_WIDTH: - return map.isNull(BORDER_BOTTOM_WIDTH) || map.getDouble(BORDER_BOTTOM_WIDTH) == 0d; - case OVERFLOW: - return map.isNull(OVERFLOW) || VISIBLE.equals(map.getString(OVERFLOW)); - default: + switch (prop) { + case OPACITY: + // null opacity behaves like opacity = 1 + // Ignore if explicitly set to default opacity. + return map.isNull(OPACITY) || map.getDouble(OPACITY) == 1d; + case BORDER_RADIUS: // Without a background color or border width set, a border won't show. + if (map.hasKey(BACKGROUND_COLOR) && map.getInt(BACKGROUND_COLOR) != Color.TRANSPARENT) { return false; + } + if (map.hasKey(BORDER_WIDTH) + && !map.isNull(BORDER_WIDTH) + && map.getDouble(BORDER_WIDTH) != 0d) { + return false; + } + return true; + case BORDER_LEFT_COLOR: + return map.getInt(BORDER_LEFT_COLOR) == Color.TRANSPARENT; + case BORDER_RIGHT_COLOR: + return map.getInt(BORDER_RIGHT_COLOR) == Color.TRANSPARENT; + case BORDER_TOP_COLOR: + return map.getInt(BORDER_TOP_COLOR) == Color.TRANSPARENT; + case BORDER_BOTTOM_COLOR: + return map.getInt(BORDER_BOTTOM_COLOR) == Color.TRANSPARENT; + case BORDER_WIDTH: + return map.isNull(BORDER_WIDTH) || map.getDouble(BORDER_WIDTH) == 0d; + case BORDER_LEFT_WIDTH: + return map.isNull(BORDER_LEFT_WIDTH) || map.getDouble(BORDER_LEFT_WIDTH) == 0d; + case BORDER_TOP_WIDTH: + return map.isNull(BORDER_TOP_WIDTH) || map.getDouble(BORDER_TOP_WIDTH) == 0d; + case BORDER_RIGHT_WIDTH: + return map.isNull(BORDER_RIGHT_WIDTH) || map.getDouble(BORDER_RIGHT_WIDTH) == 0d; + case BORDER_BOTTOM_WIDTH: + return map.isNull(BORDER_BOTTOM_WIDTH) || map.getDouble(BORDER_BOTTOM_WIDTH) == 0d; + case OVERFLOW: + return map.isNull(OVERFLOW) || VISIBLE.equals(map.getString(OVERFLOW)); + default: + return false; } - } - return false; } } From fdce93845514a781d01da8cc2c944dbb571f3012 Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Mon, 2 Jul 2018 10:41:17 -0700 Subject: [PATCH 17/65] fix missing prettier file (#20001) Summary: fix missing prettier file pass all current ci. https://github.com/facebook/react-native/pull/19987 [GENERAL] [INTERNAL] [TOOL] - fix missing prettier file. Closes https://github.com/facebook/react-native/pull/20001 Differential Revision: D8714374 Pulled By: hramos fbshipit-source-id: acdcb5d84c56d26c55f6262a0a98aefe786de8cb --- Libraries/polyfills/babelHelpers.js | 3 +-- local-cli/runAndroid/runAndroid.js | 13 +++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Libraries/polyfills/babelHelpers.js b/Libraries/polyfills/babelHelpers.js index 991b4fbfbdb216..f831deaa842fac 100644 --- a/Libraries/polyfills/babelHelpers.js +++ b/Libraries/polyfills/babelHelpers.js @@ -197,8 +197,7 @@ babelHelpers.get = function _get(target, property, receiver = target) { } return desc.value; -} - +}; // ### inherits ### diff --git a/local-cli/runAndroid/runAndroid.js b/local-cli/runAndroid/runAndroid.js index cd21b6ac29cfd7..6835c97bcb0bf0 100644 --- a/local-cli/runAndroid/runAndroid.js +++ b/local-cli/runAndroid/runAndroid.js @@ -354,9 +354,7 @@ function startServerInNewWindow(port) { const scriptFile = isWindows ? 'launchPackager.bat' : 'launchPackager.command'; - const packagerEnvFilename = isWindows - ? '.packager.bat' - : '.packager.env'; + const packagerEnvFilename = isWindows ? '.packager.bat' : '.packager.env'; const portExportContent = isWindows ? `set RCT_METRO_PORT=${port}` : `export RCT_METRO_PORT=${port}`; @@ -373,11 +371,14 @@ function startServerInNewWindow(port) { '..', '..', 'scripts', - packagerEnvFilename + packagerEnvFilename, ); - + // ensure we overwrite file by passing the 'w' flag - fs.writeFileSync(packagerEnvFile, portExportContent, {encoding: 'utf8', flag: 'w'}); + fs.writeFileSync(packagerEnvFile, portExportContent, { + encoding: 'utf8', + flag: 'w', + }); if (process.platform === 'darwin') { if (terminal) { From 54942746d4037e1153e14fcfc95e4edc772d296a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Mon, 2 Jul 2018 11:05:31 -0700 Subject: [PATCH 18/65] Hotfix to include react-native-windows in hasteImpl accepted paths (#20007) Summary: Closes https://github.com/facebook/react-native/pull/20007 We removed support for providesModule annotations and maintained support for Haste names in installed modules via `providesModuleNodeModules`, but our default `hasteImpl` doesn't take them into account. We need to find a better way to override core components from plugins but meanwhile this adds an exception for react-native-windows in the default `hasteImpl` to unblock their upgrade to the latest RC. Fixes https://github.com/facebook/metro/issues/188 Reviewed By: mjesun Differential Revision: D8695207 fbshipit-source-id: 2ad6cb1e93e600880a148776ac45f6ebd7d205d3 --- jest/hasteImpl.js | 12 ++++++++---- local-cli/core/index.js | 8 ++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/jest/hasteImpl.js b/jest/hasteImpl.js index 568f7e8df0d0dc..e72fa4f37b26ab 100644 --- a/jest/hasteImpl.js +++ b/jest/hasteImpl.js @@ -12,7 +12,10 @@ const path = require('path'); -const ROOT = path.join(__dirname, '..'); +const ROOTS = [ + path.resolve(__dirname, '..') + path.sep, + path.resolve(__dirname, '../../react-native-windows') + path.sep, +]; const BLACKLISTED_PATTERNS /*: Array */ = [ /.*\/__(mocks|tests)__\/.*/, @@ -33,7 +36,7 @@ const NAME_REDUCERS /*: Array<[RegExp, string]> */ = [ // strip .js/.js.flow suffix [/^(.*)\.js(\.flow)?$/, '$1'], // strip .android/.ios/.native/.web suffix - [/^(.*)\.(android|ios|native|web)$/, '$1'], + [/^(.*)\.(android|ios|native|web|windows)$/, '$1'], ]; const haste = { @@ -63,11 +66,12 @@ function isHastePath(filePath /*: string */) /*: boolean */ { return false; } - if (!filePath.startsWith(ROOT)) { + const root = ROOTS.find(r => filePath.startsWith(r)); + if (!root) { return false; } - filePath = filePath.substr(ROOT.length + 1); + filePath = filePath.substr(root.length); if (BLACKLISTED_PATTERNS.some(pattern => pattern.test(filePath))) { return false; } diff --git a/local-cli/core/index.js b/local-cli/core/index.js index d2b3399d177b37..4d94aaebef4bac 100644 --- a/local-cli/core/index.js +++ b/local-cli/core/index.js @@ -72,6 +72,14 @@ const pluginPlatforms = plugins.platforms.reduce((acc, pathToPlatforms) => { const defaultRNConfig = { hasteImplModulePath: require.resolve('../../jest/hasteImpl'), + getPlatforms(): Array { + return ['ios', 'android', 'windows', 'web']; + }, + + getProvidesModuleNodeModules(): Array { + return ['react-native', 'react-native-windows']; + }, + getProjectCommands(): Array { const commands = plugins.commands.map(pathToCommands => { const name = pathToCommands.split(path.sep)[0]; From db2159d0b3fd57556383eff68d32d32246dd9081 Mon Sep 17 00:00:00 2001 From: Yunyu Lin Date: Mon, 2 Jul 2018 13:26:38 -0700 Subject: [PATCH 19/65] Fix some classes of incorrect Flow errors for Animated Summary: Replace the union with a spread Reviewed By: blairvanderhoof Differential Revision: D8715694 fbshipit-source-id: 3b1ce893a065bfc7395b576e485a79f09bacc999 --- Libraries/Animated/src/Animated.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Libraries/Animated/src/Animated.js b/Libraries/Animated/src/Animated.js index f25d2a0796a1ad..8678b21f14b889 100644 --- a/Libraries/Animated/src/Animated.js +++ b/Libraries/Animated/src/Animated.js @@ -16,14 +16,10 @@ const ScrollView = require('ScrollView'); const Text = require('Text'); const View = require('View'); -const Animated = { +module.exports = { + ...AnimatedImplementation, View: AnimatedImplementation.createAnimatedComponent(View), Text: AnimatedImplementation.createAnimatedComponent(Text), Image: AnimatedImplementation.createAnimatedComponent(Image), ScrollView: AnimatedImplementation.createAnimatedComponent(ScrollView), }; - -Object.assign((Animated: Object), AnimatedImplementation); - -module.exports = ((Animated: any): typeof AnimatedImplementation & - typeof Animated); From 3b29274cc1dc335fd810cbbef0e32123d8257704 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Mon, 2 Jul 2018 14:41:49 -0700 Subject: [PATCH 20/65] Remove the deprecated `isIPhoneX_deprecated` constant (#19920) Summary: Cleanup the `isIPhoneX_deprecated` constant which was said to be removed by June 1st 2018. Closes https://github.com/facebook/react-native/pull/19920 Differential Revision: D8714400 Pulled By: hramos fbshipit-source-id: 0b0b3a2d7b8098baf0474afea230780c79b2fe14 --- RNTester/js/SafeAreaViewExample.js | 24 ------------------------ React/Modules/RCTDeviceInfo.m | 21 --------------------- 2 files changed, 45 deletions(-) diff --git a/RNTester/js/SafeAreaViewExample.js b/RNTester/js/SafeAreaViewExample.js index 927a26651a4f8f..0af1d1f1f99ac8 100644 --- a/RNTester/js/SafeAreaViewExample.js +++ b/RNTester/js/SafeAreaViewExample.js @@ -64,21 +64,6 @@ class SafeAreaViewExample extends React.Component< } } -class IsIPhoneXExample extends React.Component<{}> { - render() { - return ( - - - Is this an iPhone X:{' '} - {DeviceInfo.isIPhoneX_deprecated - ? 'Yeah!' - : 'Nope. (Or `isIPhoneX_deprecated` was already removed.)'} - - - ); - } -} - exports.examples = [ { title: ' Example', @@ -86,15 +71,6 @@ exports.examples = [ 'SafeAreaView automatically applies paddings reflect the portion of the view that is not covered by other (special) ancestor views.', render: () => , }, - { - title: 'isIPhoneX_deprecated Example', - description: - '`DeviceInfo.isIPhoneX_deprecated` returns true only on iPhone X. ' + - 'Note: This prop is deprecated and will be removed right after June 01, 2018. ' + - 'Please use this only for a quick and temporary solution. ' + - 'Use instead.', - render: () => , - }, ]; var styles = StyleSheet.create({ diff --git a/React/Modules/RCTDeviceInfo.m b/React/Modules/RCTDeviceInfo.m index 20e53d55af611f..7db187e3063d62 100644 --- a/React/Modules/RCTDeviceInfo.m +++ b/React/Modules/RCTDeviceInfo.m @@ -51,22 +51,6 @@ - (void)setBridge:(RCTBridge *)bridge #endif } -static BOOL RCTIsIPhoneX() { - static BOOL isIPhoneX = NO; - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - RCTAssertMainQueue(); - - isIPhoneX = CGSizeEqualToSize( - [UIScreen mainScreen].nativeBounds.size, - CGSizeMake(1125, 2436) - ); - }); - - return isIPhoneX; -} - static NSDictionary *RCTExportedDimensions(RCTBridge *bridge) { RCTAssertMainQueue(); @@ -102,11 +86,6 @@ - (void)invalidate { return @{ @"Dimensions": RCTExportedDimensions(_bridge), - // Note: - // This prop is deprecated and will be removed right after June 01, 2018. - // Please use this only for a quick and temporary solution. - // Use instead. - @"isIPhoneX_deprecated": @(RCTIsIPhoneX()), }; } From 18d3648fa8a3e3fd978e981327672b3a0af4c748 Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Mon, 2 Jul 2018 14:42:39 -0700 Subject: [PATCH 21/65] Simplify `yarn prettier` and make it work on windows (#19987) Summary: make prettier script works on windows pass all current ci. none [GENERAL] [INTERNAL] [Script] - make prettier script works on windows. Closes https://github.com/facebook/react-native/pull/19987 Differential Revision: D8714381 Pulled By: hramos fbshipit-source-id: 0e5c5a6a5817094edd47918eb57d7f5a281560d6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d25acb17563443..d25b34bab2aa10 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "test-ci": "JEST_JUNIT_OUTPUT=\"reports/junit/js-test-results.xml\" jest --maxWorkers=2 --ci --testResultsProcessor=\"jest-junit\"", "flow": "flow", "lint": "eslint .", - "prettier": "find . -name node_modules -prune -or -name '*.js' -print | xargs prettier --write", + "prettier": "prettier \"./**/*.js\" --write", "start": "/usr/bin/env bash -c './scripts/packager.sh \"$@\" || true' --", "docker-setup-android": "docker pull reactnativeci/android-base:latest", "docker-build-android-base": "docker build -t reactnativeci/android-base -f ContainerShip/Dockerfile.android-base .", From a09c464585e7141bf631a988e25464c86c93a192 Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Mon, 2 Jul 2018 17:23:48 -0700 Subject: [PATCH 22/65] iOS: avoid crash because of null eventTarget Summary: We were supposed to pass in proper eventEmitter, but passed in one with null eventTarget instead, causing assertion failures when dispatching event. Reviewed By: sebmarkbage, shergin Differential Revision: D8720793 fbshipit-source-id: 891f3b2a2c76a6dd3e40039623c6e86991aad50b --- ReactCommon/fabric/uimanager/FabricUIManager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ReactCommon/fabric/uimanager/FabricUIManager.cpp b/ReactCommon/fabric/uimanager/FabricUIManager.cpp index 463c537bcdbf84..23dd8f8c60bb81 100644 --- a/ReactCommon/fabric/uimanager/FabricUIManager.cpp +++ b/ReactCommon/fabric/uimanager/FabricUIManager.cpp @@ -166,7 +166,7 @@ SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode) componentDescriptor->cloneShadowNode( shadowNode, nullptr, - componentDescriptor->createEventEmitter(nullptr /*TODO(shergin)*/, shadowNode->getTag()), + shadowNode->getEventEmitter(), nullptr ); @@ -183,7 +183,7 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNod componentDescriptor->cloneShadowNode( shadowNode, nullptr, - componentDescriptor->createEventEmitter(nullptr /*TODO(shergin)*/, shadowNode->getTag()), + shadowNode->getEventEmitter(), ShadowNode::emptySharedShadowNodeSharedList() ); @@ -201,7 +201,7 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode & componentDescriptor->cloneShadowNode( shadowNode, componentDescriptor->cloneProps(shadowNode->getProps(), rawProps), - componentDescriptor->createEventEmitter(nullptr /*TODO(shergin)*/, shadowNode->getTag()), + shadowNode->getEventEmitter(), nullptr ); @@ -219,7 +219,7 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewChildrenAndProps(const SharedS componentDescriptor->cloneShadowNode( shadowNode, componentDescriptor->cloneProps(shadowNode->getProps(), rawProps), - componentDescriptor->createEventEmitter(nullptr /*TODO(shergin)*/, shadowNode->getTag()), + shadowNode->getEventEmitter(), ShadowNode::emptySharedShadowNodeSharedList() ); From c1831d50cfd35b7a7393e50bc71d8389b36021ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Here=C3=B1=C3=BA?= Date: Mon, 2 Jul 2018 20:17:47 -0700 Subject: [PATCH 23/65] Typo in DockerTests.md (#20009) Summary: [DOCS] [BUGFIX] [DockerTests.md] - Typo on string #038 Closes https://github.com/facebook/react-native/pull/20009 Differential Revision: D8721811 Pulled By: TheSavior fbshipit-source-id: e678c74fd89bc0c0e9db48590e1911d23bc4d339 --- DockerTests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DockerTests.md b/DockerTests.md index 790d1952786954..f1714db87a0a05 100644 --- a/DockerTests.md +++ b/DockerTests.md @@ -35,7 +35,7 @@ There are two Dockerfiles for use with the Android codebase. The `Dockerfile.android-base` contains all the necessary prerequisites required to run the React Android tests. It is separated out into a separate Dockerfile because these are dependencies that rarely change and also because it is quite -a beastly image since it contains all the Android depedencies for running android and the emulators (~9GB). +a beastly image since it contains all the Android dependencies for running android and the emulators (~9GB). The good news is you should rarely have to build or pull down the base image! All iterative code updates happen as part of the `Dockerfile.android` image build. From bbdc12eda7dec135799b7f4c41fe678180970dd2 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Tue, 3 Jul 2018 00:24:18 -0700 Subject: [PATCH 24/65] RN: Add Overflow Visible Kill Switch (Android) Summary: Adds a kill switch that reverts the default behavior of `overflow` to be hidden again. The intent of this kill switch is to give applications more time to migrate if necessary (e.g. if they are depending on third party packages with native components that are not compatible with `overflow` being visible by default). To use the flag, simply set: import com.facebook.react.views.view.ReactViewGroup; // Somewhere in the initialization of your application. ReactViewGroup.sDefaultOverflowHidden = true; Reviewed By: achen1 Differential Revision: D8718963 fbshipit-source-id: 0eb9aee45dfe04e9ae34d86e3bedcd30a185ef82 --- .../com/facebook/react/views/view/ReactViewGroup.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 bdd522bd2a60ad..e8afaa93574538 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 @@ -49,6 +49,11 @@ public class ReactViewGroup extends ViewGroup implements ReactInterceptingViewGroup, ReactClippingViewGroup, ReactPointerEventsView, ReactHitSlopView, ReactZIndexedViewGroup { + /** + * Kill switch to make overflow hidden by default. This flag will eventually be removed. + */ + public static boolean sDefaultOverflowHidden; + private static final int ARRAY_CAPACITY_INCREMENT = 12; private static final int DEFAULT_BACKGROUND_COLOR = Color.TRANSPARENT; private static final LayoutParams sDefaultLayoutParam = new ViewGroup.LayoutParams(0, 0); @@ -113,7 +118,10 @@ public void onLayoutChange( public ReactViewGroup(Context context) { super(context); - setClipChildren(false); + // TODO: Remove this check after a couple public releases. + if (!sDefaultOverflowHidden) { + setClipChildren(false); + } mDrawingOrderHelper = new ViewGroupDrawingOrderHelper(this); } From ba56725eb8fa905986095fa828f2fcfcb1b61838 Mon Sep 17 00:00:00 2001 From: Peter van der Zee Date: Tue, 3 Jul 2018 08:42:49 -0700 Subject: [PATCH 25/65] Upgrade eslint to v5.0.1 on xplat Summary: @public Upgrades eslint to v5.0.1 Updated `eslint-plugin-eslint-comments`, which was necessary for eslint 5 Disabled the `prefer-const` rule while we wait for https://github.com/eslint/eslint/issues/10520 to be fixed/published. Reviewed By: zertosh Differential Revision: D8692838 fbshipit-source-id: fa0cae3e299af2350c8c30ceb94d70740ee84eab --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d25b34bab2aa10..ef7f978438e24d 100644 --- a/package.json +++ b/package.json @@ -203,10 +203,10 @@ "async": "^2.4.0", "babel-eslint": "8.2.1", "babel-generator": "^6.26.0", - "eslint": "4.17.0", + "eslint": "5.0.1", "eslint-config-fb-strict": "22.1.0", "eslint-config-fbjs": "2.0.1", - "eslint-plugin-eslint-comments": "2.0.2", + "eslint-plugin-eslint-comments": "^3.0.1", "eslint-plugin-flowtype": "2.43.0", "eslint-plugin-jest": "21.8.0", "eslint-plugin-prettier": "2.6.0", From bbc8bb1f9d6b9f99d7bdca09f553c4015555bd51 Mon Sep 17 00:00:00 2001 From: Miguel Jimenez Esun Date: Tue, 3 Jul 2018 13:44:54 -0700 Subject: [PATCH 26/65] Do not use morgan internally Summary: `morgan` produces non-json output, which affects `js1 run` when ran with the `--json` flag. Reviewed By: Kureev Differential Revision: D8724830 fbshipit-source-id: 11377f6ef39341c658a7f905383398423a721630 --- local-cli/server/middleware/MiddlewareManager.js | 5 ++--- local-cli/server/runServer.js | 3 +++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/local-cli/server/middleware/MiddlewareManager.js b/local-cli/server/middleware/MiddlewareManager.js index 78b69c777ab2a9..25fe213c287d62 100644 --- a/local-cli/server/middleware/MiddlewareManager.js +++ b/local-cli/server/middleware/MiddlewareManager.js @@ -11,7 +11,6 @@ const compression = require('compression'); const connect = require('connect'); const errorhandler = require('errorhandler'); -const morgan = require('morgan'); const path = require('path'); const serveStatic = require('serve-static'); const WebSocketServer = require('ws').Server; @@ -33,7 +32,8 @@ type WebSocketProxy = { server: WebSocketServer, isChromeConnected: () => boolean, }; -type Connect = any; + +type Connect = $Call; module.exports = class MiddlewareManager { app: Connect; @@ -52,7 +52,6 @@ module.exports = class MiddlewareManager { .use(statusPageMiddleware) .use(systraceProfileMiddleware) .use(indexPageMiddleware) - .use(morgan('combined')) .use(errorhandler()); } diff --git a/local-cli/server/runServer.js b/local-cli/server/runServer.js index 59f822f44dad68..f5a94b73958894 100644 --- a/local-cli/server/runServer.js +++ b/local-cli/server/runServer.js @@ -16,6 +16,7 @@ const Metro = require('metro'); const {Terminal} = require('metro-core'); +const morgan = require('morgan'); const path = require('path'); const MiddlewareManager = require('./middleware/MiddlewareManager'); @@ -47,6 +48,8 @@ async function runServer(args: Args, config: ConfigT) { const reporter = new ReporterImpl(terminal); const middlewareManager = new MiddlewareManager(args); + middlewareManager.getConnectInstance().use(morgan('combined')); + args.watchFolders.forEach(middlewareManager.serveStatic); const serverInstance = await Metro.runServer({ From 28c7ccf785132458fce32c234ce777a6fe475c93 Mon Sep 17 00:00:00 2001 From: Himabindu Gadupudi Date: Tue, 3 Jul 2018 15:31:48 -0700 Subject: [PATCH 27/65] Image source without uri should return null. Summary: When image source doesn't have uri and is neither an array, it should return null. Reviewed By: yungsters Differential Revision: D8728688 fbshipit-source-id: 915c4f3f450907ee3435ac99b1fe9849738766da --- Libraries/Image/Image.android.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index 6f0a312e97ef20..ec25a4ee1eeb04 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -212,6 +212,10 @@ let Image = ( ); } + if (!source.uri && !Array.isArray(source)) { + return null; + } + let style; let sources; if (source?.uri != null) { From 33d20da41b814a2fb9ba02cbab8b61a819cad95b Mon Sep 17 00:00:00 2001 From: Dulmandakh Date: Tue, 3 Jul 2018 18:12:38 -0700 Subject: [PATCH 28/65] @allow-large-files [react-native][PR] Upgrade Gradle to 4.4 (#19899) Summary: Bump gradle to 4.4, version used by android studio 3.x and gradle plugin 3.x. This will help make migration easier and smoother. CI: https://circleci.com/gh/dulmandakh/react-native/591 FYI: I found that gradle 4.8 works fine with gradle plugin 2.3, but gradle plugin 3.x displays warnings and asks to disable on demand configuration. Closes https://github.com/facebook/react-native/pull/19899 Reviewed By: fkgozali Differential Revision: D8697929 Pulled By: hramos fbshipit-source-id: 21eb625ee1e4a1fa02aa22de4c36a07269ca467b --- gradle/wrapper/gradle-wrapper.properties | 2 +- .../HelloWorld/android/gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ec9c72459fa28a..e318290e619bb6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/local-cli/templates/HelloWorld/android/gradle/wrapper/gradle-wrapper.properties b/local-cli/templates/HelloWorld/android/gradle/wrapper/gradle-wrapper.properties index 81a86e213401f8..b6517bb1d16502 100644 --- a/local-cli/templates/HelloWorld/android/gradle/wrapper/gradle-wrapper.properties +++ b/local-cli/templates/HelloWorld/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip From 079bf3f2067cb268b60e75cd9e1bc51a9c85359c Mon Sep 17 00:00:00 2001 From: Zdravko Nikolovski Date: Tue, 3 Jul 2018 18:13:06 -0700 Subject: [PATCH 29/65] Packager linking when using custom debug configuration on iOS device (#16451) Summary: In many projects we have different environments that we connect to. For these environments (for example: Test, Staging, Production) we have custom configurations (Debug and Release). While this is not a problem on Android, it is a problem on iOS. With the current implementation of the react-native-xcode.sh script, when using a custom Debug configuration, the app started on iOS device, can't contact the Packager. This pull request solves this issue. Connect a real device, start the app with a custom debug configuration in Xcode. Shake and Reload. [IOS][BUGFIX][./scripts/react-native-xcode.sh] Add support for connecting to the Packager when running the iOS app on device when using custom Debug configuration. Closes https://github.com/facebook/react-native/pull/16451 Differential Revision: D8730537 Pulled By: hramos fbshipit-source-id: a36007776e8fe9e401c38015040abd2c2bbd7c58 --- scripts/react-native-xcode.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/react-native-xcode.sh b/scripts/react-native-xcode.sh index 7194c2a1856c5b..88ea804a806324 100755 --- a/scripts/react-native-xcode.sh +++ b/scripts/react-native-xcode.sh @@ -94,7 +94,7 @@ type $NODE_BINARY >/dev/null 2>&1 || nodejs_not_found set -x DEST=$CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH -if [[ "$CONFIGURATION" = "Debug" && ! "$PLATFORM_NAME" == *simulator ]]; then +if [[ "$CONFIGURATION" = *Debug* && ! "$PLATFORM_NAME" == *simulator ]]; then IP=$(ipconfig getifaddr en0) if [ -z "$IP" ]; then IP=$(ifconfig | grep 'inet ' | grep -v ' 127.' | cut -d\ -f2 | awk 'NR==1{print $1}') From 50675404873c1ffac0deedc51fe745168051148b Mon Sep 17 00:00:00 2001 From: Alexey Kureev Date: Tue, 3 Jul 2018 23:45:28 -0700 Subject: [PATCH 30/65] Fix react-native CLI (internal and external one) Summary: - Fix wrong debugger-ui path - Override host and port using args Reviewed By: yungsters Differential Revision: D8731159 fbshipit-source-id: ca8ad76a02eda9e0b9cdb1a952aa5631d660868f --- local-cli/server/middleware/MiddlewareManager.js | 2 +- local-cli/server/runServer.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/local-cli/server/middleware/MiddlewareManager.js b/local-cli/server/middleware/MiddlewareManager.js index 25fe213c287d62..5402caf6f8ed12 100644 --- a/local-cli/server/middleware/MiddlewareManager.js +++ b/local-cli/server/middleware/MiddlewareManager.js @@ -40,7 +40,7 @@ module.exports = class MiddlewareManager { options: Options; constructor(options: Options) { - const debuggerUIFolder = path.join(__dirname, 'util', 'debugger-ui'); + const debuggerUIFolder = path.join(__dirname, '..', 'util', 'debugger-ui'); this.options = options; this.app = connect() diff --git a/local-cli/server/runServer.js b/local-cli/server/runServer.js index f5a94b73958894..7dfaaed72a18ff 100644 --- a/local-cli/server/runServer.js +++ b/local-cli/server/runServer.js @@ -66,6 +66,8 @@ async function runServer(args: Args, config: ConfigT) { : config.getTransformModulePath(), watch: !args.nonPersistent, }, + host: args.host, + port: args.port, }); // In Node 8, the default keep-alive for an HTTP connection is 5 seconds. In From fff43614aa5185e9815a0b42ab2c1d8299ce1fc7 Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Thu, 5 Jul 2018 13:59:44 -0700 Subject: [PATCH 31/65] android: disable `setClipChildren(false)` until RN ART issue is resolved Summary: It looks like for some reason when ReactViewGroup uses setClipChildren(false), the ReactNativeARTSurface no longer redraws when its width is expanded. Disable this new overflow behavior until the underlying issue is fixed. Reviewed By: achen1 Differential Revision: D8739003 fbshipit-source-id: ffae0e3eb0cd8ce385eae33a87b5ba0325cae3c4 --- .../java/com/facebook/react/views/view/ReactViewGroup.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 e8afaa93574538..f3942754ec98be 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 @@ -51,8 +51,9 @@ public class ReactViewGroup extends ViewGroup implements /** * Kill switch to make overflow hidden by default. This flag will eventually be removed. + * TODO (T31096050): Sets this back to `false` until ReactNativeARTSurface issue is resolved. */ - public static boolean sDefaultOverflowHidden; + public static boolean sDefaultOverflowHidden = true; private static final int ARRAY_CAPACITY_INCREMENT = 12; private static final int DEFAULT_BACKGROUND_COLOR = Color.TRANSPARENT; From 2424ef5654cffbe8c62465325c4c04eb00b40c01 Mon Sep 17 00:00:00 2001 From: Spencer Ahrens Date: Thu, 5 Jul 2018 15:08:10 -0700 Subject: [PATCH 32/65] Move ScrollView prop comments from propTypes to flow types Summary: Next step: make propTypes `__DEV__` only. Reviewed By: TheSavior Differential Revision: D8721300 fbshipit-source-id: 066b495836a87ea92d370728911e7b7ba6566c53 --- Libraries/Components/ScrollView/ScrollView.js | 676 +++++++++--------- 1 file changed, 338 insertions(+), 338 deletions(-) diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index a2be38422765ef..cec27cc67fff6c 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -76,49 +76,263 @@ type TouchableProps = $ReadOnly<{| |}>; type IOSProps = $ReadOnly<{| + /** + * Controls whether iOS should automatically adjust the content inset + * for scroll views that are placed behind a navigation bar or + * tab bar/ toolbar. The default value is true. + * @platform ios + */ automaticallyAdjustContentInsets?: ?boolean, + /** + * The amount by which the scroll view content is inset from the edges + * of the scroll view. Defaults to `{top: 0, left: 0, bottom: 0, right: 0}`. + * @platform ios + */ contentInset?: ?EdgeInsetsProp, + /** + * Used to manually set the starting scroll offset. + * The default value is `{x: 0, y: 0}`. + * @platform ios + */ contentOffset?: ?PointProp, + /** + * When true, the scroll view bounces when it reaches the end of the + * content if the content is larger then the scroll view along the axis of + * the scroll direction. When false, it disables all bouncing even if + * the `alwaysBounce*` props are true. The default value is true. + * @platform ios + */ bounces?: ?boolean, + /** + * When true, gestures can drive zoom past min/max and the zoom will animate + * to the min/max value at gesture end, otherwise the zoom will not exceed + * the limits. + * @platform ios + */ bouncesZoom?: ?boolean, + /** + * When true, the scroll view bounces horizontally when it reaches the end + * even if the content is smaller than the scroll view itself. The default + * value is true when `horizontal={true}` and false otherwise. + * @platform ios + */ alwaysBounceHorizontal?: ?boolean, + /** + * When true, the scroll view bounces vertically when it reaches the end + * even if the content is smaller than the scroll view itself. The default + * value is false when `horizontal={true}` and true otherwise. + * @platform ios + */ alwaysBounceVertical?: ?boolean, + /** + * When true, the scroll view automatically centers the content when the + * content is smaller than the scroll view bounds; when the content is + * larger than the scroll view, this property has no effect. The default + * value is false. + * @platform ios + */ centerContent?: ?boolean, + /** + * A floating-point number that determines how quickly the scroll view + * decelerates after the user lifts their finger. You may also use string + * shortcuts `"normal"` and `"fast"` which match the underlying iOS settings + * for `UIScrollViewDecelerationRateNormal` and + * `UIScrollViewDecelerationRateFast` respectively. + * + * - `'normal'`: 0.998 (the default) + * - `'fast'`: 0.99 + * + * @platform ios + */ decelerationRate?: ?('fast' | 'normal' | number), + /** + * The style of the scroll indicators. + * + * - `'default'` (the default), same as `black`. + * - `'black'`, scroll indicator is black. This style is good against a light background. + * - `'white'`, scroll indicator is white. This style is good against a dark background. + * + * @platform ios + */ indicatorStyle?: ?('default' | 'black' | 'white'), + /** + * When true, the ScrollView will try to lock to only vertical or horizontal + * scrolling while dragging. The default value is false. + * @platform ios + */ directionalLockEnabled?: ?boolean, + /** + * When false, once tracking starts, won't try to drag if the touch moves. + * The default value is true. + * @platform ios + */ canCancelContentTouches?: ?boolean, + /** + * When set, the scroll view will adjust the scroll position so that the first child that is + * currently visible and at or beyond `minIndexForVisible` will not change position. This is + * useful for lists that are loading content in both directions, e.g. a chat thread, where new + * messages coming in might otherwise cause the scroll position to jump. A value of 0 is common, + * but other values such as 1 can be used to skip loading spinners or other content that should + * not maintain position. + * + * The optional `autoscrollToTopThreshold` can be used to make the content automatically scroll + * to the top after making the adjustment if the user was within the threshold of the top before + * the adjustment was made. This is also useful for chat-like applications where you want to see + * new messages scroll into place, but not if the user has scrolled up a ways and it would be + * disruptive to scroll a bunch. + * + * Caveat 1: Reordering elements in the scrollview with this enabled will probably cause + * jumpiness and jank. It can be fixed, but there are currently no plans to do so. For now, + * don't re-order the content of any ScrollViews or Lists that use this feature. + * + * Caveat 2: This simply uses `contentOffset` and `frame.origin` in native code to compute + * visibility. Occlusion, transforms, and other complexity won't be taken into account as to + * whether content is "visible" or not. + * + * @platform ios + */ maintainVisibleContentPosition?: ?$ReadOnly<{| minIndexForVisible: number, autoscrollToTopThreshold?: ?number, |}>, + /** + * The maximum allowed zoom scale. The default value is 1.0. + * @platform ios + */ maximumZoomScale?: ?number, + /** + * The minimum allowed zoom scale. The default value is 1.0. + * @platform ios + */ minimumZoomScale?: ?number, + /** + * When true, ScrollView allows use of pinch gestures to zoom in and out. + * The default value is true. + * @platform ios + */ pinchGestureEnabled?: ?boolean, + /** + * This controls how often the scroll event will be fired while scrolling + * (as a time interval in ms). A lower number yields better accuracy for code + * that is tracking the scroll position, but can lead to scroll performance + * problems due to the volume of information being send over the bridge. + * You will not notice a difference between values set between 1-16 as the + * JS run loop is synced to the screen refresh rate. If you do not need precise + * scroll position tracking, set this value higher to limit the information + * being sent across the bridge. The default value is zero, which results in + * the scroll event being sent only once each time the view is scrolled. + * @platform ios + */ scrollEventThrottle?: ?number, + /** + * The amount by which the scroll view indicators are inset from the edges + * of the scroll view. This should normally be set to the same value as + * the `contentInset`. Defaults to `{0, 0, 0, 0}`. + * @platform ios + */ scrollIndicatorInsets?: ?EdgeInsetsProp, + /** + * When true, the scroll view scrolls to top when the status bar is tapped. + * The default value is true. + * @platform ios + */ scrollsToTop?: ?boolean, + /** + * When true, shows a horizontal scroll indicator. + * The default value is true. + */ showsHorizontalScrollIndicator?: ?boolean, + /** + * When `snapToInterval` is set, `snapToAlignment` will define the relationship + * of the snapping to the scroll view. + * + * - `'start'` (the default) will align the snap at the left (horizontal) or top (vertical) + * - `'center'` will align the snap in the center + * - `'end'` will align the snap at the right (horizontal) or bottom (vertical) + * + * @platform ios + */ snapToAlignment?: ?('start' | 'center' | 'end'), + /** + * The current scale of the scroll view content. The default value is 1.0. + * @platform ios + */ zoomScale?: ?number, + /** + * This property specifies how the safe area insets are used to modify the + * content area of the scroll view. The default value of this property is + * "never". Available on iOS 11 and later. + * @platform ios + */ contentInsetAdjustmentBehavior?: ?( | 'automatic' | 'scrollableAxes' | 'never' | 'always' ), + /** + * When true, ScrollView will emit updateChildFrames data in scroll events, + * otherwise will not compute or emit child frame data. This only exists + * to support legacy issues, `onLayout` should be used instead to retrieve + * frame data. + * The default value is false. + * @platform ios + */ DEPRECATED_sendUpdatedChildFrames?: ?boolean, |}>; type AndroidProps = $ReadOnly<{| + /** + * Enables nested scrolling for Android API level 21+. + * Nested scrolling is supported by default on iOS + * @platform android + */ nestedScrollEnabled?: ?boolean, + /** + * Sometimes a scrollview takes up more space than its content fills. When this is + * the case, this prop will fill the rest of the scrollview with a color to avoid setting + * a background and creating unnecessary overdraw. This is an advanced optimization + * that is not needed in the general case. + * @platform android + */ endFillColor?: ?ColorValue, + /** + * Tag used to log scroll performance on this scroll view. Will force + * momentum events to be turned on (see sendMomentumEvents). This doesn't do + * anything out of the box and you need to implement a custom native + * FpsListener for it to be useful. + * @platform android + */ scrollPerfTag?: ?string, + /** + * Used to override default value of overScroll mode. + * + * Possible values: + * + * - `'auto'` - Default value, allow a user to over-scroll + * this view only if the content is large enough to meaningfully scroll. + * - `'always'` - Always allow a user to over-scroll this view. + * - `'never'` - Never allow a user to over-scroll this view. + * + * @platform android + */ overScrollMode?: ?('auto' | 'always' | 'never'), |}>; type VRProps = $ReadOnly<{| - scrollBarThumbImage?: ?($ReadOnly<{||}> | number), + /** + * Optionally an image can be used for the scroll bar thumb. This will + * override the color. While the image is loading or the image fails to + * load the color will be used instead. Use an alpha of 0 in the color + * to avoid seeing it while the image is loading. + * + * - `uri` - a string representing the resource identifier for the image, which + * should be either a local file path or the name of a static image resource + * - `number` - Opaque type returned by something like + * `import IMAGE from './image.jpg'`. + * @platform vr + */ + scrollBarThumbImage?: ?($ReadOnly<{||}> | number), // Opaque type returned by import IMAGE from './image.jpg' |}>; export type Props = $ReadOnly<{| @@ -128,30 +342,153 @@ export type Props = $ReadOnly<{| ...AndroidProps, ...VRProps, + /** + * These styles will be applied to the scroll view content container which + * wraps all of the child views. Example: + * + * ``` + * return ( + * + * + * ); + * ... + * const styles = StyleSheet.create({ + * contentContainer: { + * paddingVertical: 20 + * } + * }); + * ``` + */ contentContainerStyle?: ?ViewStyleProp, + /** + * When true, the scroll view's children are arranged horizontally in a row + * instead of vertically in a column. The default value is false. + */ horizontal?: ?boolean, + /** + * If sticky headers should stick at the bottom instead of the top of the + * ScrollView. This is usually used with inverted ScrollViews. + */ invertStickyHeaders?: ?boolean, + /** + * Determines whether the keyboard gets dismissed in response to a drag. + * + * *Cross platform* + * + * - `'none'` (the default), drags do not dismiss the keyboard. + * - `'on-drag'`, the keyboard is dismissed when a drag begins. + * + * *iOS Only* + * + * - `'interactive'`, the keyboard is dismissed interactively with the drag and moves in + * synchrony with the touch; dragging upwards cancels the dismissal. + * On android this is not supported and it will have the same behavior as 'none'. + */ keyboardDismissMode?: ?( | 'none' // default | 'on-drag' // cross-platform | 'interactive' ), // ios only + /** + * Determines when the keyboard should stay visible after a tap. + * + * - `'never'` (the default), tapping outside of the focused text input when the keyboard + * is up dismisses the keyboard. When this happens, children won't receive the tap. + * - `'always'`, the keyboard will not dismiss automatically, and the scroll view will not + * catch taps, but children of the scroll view can catch taps. + * - `'handled'`, the keyboard will not dismiss automatically when the tap was handled by + * a children, (or captured by an ancestor). + * - `false`, deprecated, use 'never' instead + * - `true`, deprecated, use 'always' instead + */ // $FlowFixMe Issues found when typing ScrollView keyboardShouldPersistTaps?: ?('always' | 'never' | 'handled' | false | true), + /** + * Called when the momentum scroll starts (scroll which occurs as the ScrollView glides to a stop). + */ onMomentumScrollBegin?: ?Function, + /** + * Called when the momentum scroll ends (scroll which occurs as the ScrollView glides to a stop). + */ onMomentumScrollEnd?: ?Function, + /** + * Fires at most once per frame during scrolling. The frequency of the + * events can be controlled using the `scrollEventThrottle` prop. + */ onScroll?: ?Function, + /** + * Called when the user begins to drag the scroll view. + */ onScrollBeginDrag?: ?Function, + /** + * Called when the user stops dragging the scroll view and it either stops + * or begins to glide. + */ onScrollEndDrag?: ?Function, + /** + * Called when scrollable content view of the ScrollView changes. + * + * Handler function is passed the content width and content height as parameters: + * `(contentWidth, contentHeight)` + * + * It's implemented using onLayout handler attached to the content container + * which this ScrollView renders. + */ onContentSizeChange?: ?Function, onKeyboardDidShow?: (event: PressEvent) => void, + /** + * When true, the scroll view stops on multiples of the scroll view's size + * when scrolling. This can be used for horizontal pagination. The default + * value is false. + * + * Note: Vertical pagination is not supported on Android. + */ pagingEnabled?: ?boolean, + /** + * When false, the view cannot be scrolled via touch interaction. + * The default value is true. + * + * Note that the view can always be scrolled by calling `scrollTo`. + */ scrollEnabled?: ?boolean, + /** + * When true, shows a vertical scroll indicator. + * The default value is true. + */ showsVerticalScrollIndicator?: ?boolean, + /** + * An array of child indices determining which children get docked to the + * top of the screen when scrolling. For example, passing + * `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the + * top of the scroll view. This property is not supported in conjunction + * with `horizontal={true}`. + */ stickyHeaderIndices?: ?$ReadOnlyArray, + /** + * When set, causes the scroll view to stop at multiples of the value of + * `snapToInterval`. This can be used for paginating through children + * that have lengths smaller than the scroll view. Typically used in + * combination with `snapToAlignment` and `decelerationRate="fast"` on ios. + * Overrides less configurable `pagingEnabled` prop. + * + * Supported for horizontal scrollview on android. + */ snapToInterval?: ?number, + /** + * Experimental: When true, offscreen child views (whose `overflow` value is + * `hidden`) are removed from their native backing superview when offscreen. + * This can improve scrolling performance on long lists. The default value is + * true. + */ removeClippedSubviews?: ?boolean, + /** + * A RefreshControl component, used to provide pull-to-refresh + * functionality for the ScrollView. Only works for vertical ScrollViews + * (`horizontal` prop must be `false`). + * + * See [RefreshControl](docs/refreshcontrol.html). + */ refreshControl?: ?React.Element, style?: ?ViewStyleProp, children?: React.Node, @@ -196,163 +533,33 @@ const ScrollView = createReactClass({ displayName: 'ScrollView', propTypes: { ...ViewPropTypes, - /** - * Controls whether iOS should automatically adjust the content inset - * for scroll views that are placed behind a navigation bar or - * tab bar/ toolbar. The default value is true. - * @platform ios - */ automaticallyAdjustContentInsets: PropTypes.bool, - /** - * The amount by which the scroll view content is inset from the edges - * of the scroll view. Defaults to `{top: 0, left: 0, bottom: 0, right: 0}`. - * @platform ios - */ contentInset: EdgeInsetsPropType, - /** - * Used to manually set the starting scroll offset. - * The default value is `{x: 0, y: 0}`. - * @platform ios - */ contentOffset: PointPropType, - /** - * When true, the scroll view bounces when it reaches the end of the - * content if the content is larger then the scroll view along the axis of - * the scroll direction. When false, it disables all bouncing even if - * the `alwaysBounce*` props are true. The default value is true. - * @platform ios - */ bounces: PropTypes.bool, - /** - * When true, gestures can drive zoom past min/max and the zoom will animate - * to the min/max value at gesture end, otherwise the zoom will not exceed - * the limits. - * @platform ios - */ bouncesZoom: PropTypes.bool, - /** - * When true, the scroll view bounces horizontally when it reaches the end - * even if the content is smaller than the scroll view itself. The default - * value is true when `horizontal={true}` and false otherwise. - * @platform ios - */ alwaysBounceHorizontal: PropTypes.bool, - /** - * When true, the scroll view bounces vertically when it reaches the end - * even if the content is smaller than the scroll view itself. The default - * value is false when `horizontal={true}` and true otherwise. - * @platform ios - */ alwaysBounceVertical: PropTypes.bool, - /** - * When true, the scroll view automatically centers the content when the - * content is smaller than the scroll view bounds; when the content is - * larger than the scroll view, this property has no effect. The default - * value is false. - * @platform ios - */ centerContent: PropTypes.bool, - /** - * These styles will be applied to the scroll view content container which - * wraps all of the child views. Example: - * - * ``` - * return ( - * - * - * ); - * ... - * const styles = StyleSheet.create({ - * contentContainer: { - * paddingVertical: 20 - * } - * }); - * ``` - */ contentContainerStyle: StyleSheetPropType(ViewStylePropTypes), - /** - * A floating-point number that determines how quickly the scroll view - * decelerates after the user lifts their finger. You may also use string - * shortcuts `"normal"` and `"fast"` which match the underlying iOS settings - * for `UIScrollViewDecelerationRateNormal` and - * `UIScrollViewDecelerationRateFast` respectively. - * - * - `'normal'`: 0.998 (the default) - * - `'fast'`: 0.99 - * - * @platform ios - */ decelerationRate: PropTypes.oneOfType([ PropTypes.oneOf(['fast', 'normal']), PropTypes.number, ]), - /** - * When true, the scroll view's children are arranged horizontally in a row - * instead of vertically in a column. The default value is false. - */ horizontal: PropTypes.bool, - /** - * The style of the scroll indicators. - * - * - `'default'` (the default), same as `black`. - * - `'black'`, scroll indicator is black. This style is good against a light background. - * - `'white'`, scroll indicator is white. This style is good against a dark background. - * - * @platform ios - */ indicatorStyle: PropTypes.oneOf([ 'default', // default 'black', 'white', ]), - /** - * If sticky headers should stick at the bottom instead of the top of the - * ScrollView. This is usually used with inverted ScrollViews. - */ invertStickyHeaders: PropTypes.bool, - /** - * When true, the ScrollView will try to lock to only vertical or horizontal - * scrolling while dragging. The default value is false. - * @platform ios - */ directionalLockEnabled: PropTypes.bool, - /** - * When false, once tracking starts, won't try to drag if the touch moves. - * The default value is true. - * @platform ios - */ canCancelContentTouches: PropTypes.bool, - /** - * Determines whether the keyboard gets dismissed in response to a drag. - * - * *Cross platform* - * - * - `'none'` (the default), drags do not dismiss the keyboard. - * - `'on-drag'`, the keyboard is dismissed when a drag begins. - * - * *iOS Only* - * - * - `'interactive'`, the keyboard is dismissed interactively with the drag and moves in - * synchrony with the touch; dragging upwards cancels the dismissal. - * On android this is not supported and it will have the same behavior as 'none'. - */ keyboardDismissMode: PropTypes.oneOf([ 'none', // default 'on-drag', // Cross-platform 'interactive', // iOS-only ]), - /** - * Determines when the keyboard should stay visible after a tap. - * - * - `'never'` (the default), tapping outside of the focused text input when the keyboard - * is up dismisses the keyboard. When this happens, children won't receive the tap. - * - `'always'`, the keyboard will not dismiss automatically, and the scroll view will not - * catch taps, but children of the scroll view can catch taps. - * - `'handled'`, the keyboard will not dismiss automatically when the tap was handled by - * a children, (or captured by an ancestor). - * - `false`, deprecated, use 'never' instead - * - `true`, deprecated, use 'always' instead - */ keyboardShouldPersistTaps: PropTypes.oneOf([ 'always', 'never', @@ -360,257 +567,50 @@ const ScrollView = createReactClass({ false, true, ]), - /** - * When set, the scroll view will adjust the scroll position so that the first child that is - * currently visible and at or beyond `minIndexForVisible` will not change position. This is - * useful for lists that are loading content in both directions, e.g. a chat thread, where new - * messages coming in might otherwise cause the scroll position to jump. A value of 0 is common, - * but other values such as 1 can be used to skip loading spinners or other content that should - * not maintain position. - * - * The optional `autoscrollToTopThreshold` can be used to make the content automatically scroll - * to the top after making the adjustment if the user was within the threshold of the top before - * the adjustment was made. This is also useful for chat-like applications where you want to see - * new messages scroll into place, but not if the user has scrolled up a ways and it would be - * disruptive to scroll a bunch. - * - * Caveat 1: Reordering elements in the scrollview with this enabled will probably cause - * jumpiness and jank. It can be fixed, but there are currently no plans to do so. For now, - * don't re-order the content of any ScrollViews or Lists that use this feature. - * - * Caveat 2: This simply uses `contentOffset` and `frame.origin` in native code to compute - * visibility. Occlusion, transforms, and other complexity won't be taken into account as to - * whether content is "visible" or not. - * - * @platform ios - */ maintainVisibleContentPosition: PropTypes.shape({ minIndexForVisible: PropTypes.number.isRequired, autoscrollToTopThreshold: PropTypes.number, }), - /** - * The maximum allowed zoom scale. The default value is 1.0. - * @platform ios - */ maximumZoomScale: PropTypes.number, - /** - * The minimum allowed zoom scale. The default value is 1.0. - * @platform ios - */ minimumZoomScale: PropTypes.number, - /** - * Enables nested scrolling for Android API level 21+. - * Nested scrolling is supported by default on iOS - * @platform android - */ nestedScrollEnabled: PropTypes.bool, - /** - * Called when the momentum scroll starts (scroll which occurs as the ScrollView glides to a stop). - */ onMomentumScrollBegin: PropTypes.func, - /** - * Called when the momentum scroll ends (scroll which occurs as the ScrollView glides to a stop). - */ onMomentumScrollEnd: PropTypes.func, - /** - * Fires at most once per frame during scrolling. The frequency of the - * events can be controlled using the `scrollEventThrottle` prop. - */ onScroll: PropTypes.func, - /** - * Called when the user begins to drag the scroll view. - */ onScrollBeginDrag: PropTypes.func, - /** - * Called when the user stops dragging the scroll view and it either stops - * or begins to glide. - */ onScrollEndDrag: PropTypes.func, - /** - * Called when scrollable content view of the ScrollView changes. - * - * Handler function is passed the content width and content height as parameters: - * `(contentWidth, contentHeight)` - * - * It's implemented using onLayout handler attached to the content container - * which this ScrollView renders. - */ onContentSizeChange: PropTypes.func, - /** - * When true, the scroll view stops on multiples of the scroll view's size - * when scrolling. This can be used for horizontal pagination. The default - * value is false. - * - * Note: Vertical pagination is not supported on Android. - */ pagingEnabled: PropTypes.bool, - /** - * When true, ScrollView allows use of pinch gestures to zoom in and out. - * The default value is true. - * @platform ios - */ pinchGestureEnabled: PropTypes.bool, - /** - * When false, the view cannot be scrolled via touch interaction. - * The default value is true. - * - * Note that the view can always be scrolled by calling `scrollTo`. - */ scrollEnabled: PropTypes.bool, - /** - * This controls how often the scroll event will be fired while scrolling - * (as a time interval in ms). A lower number yields better accuracy for code - * that is tracking the scroll position, but can lead to scroll performance - * problems due to the volume of information being send over the bridge. - * You will not notice a difference between values set between 1-16 as the - * JS run loop is synced to the screen refresh rate. If you do not need precise - * scroll position tracking, set this value higher to limit the information - * being sent across the bridge. The default value is zero, which results in - * the scroll event being sent only once each time the view is scrolled. - * @platform ios - */ scrollEventThrottle: PropTypes.number, - /** - * The amount by which the scroll view indicators are inset from the edges - * of the scroll view. This should normally be set to the same value as - * the `contentInset`. Defaults to `{0, 0, 0, 0}`. - * @platform ios - */ scrollIndicatorInsets: EdgeInsetsPropType, - /** - * When true, the scroll view scrolls to top when the status bar is tapped. - * The default value is true. - * @platform ios - */ scrollsToTop: PropTypes.bool, - /** - * When true, shows a horizontal scroll indicator. - * The default value is true. - */ showsHorizontalScrollIndicator: PropTypes.bool, - /** - * When true, shows a vertical scroll indicator. - * The default value is true. - */ showsVerticalScrollIndicator: PropTypes.bool, - /** - * An array of child indices determining which children get docked to the - * top of the screen when scrolling. For example, passing - * `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the - * top of the scroll view. This property is not supported in conjunction - * with `horizontal={true}`. - */ stickyHeaderIndices: PropTypes.arrayOf(PropTypes.number), - /** - * When set, causes the scroll view to stop at multiples of the value of - * `snapToInterval`. This can be used for paginating through children - * that have lengths smaller than the scroll view. Typically used in - * combination with `snapToAlignment` and `decelerationRate="fast"` on ios. - * Overrides less configurable `pagingEnabled` prop. - * - * Supported for horizontal scrollview on android. - */ snapToInterval: PropTypes.number, - /** - * When `snapToInterval` is set, `snapToAlignment` will define the relationship - * of the snapping to the scroll view. - * - * - `'start'` (the default) will align the snap at the left (horizontal) or top (vertical) - * - `'center'` will align the snap in the center - * - `'end'` will align the snap at the right (horizontal) or bottom (vertical) - * - * @platform ios - */ snapToAlignment: PropTypes.oneOf([ 'start', // default 'center', 'end', ]), - /** - * Experimental: When true, offscreen child views (whose `overflow` value is - * `hidden`) are removed from their native backing superview when offscreen. - * This can improve scrolling performance on long lists. The default value is - * true. - */ removeClippedSubviews: PropTypes.bool, - /** - * The current scale of the scroll view content. The default value is 1.0. - * @platform ios - */ zoomScale: PropTypes.number, - /** - * This property specifies how the safe area insets are used to modify the - * content area of the scroll view. The default value of this property is - * "never". Available on iOS 11 and later. - * @platform ios - */ contentInsetAdjustmentBehavior: PropTypes.oneOf([ 'automatic', 'scrollableAxes', 'never', // default 'always', ]), - /** - * A RefreshControl component, used to provide pull-to-refresh - * functionality for the ScrollView. Only works for vertical ScrollViews - * (`horizontal` prop must be `false`). - * - * See [RefreshControl](docs/refreshcontrol.html). - */ refreshControl: PropTypes.element, - /** - * Sometimes a scrollview takes up more space than its content fills. When this is - * the case, this prop will fill the rest of the scrollview with a color to avoid setting - * a background and creating unnecessary overdraw. This is an advanced optimization - * that is not needed in the general case. - * @platform android - */ endFillColor: ColorPropType, - /** - * Tag used to log scroll performance on this scroll view. Will force - * momentum events to be turned on (see sendMomentumEvents). This doesn't do - * anything out of the box and you need to implement a custom native - * FpsListener for it to be useful. - * @platform android - */ scrollPerfTag: PropTypes.string, - /** - * Used to override default value of overScroll mode. - * - * Possible values: - * - * - `'auto'` - Default value, allow a user to over-scroll - * this view only if the content is large enough to meaningfully scroll. - * - `'always'` - Always allow a user to over-scroll this view. - * - `'never'` - Never allow a user to over-scroll this view. - * - * @platform android - */ overScrollMode: PropTypes.oneOf(['auto', 'always', 'never']), - /** - * When true, ScrollView will emit updateChildFrames data in scroll events, - * otherwise will not compute or emit child frame data. This only exists - * to support legacy issues, `onLayout` should be used instead to retrieve - * frame data. - * The default value is false. - * @platform ios - */ DEPRECATED_sendUpdatedChildFrames: PropTypes.bool, - /** - * Optionally an image can be used for the scroll bar thumb. This will - * override the color. While the image is loading or the image fails to - * load the color will be used instead. Use an alpha of 0 in the color - * to avoid seeing it while the image is loading. - * - * - `uri` - a string representing the resource identifier for the image, which - * should be either a local file path or the name of a static image resource - * - `number` - Opaque type returned by something like - * `import IMAGE from './image.jpg'`. - * @platform vr - */ scrollBarThumbImage: PropTypes.oneOfType([ PropTypes.shape({ uri: PropTypes.string, From f40de0e467815062c9bc61e645a835006b58c574 Mon Sep 17 00:00:00 2001 From: Spencer Ahrens Date: Thu, 5 Jul 2018 15:08:11 -0700 Subject: [PATCH 33/65] Fix some ScrollView lint Summary: $title Reviewed By: TheSavior Differential Revision: D8721334 fbshipit-source-id: 1aad238da9b8efdef6e2f3f1f2effd213fa9c3aa --- Libraries/Components/ScrollView/ScrollView.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index cec27cc67fff6c..6ad41c6b7cc36b 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -875,7 +875,7 @@ const ScrollView = createReactClass({ ScrollViewClass = RCTScrollView; ScrollContentContainerViewClass = RCTScrollContentView; warning( - !this.props.snapToInterval || !this.props.pagingEnabled, + this.props.snapToInterval != null || !this.props.pagingEnabled, 'snapToInterval is currently ignored when pagingEnabled is true.', ); } @@ -1028,7 +1028,7 @@ const ScrollView = createReactClass({ }; const {decelerationRate} = this.props; - if (decelerationRate) { + if (decelerationRate != null) { props.decelerationRate = processDecelerationRate(decelerationRate); } From 5b6ff01764502c88848867c7e04cab969da384a2 Mon Sep 17 00:00:00 2001 From: Spencer Ahrens Date: Thu, 5 Jul 2018 15:08:13 -0700 Subject: [PATCH 34/65] Remove ScrollView.propTypes Summary: We're unifying on flow types, and propTypes require non-trivial resources to initialize in aggregate. Some open source code might depend on extracting ScrollView.propTypes which will now fail. To fix, simplly remove these dependencies and use flow or typescript for verifying correct prop usage instead. Reviewed By: TheSavior Differential Revision: D8726371 fbshipit-source-id: 19e9540794db97a9e356615b544759a0753fd68c --- .../ScrollView/InternalScrollViewType.js | 3 +- Libraries/Components/ScrollView/ScrollView.js | 110 +------- Libraries/Components/WebView/WebView.ios.js | 5 +- Libraries/Lists/ListView/ListView.js | 239 ++++++++---------- 4 files changed, 112 insertions(+), 245 deletions(-) diff --git a/Libraries/Components/ScrollView/InternalScrollViewType.js b/Libraries/Components/ScrollView/InternalScrollViewType.js index a1d42bb46a6d29..471e25d9a5dab9 100644 --- a/Libraries/Components/ScrollView/InternalScrollViewType.js +++ b/Libraries/Components/ScrollView/InternalScrollViewType.js @@ -22,7 +22,8 @@ class InternalScrollViewType extends ReactNative.NativeComponent { ) {} flashScrollIndicators() {} - scrollToEnd(options?: {animated?: boolean}) {} + propTypes: empty; + scrollToEnd(options?: ?{animated?: boolean}) {} scrollWithoutAnimationTo(y: number = 0, x: number = 0) {} getScrollResponder(): any {} diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index 6ad41c6b7cc36b..7665527f5ad8c4 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -11,20 +11,13 @@ 'use strict'; const AnimatedImplementation = require('AnimatedImplementation'); -const ColorPropType = require('ColorPropType'); -const EdgeInsetsPropType = require('EdgeInsetsPropType'); const Platform = require('Platform'); -const PointPropType = require('PointPropType'); -const PropTypes = require('prop-types'); const React = require('React'); const ReactNative = require('ReactNative'); const ScrollResponder = require('ScrollResponder'); const ScrollViewStickyHeader = require('ScrollViewStickyHeader'); const StyleSheet = require('StyleSheet'); -const StyleSheetPropType = require('StyleSheetPropType'); const View = require('View'); -const ViewPropTypes = require('ViewPropTypes'); -const ViewStylePropTypes = require('ViewStylePropTypes'); const InternalScrollViewType = require('InternalScrollViewType'); const createReactClass = require('create-react-class'); @@ -531,95 +524,6 @@ export type Props = $ReadOnly<{| */ const ScrollView = createReactClass({ displayName: 'ScrollView', - propTypes: { - ...ViewPropTypes, - automaticallyAdjustContentInsets: PropTypes.bool, - contentInset: EdgeInsetsPropType, - contentOffset: PointPropType, - bounces: PropTypes.bool, - bouncesZoom: PropTypes.bool, - alwaysBounceHorizontal: PropTypes.bool, - alwaysBounceVertical: PropTypes.bool, - centerContent: PropTypes.bool, - contentContainerStyle: StyleSheetPropType(ViewStylePropTypes), - decelerationRate: PropTypes.oneOfType([ - PropTypes.oneOf(['fast', 'normal']), - PropTypes.number, - ]), - horizontal: PropTypes.bool, - indicatorStyle: PropTypes.oneOf([ - 'default', // default - 'black', - 'white', - ]), - invertStickyHeaders: PropTypes.bool, - directionalLockEnabled: PropTypes.bool, - canCancelContentTouches: PropTypes.bool, - keyboardDismissMode: PropTypes.oneOf([ - 'none', // default - 'on-drag', // Cross-platform - 'interactive', // iOS-only - ]), - keyboardShouldPersistTaps: PropTypes.oneOf([ - 'always', - 'never', - 'handled', - false, - true, - ]), - maintainVisibleContentPosition: PropTypes.shape({ - minIndexForVisible: PropTypes.number.isRequired, - autoscrollToTopThreshold: PropTypes.number, - }), - maximumZoomScale: PropTypes.number, - minimumZoomScale: PropTypes.number, - nestedScrollEnabled: PropTypes.bool, - onMomentumScrollBegin: PropTypes.func, - onMomentumScrollEnd: PropTypes.func, - onScroll: PropTypes.func, - onScrollBeginDrag: PropTypes.func, - onScrollEndDrag: PropTypes.func, - onContentSizeChange: PropTypes.func, - pagingEnabled: PropTypes.bool, - pinchGestureEnabled: PropTypes.bool, - scrollEnabled: PropTypes.bool, - scrollEventThrottle: PropTypes.number, - scrollIndicatorInsets: EdgeInsetsPropType, - scrollsToTop: PropTypes.bool, - showsHorizontalScrollIndicator: PropTypes.bool, - showsVerticalScrollIndicator: PropTypes.bool, - stickyHeaderIndices: PropTypes.arrayOf(PropTypes.number), - snapToInterval: PropTypes.number, - snapToAlignment: PropTypes.oneOf([ - 'start', // default - 'center', - 'end', - ]), - removeClippedSubviews: PropTypes.bool, - zoomScale: PropTypes.number, - contentInsetAdjustmentBehavior: PropTypes.oneOf([ - 'automatic', - 'scrollableAxes', - 'never', // default - 'always', - ]), - refreshControl: PropTypes.element, - - endFillColor: ColorPropType, - - scrollPerfTag: PropTypes.string, - - overScrollMode: PropTypes.oneOf(['auto', 'always', 'never']), - DEPRECATED_sendUpdatedChildFrames: PropTypes.bool, - scrollBarThumbImage: PropTypes.oneOfType([ - PropTypes.shape({ - uri: PropTypes.string, - }), - // Opaque type returned by import IMAGE from './image.jpg' - PropTypes.number, - ]), - }, - mixins: [ScrollResponder.Mixin], _scrollAnimatedValue: (new AnimatedImplementation.Value( @@ -637,11 +541,9 @@ const ScrollView = createReactClass({ UNSAFE_componentWillMount: function() { this._scrollAnimatedValue = new AnimatedImplementation.Value( - // $FlowFixMe this.props.contentOffset ? this.props.contentOffset.y : 0, ); this._scrollAnimatedValue.setOffset( - // $FlowFixMe this.props.contentInset ? this.props.contentInset.top : 0, ); this._stickyHeaderRefs = new Map(); @@ -784,7 +686,6 @@ const ScrollView = createReactClass({ if (!this.props.stickyHeaderIndices) { return; } - // $FlowFixMe Invalid prop usage const childArray = React.Children.toArray(this.props.children); if (key !== this._getKeyForIndex(index, childArray)) { // ignore stale layout update @@ -794,10 +695,8 @@ const ScrollView = createReactClass({ const layoutY = event.nativeEvent.layout.y; this._headerLayoutYs.set(key, layoutY); - // $FlowFixMe Invalid prop usage const indexOfIndex = this.props.stickyHeaderIndices.indexOf(index); const previousHeaderIndex = this.props.stickyHeaderIndices[ - // $FlowFixMe Invalid prop usage indexOfIndex - 1 ]; if (previousHeaderIndex != null) { @@ -918,16 +817,13 @@ const ScrollView = createReactClass({ const hasStickyHeaders = stickyHeaderIndices && stickyHeaderIndices.length > 0; const childArray = - // $FlowFixMe Invalid prop usage hasStickyHeaders && React.Children.toArray(this.props.children); const children = hasStickyHeaders ? // $FlowFixMe Invalid prop usage childArray.map((child, index) => { - // $FlowFixMe Invalid prop usage const indexOfIndex = child ? stickyHeaderIndices.indexOf(index) : -1; if (indexOfIndex > -1) { const key = child.key; - // $FlowFixMe Invalid prop usage const nextIndex = stickyHeaderIndices[indexOfIndex + 1]; return ( {Platform.isTV ? null : refreshControl} {contentContainer} @@ -1058,7 +952,6 @@ const ScrollView = createReactClass({ {contentContainer} , @@ -1066,7 +959,6 @@ const ScrollView = createReactClass({ } } return ( - // $FlowFixMe Invalid prop usage {contentContainer} diff --git a/Libraries/Components/WebView/WebView.ios.js b/Libraries/Components/WebView/WebView.ios.js index ca91bc3b877edc..56290df97bcf94 100644 --- a/Libraries/Components/WebView/WebView.ios.js +++ b/Libraries/Components/WebView/WebView.ios.js @@ -203,7 +203,10 @@ class WebView extends React.Component { * - fast: 0.99 (the default for iOS web view) * @platform ios */ - decelerationRate: ScrollView.propTypes.decelerationRate, + decelerationRate: PropTypes.oneOfType([ + PropTypes.oneOf(['fast', 'normal']), + PropTypes.number, + ]), /** * Boolean value that determines whether scrolling is enabled in the * `WebView`. The default value is `true`. diff --git a/Libraries/Lists/ListView/ListView.js b/Libraries/Lists/ListView/ListView.js index 10ab9aef3101e9..bed5dbda2e2f93 100644 --- a/Libraries/Lists/ListView/ListView.js +++ b/Libraries/Lists/ListView/ListView.js @@ -13,7 +13,6 @@ const InternalListViewType = require('InternalListViewType'); const ListViewDataSource = require('ListViewDataSource'); const Platform = require('Platform'); const React = require('React'); -const PropTypes = require('prop-types'); const ReactNative = require('ReactNative'); const RCTScrollViewManager = require('NativeModules').ScrollViewManager; const ScrollView = require('ScrollView'); @@ -37,22 +36,124 @@ const DEFAULT_SCROLL_CALLBACK_THROTTLE = 50; type Props = $ReadOnly<{| ...ScrollViewProps, + /** + * An instance of [ListView.DataSource](docs/listviewdatasource.html) to use + */ dataSource: ListViewDataSource, + /** + * (sectionID, rowID, adjacentRowHighlighted) => renderable + * + * If provided, a renderable component to be rendered as the separator + * below each row but not the last row if there is a section header below. + * Take a sectionID and rowID of the row above and whether its adjacent row + * is highlighted. + */ renderSeparator?: ?Function, + /** + * (rowData, sectionID, rowID, highlightRow) => renderable + * + * Takes a data entry from the data source and its ids and should return + * a renderable component to be rendered as the row. By default the data + * is exactly what was put into the data source, but it's also possible to + * provide custom extractors. ListView can be notified when a row is + * being highlighted by calling `highlightRow(sectionID, rowID)`. This + * sets a boolean value of adjacentRowHighlighted in renderSeparator, allowing you + * to control the separators above and below the highlighted row. The highlighted + * state of a row can be reset by calling highlightRow(null). + */ renderRow: Function, + /** + * How many rows to render on initial component mount. Use this to make + * it so that the first screen worth of data appears at one time instead of + * over the course of multiple frames. + */ initialListSize?: ?number, + /** + * Called when all rows have been rendered and the list has been scrolled + * to within onEndReachedThreshold of the bottom. The native scroll + * event is provided. + */ onEndReached?: ?Function, + /** + * Threshold in pixels (virtual, not physical) for calling onEndReached. + */ onEndReachedThreshold?: ?number, + /** + * Number of rows to render per event loop. Note: if your 'rows' are actually + * cells, i.e. they don't span the full width of your view (as in the + * ListViewGridLayoutExample), you should set the pageSize to be a multiple + * of the number of cells per row, otherwise you're likely to see gaps at + * the edge of the ListView as new pages are loaded. + */ pageSize?: ?number, + /** + * () => renderable + * + * The header and footer are always rendered (if these props are provided) + * on every render pass. If they are expensive to re-render, wrap them + * in StaticContainer or other mechanism as appropriate. Footer is always + * at the bottom of the list, and header at the top, on every render pass. + * In a horizontal ListView, the header is rendered on the left and the + * footer on the right. + */ renderFooter?: ?Function, renderHeader?: ?Function, + /** + * (sectionData, sectionID) => renderable + * + * If provided, a header is rendered for this section. + */ renderSectionHeader?: ?Function, + /** + * (props) => renderable + * + * A function that returns the scrollable component in which the list rows + * are rendered. Defaults to returning a ScrollView with the given props. + */ renderScrollComponent?: ?Function, + /** + * How early to start rendering rows before they come on screen, in + * pixels. + */ scrollRenderAheadDistance?: ?number, + /** + * (visibleRows, changedRows) => void + * + * Called when the set of visible rows changes. `visibleRows` maps + * { sectionID: { rowID: true }} for all the visible rows, and + * `changedRows` maps { sectionID: { rowID: true | false }} for the rows + * that have changed their visibility, with true indicating visible, and + * false indicating the view has moved out of view. + */ onChangeVisibleRows?: ?Function, + /** + * A performance optimization for improving scroll perf of + * large lists, used in conjunction with overflow: 'hidden' on the row + * containers. This is enabled by default. + */ removeClippedSubviews?: ?boolean, + /** + * Makes the sections headers sticky. The sticky behavior means that it + * will scroll with the content at the top of the section until it reaches + * the top of the screen, at which point it will stick to the top until it + * is pushed off the screen by the next section header. This property is + * not supported in conjunction with `horizontal={true}`. Only enabled by + * default on iOS because of typical platform standards. + */ stickySectionHeadersEnabled?: ?boolean, + /** + * An array of child indices determining which children get docked to the + * top of the screen when scrolling. For example, passing + * `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the + * top of the scroll view. This property is not supported in conjunction + * with `horizontal={true}`. + */ stickyHeaderIndices?: ?$ReadOnlyArray, + /** + * Flag indicating whether empty section headers should be rendered. In the future release + * empty section headers will be rendered by default, and the flag will be deprecated. + * If empty sections are not desired to be rendered their indices should be excluded from sectionID object. + */ enableEmptySections?: ?boolean, |}>; @@ -128,136 +229,6 @@ const ListView = createReactClass({ DataSource: ListViewDataSource, }, - /** - * You must provide a renderRow function. If you omit any of the other render - * functions, ListView will simply skip rendering them. - * - * - renderRow(rowData, sectionID, rowID, highlightRow); - * - renderSectionHeader(sectionData, sectionID); - */ - propTypes: { - ...ScrollView.propTypes, - /** - * An instance of [ListView.DataSource](docs/listviewdatasource.html) to use - */ - dataSource: PropTypes.instanceOf(ListViewDataSource).isRequired, - /** - * (sectionID, rowID, adjacentRowHighlighted) => renderable - * - * If provided, a renderable component to be rendered as the separator - * below each row but not the last row if there is a section header below. - * Take a sectionID and rowID of the row above and whether its adjacent row - * is highlighted. - */ - renderSeparator: PropTypes.func, - /** - * (rowData, sectionID, rowID, highlightRow) => renderable - * - * Takes a data entry from the data source and its ids and should return - * a renderable component to be rendered as the row. By default the data - * is exactly what was put into the data source, but it's also possible to - * provide custom extractors. ListView can be notified when a row is - * being highlighted by calling `highlightRow(sectionID, rowID)`. This - * sets a boolean value of adjacentRowHighlighted in renderSeparator, allowing you - * to control the separators above and below the highlighted row. The highlighted - * state of a row can be reset by calling highlightRow(null). - */ - renderRow: PropTypes.func.isRequired, - /** - * How many rows to render on initial component mount. Use this to make - * it so that the first screen worth of data appears at one time instead of - * over the course of multiple frames. - */ - initialListSize: PropTypes.number.isRequired, - /** - * Called when all rows have been rendered and the list has been scrolled - * to within onEndReachedThreshold of the bottom. The native scroll - * event is provided. - */ - onEndReached: PropTypes.func, - /** - * Threshold in pixels (virtual, not physical) for calling onEndReached. - */ - onEndReachedThreshold: PropTypes.number.isRequired, - /** - * Number of rows to render per event loop. Note: if your 'rows' are actually - * cells, i.e. they don't span the full width of your view (as in the - * ListViewGridLayoutExample), you should set the pageSize to be a multiple - * of the number of cells per row, otherwise you're likely to see gaps at - * the edge of the ListView as new pages are loaded. - */ - pageSize: PropTypes.number.isRequired, - /** - * () => renderable - * - * The header and footer are always rendered (if these props are provided) - * on every render pass. If they are expensive to re-render, wrap them - * in StaticContainer or other mechanism as appropriate. Footer is always - * at the bottom of the list, and header at the top, on every render pass. - * In a horizontal ListView, the header is rendered on the left and the - * footer on the right. - */ - renderFooter: PropTypes.func, - renderHeader: PropTypes.func, - /** - * (sectionData, sectionID) => renderable - * - * If provided, a header is rendered for this section. - */ - renderSectionHeader: PropTypes.func, - /** - * (props) => renderable - * - * A function that returns the scrollable component in which the list rows - * are rendered. Defaults to returning a ScrollView with the given props. - */ - renderScrollComponent: PropTypes.func.isRequired, - /** - * How early to start rendering rows before they come on screen, in - * pixels. - */ - scrollRenderAheadDistance: PropTypes.number.isRequired, - /** - * (visibleRows, changedRows) => void - * - * Called when the set of visible rows changes. `visibleRows` maps - * { sectionID: { rowID: true }} for all the visible rows, and - * `changedRows` maps { sectionID: { rowID: true | false }} for the rows - * that have changed their visibility, with true indicating visible, and - * false indicating the view has moved out of view. - */ - onChangeVisibleRows: PropTypes.func, - /** - * A performance optimization for improving scroll perf of - * large lists, used in conjunction with overflow: 'hidden' on the row - * containers. This is enabled by default. - */ - removeClippedSubviews: PropTypes.bool, - /** - * Makes the sections headers sticky. The sticky behavior means that it - * will scroll with the content at the top of the section until it reaches - * the top of the screen, at which point it will stick to the top until it - * is pushed off the screen by the next section header. This property is - * not supported in conjunction with `horizontal={true}`. Only enabled by - * default on iOS because of typical platform standards. - */ - stickySectionHeadersEnabled: PropTypes.bool, - /** - * An array of child indices determining which children get docked to the - * top of the screen when scrolling. For example, passing - * `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the - * top of the scroll view. This property is not supported in conjunction - * with `horizontal={true}`. - */ - stickyHeaderIndices: PropTypes.arrayOf(PropTypes.number).isRequired, - /** - * Flag indicating whether empty section headers should be rendered. In the future release - * empty section headers will be rendered by default, and the flag will be deprecated. - * If empty sections are not desired to be rendered their indices should be excluded from sectionID object. - */ - enableEmptySections: PropTypes.bool, - }, - /** * Exports some data, e.g. for perf investigations or analytics. */ @@ -296,7 +267,7 @@ const ListView = createReactClass({ * * See `ScrollView#scrollTo`. */ - scrollTo: function(...args: Array) { + scrollTo: function(...args: any) { if (this._scrollComponent && this._scrollComponent.scrollTo) { this._scrollComponent.scrollTo(...args); } @@ -312,7 +283,7 @@ const ListView = createReactClass({ * * See `ScrollView#scrollToEnd`. */ - scrollToEnd: function(options?: ?{animated?: ?boolean}) { + scrollToEnd: function(options?: ?{animated?: boolean}) { if (this._scrollComponent) { if (this._scrollComponent.scrollToEnd) { this._scrollComponent.scrollToEnd(options); @@ -366,7 +337,7 @@ const ListView = createReactClass({ }, getInnerViewNode: function() { - return this._scrollComponent.getInnerViewNode(); + return this._scrollComponent && this._scrollComponent.getInnerViewNode(); }, UNSAFE_componentWillMount: function() { From 46ffb106278425631c26049fa50b185e90789c9c Mon Sep 17 00:00:00 2001 From: Himabindu Gadupudi Date: Thu, 5 Jul 2018 15:08:41 -0700 Subject: [PATCH 35/65] Fix null source bug in Image view while accessing source's uri Summary: Fix null source bug in Image view while accessing source's uri Reviewed By: achen1 Differential Revision: D8739379 fbshipit-source-id: 0338b19135fa8af9ebe599cabbc9e321fb0906a5 --- Libraries/Image/Image.android.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index ec25a4ee1eeb04..99636169f4c9ef 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -212,7 +212,7 @@ let Image = ( ); } - if (!source.uri && !Array.isArray(source)) { + if (source && !source?.uri && !Array.isArray(source)) { return null; } From 0f4926598aa4c3532949572f8c7c7a20b568e47a Mon Sep 17 00:00:00 2001 From: Florian Schoellhammer Date: Thu, 5 Jul 2018 19:10:28 -0700 Subject: [PATCH 36/65] Back out "[react-native][PR] Remove the deprecated `isIPhoneX_deprecated` constant" Summary: Original commit changeset: 0b0b3a2d7b80 Reverting D8714400 which removed the `isIPhoneX_deprecated` flag, which is still widely used across the RN codebase https://fburl.com/biggrep/16jg5bzn Reviewed By: hramos Differential Revision: D8743401 fbshipit-source-id: cfc44bdd8019eda41e67ca573b20be417d121d12 --- RNTester/js/SafeAreaViewExample.js | 24 ++++++++++++++++++++++++ React/Modules/RCTDeviceInfo.m | 21 +++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/RNTester/js/SafeAreaViewExample.js b/RNTester/js/SafeAreaViewExample.js index 0af1d1f1f99ac8..927a26651a4f8f 100644 --- a/RNTester/js/SafeAreaViewExample.js +++ b/RNTester/js/SafeAreaViewExample.js @@ -64,6 +64,21 @@ class SafeAreaViewExample extends React.Component< } } +class IsIPhoneXExample extends React.Component<{}> { + render() { + return ( + + + Is this an iPhone X:{' '} + {DeviceInfo.isIPhoneX_deprecated + ? 'Yeah!' + : 'Nope. (Or `isIPhoneX_deprecated` was already removed.)'} + + + ); + } +} + exports.examples = [ { title: ' Example', @@ -71,6 +86,15 @@ exports.examples = [ 'SafeAreaView automatically applies paddings reflect the portion of the view that is not covered by other (special) ancestor views.', render: () => , }, + { + title: 'isIPhoneX_deprecated Example', + description: + '`DeviceInfo.isIPhoneX_deprecated` returns true only on iPhone X. ' + + 'Note: This prop is deprecated and will be removed right after June 01, 2018. ' + + 'Please use this only for a quick and temporary solution. ' + + 'Use instead.', + render: () => , + }, ]; var styles = StyleSheet.create({ diff --git a/React/Modules/RCTDeviceInfo.m b/React/Modules/RCTDeviceInfo.m index 7db187e3063d62..20e53d55af611f 100644 --- a/React/Modules/RCTDeviceInfo.m +++ b/React/Modules/RCTDeviceInfo.m @@ -51,6 +51,22 @@ - (void)setBridge:(RCTBridge *)bridge #endif } +static BOOL RCTIsIPhoneX() { + static BOOL isIPhoneX = NO; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + RCTAssertMainQueue(); + + isIPhoneX = CGSizeEqualToSize( + [UIScreen mainScreen].nativeBounds.size, + CGSizeMake(1125, 2436) + ); + }); + + return isIPhoneX; +} + static NSDictionary *RCTExportedDimensions(RCTBridge *bridge) { RCTAssertMainQueue(); @@ -86,6 +102,11 @@ - (void)invalidate { return @{ @"Dimensions": RCTExportedDimensions(_bridge), + // Note: + // This prop is deprecated and will be removed right after June 01, 2018. + // Please use this only for a quick and temporary solution. + // Use instead. + @"isIPhoneX_deprecated": @(RCTIsIPhoneX()), }; } From ac09261a4cb543ee30b38d1ebdc57046f2d7c406 Mon Sep 17 00:00:00 2001 From: Yan Soares Couto Date: Fri, 6 Jul 2018 04:16:19 -0700 Subject: [PATCH 37/65] downloadBundleFromURL with an optional starting Request.Builder Summary: This makes it possible to specify an optional Request.Builder when calling `downloadBundleFromURL` (the old method still works as usual). Reviewed By: davidaurelio Differential Revision: D8691303 fbshipit-source-id: 2fb2aecd3506355c6b3a72457a7bb9acfd03b18d --- .../react/devsupport/BundleDownloader.java | 23 ++++++++++++++----- .../react/devsupport/DevServerHelper.java | 10 ++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java index e64d02edbb974b..cf35c8a6ce9478 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java @@ -104,14 +104,25 @@ public BundleDownloader(OkHttpClient client) { } public void downloadBundleFromURL( - final DevBundleDownloadListener callback, - final File outputFile, - final String bundleURL, - final @Nullable BundleInfo bundleInfo, - final BundleDeltaClient.ClientType clientType) { + final DevBundleDownloadListener callback, + final File outputFile, + final String bundleURL, + final @Nullable BundleInfo bundleInfo, + final BundleDeltaClient.ClientType clientType) { + downloadBundleFromURL( + callback, outputFile, bundleURL, bundleInfo, clientType, new Request.Builder()); + } + + public void downloadBundleFromURL( + final DevBundleDownloadListener callback, + final File outputFile, + final String bundleURL, + final @Nullable BundleInfo bundleInfo, + final BundleDeltaClient.ClientType clientType, + Request.Builder requestBuilder) { final Request request = - new Request.Builder() + requestBuilder .url(formatBundleUrl(bundleURL, clientType)) // FIXME: there is a bug that makes MultipartStreamReader to never find the end of the // multipart message. This temporarily disables the multipart mode to work around it, diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java index bcf803aa6f971b..b1342c0555e7c1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java @@ -382,6 +382,16 @@ public void downloadBundleFromURL( mBundleDownloader.downloadBundleFromURL(callback, outputFile, bundleURL, bundleInfo, getDeltaClientType()); } + public void downloadBundleFromURL( + DevBundleDownloadListener callback, + File outputFile, + String bundleURL, + BundleDownloader.BundleInfo bundleInfo, + Request.Builder requestBuilder) { + mBundleDownloader.downloadBundleFromURL( + callback, outputFile, bundleURL, bundleInfo, getDeltaClientType(), requestBuilder); + } + private BundleDeltaClient.ClientType getDeltaClientType() { if (mSettings.isBundleDeltasCppEnabled()) { return BundleDeltaClient.ClientType.NATIVE; From 6292e2707ae1d26949dea66a202216857f279802 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Fri, 6 Jul 2018 09:12:56 -0700 Subject: [PATCH 38/65] Revert order of Remove Mount Item operations Summary: Revert the order of "remove mount items", to ensure views are removed from high index to low index. Reviewed By: shergin Differential Revision: D8742796 fbshipit-source-id: 6e04c39386d290bf3958ee83256d4fbe23e2c4ca --- ReactCommon/fabric/uimanager/Differentiator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReactCommon/fabric/uimanager/Differentiator.cpp b/ReactCommon/fabric/uimanager/Differentiator.cpp index 7a2c9a4f613a12..2d451b19fae6c9 100644 --- a/ReactCommon/fabric/uimanager/Differentiator.cpp +++ b/ReactCommon/fabric/uimanager/Differentiator.cpp @@ -152,7 +152,7 @@ static void calculateMutationInstructions( // All instructions in an optimal order: instructions.insert(instructions.end(), destructionDownwardInstructions.begin(), destructionDownwardInstructions.end()); instructions.insert(instructions.end(), replaceInstructions.begin(), replaceInstructions.end()); - instructions.insert(instructions.end(), removeInstructions.begin(), removeInstructions.end()); + instructions.insert(instructions.end(), removeInstructions.rbegin(), removeInstructions.rend()); instructions.insert(instructions.end(), createInstructions.begin(), createInstructions.end()); instructions.insert(instructions.end(), downwardInstructions.begin(), downwardInstructions.end()); instructions.insert(instructions.end(), insertInstructions.begin(), insertInstructions.end()); From 816d302e98cb14224f8bb2772299f87777a26ef8 Mon Sep 17 00:00:00 2001 From: Himabindu Gadupudi Date: Fri, 6 Jul 2018 12:23:52 -0700 Subject: [PATCH 39/65] Reverting image source null so the fix can go all once later Summary: Image source null which is in RC D8628053 has a bug which has a fix but didn't make to RC. Reverting so it can be cleaned up before going in RC. Reviewed By: achen1 Differential Revision: D8751687 fbshipit-source-id: e08b23a031455be23047880871813bdc840542dd --- Libraries/Image/Image.android.js | 9 ++++++--- .../react/views/image/ReactImageView.java | 15 +++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index 99636169f4c9ef..d0e685a5e64229 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -190,6 +190,9 @@ let Image = ( props.loadingIndicatorSource, ); + // As opposed to the ios version, here we render `null` when there is no source, source.uri + // or source array. + if (source && source.uri === '') { console.warn('source.uri should not be an empty string'); } @@ -212,13 +215,13 @@ let Image = ( ); } - if (source && !source?.uri && !Array.isArray(source)) { + if (!source || (!source.uri && !Array.isArray(source))) { return null; } let style; let sources; - if (source?.uri != null) { + if (source.uri) { const {width, height} = source; style = flattenStyle([{width, height}, styles.base, props.style]); sources = [{uri: source.uri}]; @@ -232,7 +235,7 @@ let Image = ( style, shouldNotifyLoadEvents: !!(onLoadStart || onLoad || onLoadEnd || onError), src: sources, - headers: source?.headers, + headers: source.headers, defaultSrc: defaultSource ? defaultSource.uri : null, loadingIndicatorSrc: loadingIndicatorSource ? loadingIndicatorSource.uri diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java index cf7a1580fcb0a3..91817b955b21ea 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java @@ -1,3 +1,4 @@ + /** * Copyright (c) 2015-present, Facebook, Inc. * @@ -70,9 +71,6 @@ public class ReactImageView extends GenericDraweeView { public static final int REMOTE_IMAGE_FADE_DURATION_MS = 300; - public static final String REMOTE_TRANSPARENT_BITMAP_URI = - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="; - private static float[] sComputedCornerRadii = new float[4]; /* @@ -341,10 +339,7 @@ public void setResizeMethod(ImageResizeMethod resizeMethod) { public void setSource(@Nullable ReadableArray sources) { mSources.clear(); - if (sources == null || sources.size() == 0) { - ImageSource imageSource = new ImageSource(getContext(), REMOTE_TRANSPARENT_BITMAP_URI); - mSources.add(imageSource); - } else { + if (sources != null && sources.size() != 0) { // Optimize for the case where we have just one uri, case in which we don't need the sizes if (sources.size() == 1) { ReadableMap source = sources.getMap(0); @@ -578,9 +573,9 @@ private boolean isTiled() { private void setSourceImage() { mImageSource = null; if (mSources.isEmpty()) { - ImageSource imageSource = new ImageSource(getContext(), REMOTE_TRANSPARENT_BITMAP_URI); - mSources.add(imageSource); - } else if (hasMultipleSources()) { + return; + } + if (hasMultipleSources()) { MultiSourceResult multiSource = MultiSourceHelper.getBestSourceForSize(getWidth(), getHeight(), mSources); mImageSource = multiSource.getBestResult(); From de09fd53bd41716142364e769e72b363bb3d3405 Mon Sep 17 00:00:00 2001 From: "Andrew Chen (Eng)" Date: Fri, 6 Jul 2018 12:31:09 -0700 Subject: [PATCH 40/65] Remove setJSEntryPoint from ReactRootView Summary: Doesn't look like it was ever used according to diffgrep https://our.intern.facebook.com/intern/diffgrep/?author=&expand_all=false&filepath=&matcher=strmatch&query=setJSEntryPoint&repo=fbsource&rev_type=all&result_size=3&search_order=2&source&target=added%20or%20removed axe is this okay? Differential Revision: D8730783 fbshipit-source-id: 1e6b9e8fbd50c108a24b592793060a5344f1d0b1 --- .../facebook/react/ReactInstanceManager.java | 2 +- .../com/facebook/react/ReactRootView.java | 38 +++---------------- 2 files changed, 6 insertions(+), 34 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index e5b3bae4412301..075ba03ea260c8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -1016,7 +1016,7 @@ private void attachRootViewToInstance( UIManager uiManagerModule = UIManagerHelper.getUIManager(mCurrentReactContext, rootView.getUIManagerType()); final int rootTag = uiManagerModule.addRootView(rootView); rootView.setRootViewTag(rootTag); - rootView.invokeJSEntryPoint(); + rootView.runApplication(); Systrace.beginAsyncSection( TRACE_TAG_REACT_JAVA_BRIDGE, "pre_rootView.onAttachedToReactInstance", diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java index 5f8ff1699f14e7..6e8a92f603683c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java @@ -7,9 +7,9 @@ package com.facebook.react; -import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE; -import static com.facebook.react.uimanager.common.UIManagerType.FABRIC; import static com.facebook.react.uimanager.common.UIManagerType.DEFAULT; +import static com.facebook.react.uimanager.common.UIManagerType.FABRIC; +import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE; import android.content.Context; import android.graphics.Canvas; @@ -50,9 +50,9 @@ import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.common.MeasureSpecProvider; import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout; +import com.facebook.react.uimanager.common.UIManagerType; import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.systrace.Systrace; -import com.facebook.react.uimanager.common.UIManagerType; import javax.annotation.Nullable; /** @@ -93,7 +93,6 @@ public interface ReactRootViewEventListener { private boolean mWasMeasured = false; private int mWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); private int mHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - private @Nullable Runnable mJSEntryPoint; private @UIManagerType int mUIManagerType = DEFAULT; public ReactRootView(Context context) { @@ -454,7 +453,7 @@ public void setAppProperties(@Nullable Bundle appProperties) { UiThreadUtil.assertOnUiThread(); mAppProperties = appProperties; if (getRootViewTag() != 0) { - invokeJSEntryPoint(); + runApplication(); } } @@ -462,34 +461,7 @@ public void setAppProperties(@Nullable Bundle appProperties) { * Calls into JS to start the React application. Can be called multiple times with the * same rootTag, which will re-render the application from the root. */ - /*package */ void invokeJSEntryPoint() { - if (mJSEntryPoint == null) { - defaultJSEntryPoint(); - } else { - mJSEntryPoint.run(); - } - } - - /** - * Set a custom entry point for invoking JS. By default, this is AppRegistry.runApplication - * @param jsEntryPoint - */ - public void setJSEntryPoint(Runnable jsEntryPoint) { - mJSEntryPoint = jsEntryPoint; - } - - public void invokeDefaultJSEntryPoint(@Nullable Bundle appProperties) { - UiThreadUtil.assertOnUiThread(); - if (appProperties != null) { - mAppProperties = appProperties; - } - defaultJSEntryPoint(); - } - - /** - * Calls the default entry point into JS which is AppRegistry.runApplication() - */ - private void defaultJSEntryPoint() { + /* package */ void runApplication() { Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactRootView.runApplication"); try { if (mReactInstanceManager == null || !mIsAttachedToInstance) { From e0e9c1549e9f4bf15060dd40764c838865fa593f Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Fri, 6 Jul 2018 14:34:38 -0700 Subject: [PATCH 41/65] Fabric: Improved prettyprinting of TreeMutationInstruction Summary: @public Quite trivial... and nice. Reviewed By: mdvacca Differential Revision: D8709951 fbshipit-source-id: 63e53eb85361fe3a0a0ecd7f21bf4c7db049d5bf --- .../uimanager/TreeMutationInstruction.cpp | 17 ++++++++++++++++- .../fabric/uimanager/TreeMutationInstruction.h | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/ReactCommon/fabric/uimanager/TreeMutationInstruction.cpp b/ReactCommon/fabric/uimanager/TreeMutationInstruction.cpp index c5f07453749c52..630e13202d1b53 100644 --- a/ReactCommon/fabric/uimanager/TreeMutationInstruction.cpp +++ b/ReactCommon/fabric/uimanager/TreeMutationInstruction.cpp @@ -150,6 +150,21 @@ std::string TreeMutationInstruction::getDebugName() const { } }; +std::string TreeMutationInstruction::getDebugValue() const { + switch (type_) { + case Creation: + return "[*" + folly::to(newChildNode_->getTag()) + "]"; + case Deletion: + return "[~" + folly::to(oldChildNode_->getTag()) + "]"; + case Insertion: + return "[" + folly::to(newChildNode_->getTag()) + "->" + folly::to(parentNode_->getTag()) + "]"; + case Removal: + return "[" + folly::to(oldChildNode_->getTag()) + "<~" + folly::to(parentNode_->getTag()) + "]"; + case Replacement: + return "[=" + folly::to(oldChildNode_->getTag()) + "]"; + } +}; + SharedDebugStringConvertibleList TreeMutationInstruction::getDebugProps() const { DebugStringConvertibleOptions options = {.maximumDepth = 1, .format = false}; @@ -176,7 +191,7 @@ SharedDebugStringConvertibleList TreeMutationInstruction::getDebugProps() const }; case Replacement: return SharedDebugStringConvertibleList { - std::make_shared("parentNode", parentNode_->getDebugDescription(options)), + std::make_shared("parentNode", parentNode_ ? parentNode_->getDebugDescription(options) : "nullptr"), std::make_shared("oldChildNode", oldChildNode_->getDebugDescription(options)), std::make_shared("newChildNode", newChildNode_->getDebugDescription(options)), std::make_shared("index", folly::to(index_)) diff --git a/ReactCommon/fabric/uimanager/TreeMutationInstruction.h b/ReactCommon/fabric/uimanager/TreeMutationInstruction.h index 920cd27f87cbd0..c27e6f71f35332 100644 --- a/ReactCommon/fabric/uimanager/TreeMutationInstruction.h +++ b/ReactCommon/fabric/uimanager/TreeMutationInstruction.h @@ -96,6 +96,7 @@ class TreeMutationInstruction: #pragma mark - DebugStringConvertible std::string getDebugName() const override; + std::string getDebugValue() const override; SharedDebugStringConvertibleList getDebugProps() const override; private: From e8ec1cb16ade2221666b2a2257c2e6892ac54b67 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Fri, 6 Jul 2018 14:34:40 -0700 Subject: [PATCH 42/65] Fabric: The diffing algorithm does not use source nodes anymore Summary: @public ... and it's as efficient as it was before. The previous version of the algorithm used `sourceNode` reference to know the previous state of the node to call the algorithm recursively. That wasn't so good because of several reasons: - It was fragile because we had two different sources of the truth of the "previous state of the tree": committed tree and source node pointer; - We had to store weak pointers to source nodes inside cloned nodes. That is not free in terms of performance; - The old approach introduced a constraint that all previously used and now reinserted nodes must be cloned to update source node (otherwise, the algorithm would regenerate instructions recreating already existing subtrees); - That cloning required access to `isSealed` flag which is supposed to be a debug-only thing (that actually affects performance and must be compile-out for release builds). The new approach compares nodes with same react tag and naturally cloning-artifacts resilient. Yes, the new approach uses a map of inserted nodes, but the previous one already had it (otherwise there is no way to tell which nodes should be "deleted"). And anyway, this is a very little map that exists for a very little period of time. Reviewed By: mdvacca Differential Revision: D8709953 fbshipit-source-id: 027abb326cf45f00f7bb0bbd7c4e612578268c66 --- .../fabric/uimanager/Differentiator.cpp | 65 ++++++++++++------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/ReactCommon/fabric/uimanager/Differentiator.cpp b/ReactCommon/fabric/uimanager/Differentiator.cpp index 2d451b19fae6c9..641a33a39ff011 100644 --- a/ReactCommon/fabric/uimanager/Differentiator.cpp +++ b/ReactCommon/fabric/uimanager/Differentiator.cpp @@ -30,7 +30,7 @@ static void calculateMutationInstructions( return; } - std::unordered_set insertedTags; + std::unordered_map insertedNodes; int index = 0; TreeMutationInstructionList createInstructions = {}; @@ -43,8 +43,8 @@ static void calculateMutationInstructions( // Stage 1: Collectings Updates for (index = 0; index < oldChildNodes->size() && index < newChildNodes->size(); index++) { - SharedShadowNode oldChildNode = oldChildNodes->at(index); - SharedShadowNode newChildNode = newChildNodes->at(index); + const auto &oldChildNode = oldChildNodes->at(index); + const auto &newChildNode = newChildNodes->at(index); if (oldChildNode->getTag() != newChildNode->getTag()) { // Totally different nodes, updating is impossible. @@ -74,7 +74,7 @@ static void calculateMutationInstructions( // Stage 2: Collectings Insertions for (; index < newChildNodes->size(); index++) { - SharedShadowNode newChildNode = newChildNodes->at(index); + const auto &newChildNode = newChildNodes->at(index); insertInstructions.push_back( TreeMutationInstruction::Insert( @@ -84,23 +84,12 @@ static void calculateMutationInstructions( ) ); - insertedTags.insert(newChildNode->getTag()); - - SharedShadowNode newChildSourceNode = newChildNode->getSourceNode(); - SharedShadowNodeSharedList newChildSourceChildNodes = - newChildSourceNode ? newChildSourceNode->getChildren() : ShadowNode::emptySharedShadowNodeSharedList(); - - calculateMutationInstructions( - *(newChildNode->getChildren()->size() ? &downwardInstructions : &destructionDownwardInstructions), - newChildNode, - newChildSourceChildNodes, - newChildNode->getChildren() - ); + insertedNodes.insert({newChildNode->getTag(), newChildNode}); } // Stage 3: Collectings Deletions and Removals for (index = lastIndexAfterFirstStage; index < oldChildNodes->size(); index++) { - SharedShadowNode oldChildNode = oldChildNodes->at(index); + const auto &oldChildNode = oldChildNodes->at(index); // Even if the old node was (re)inserted, we have to generate `remove` // instruction. @@ -112,12 +101,11 @@ static void calculateMutationInstructions( ) ); - auto numberOfRemovedTags = insertedTags.erase(oldChildNode->getTag()); - assert(numberOfRemovedTags == 0 || numberOfRemovedTags == 1); + const auto &it = insertedNodes.find(oldChildNode->getTag()); - if (numberOfRemovedTags == 0) { - // The old node was *not* (re)inserted, - // so we have to generate `delete` instruction and apply the algorithm + if (it == insertedNodes.end()) { + // The old node was *not* (re)inserted. + // We have to generate `delete` instruction and apply the algorithm // recursively. deleteInstructions.push_back( TreeMutationInstruction::Delete( @@ -125,19 +113,41 @@ static void calculateMutationInstructions( ) ); + // We also have to call the algorithm recursively to clean up the entire + // subtree starting from the removed node. calculateMutationInstructions( destructionDownwardInstructions, oldChildNode, oldChildNode->getChildren(), ShadowNode::emptySharedShadowNodeSharedList() ); + } else { + // The old node *was* (re)inserted. + // We have to call the algorithm recursively if the inserted node + // is *not* the same as removed one. + const auto &newChildNode = it->second; + if (newChildNode != oldChildNode) { + calculateMutationInstructions( + *(newChildNode->getChildren()->size() ? &downwardInstructions : &destructionDownwardInstructions), + newChildNode, + oldChildNode->getChildren(), + newChildNode->getChildren() + ); + } + + // In any case we have to remove the node from `insertedNodes` as + // indication that the node was actually removed (which means that + // the node existed before), hence we don't have to generate + // `create` instruction. + insertedNodes.erase(it); } } // Stage 4: Collectings Creations for (index = lastIndexAfterFirstStage; index < newChildNodes->size(); index++) { - SharedShadowNode newChildNode = newChildNodes->at(index); - if (insertedTags.find(newChildNode->getTag()) == insertedTags.end()) { + const auto &newChildNode = newChildNodes->at(index); + + if (insertedNodes.find(newChildNode->getTag()) == insertedNodes.end()) { // The new node was (re)inserted, so there is no need to create it. continue; } @@ -147,6 +157,13 @@ static void calculateMutationInstructions( newChildNode ) ); + + calculateMutationInstructions( + downwardInstructions, + newChildNode, + ShadowNode::emptySharedShadowNodeSharedList(), + newChildNode->getChildren() + ); } // All instructions in an optimal order: From 604bcfa4a83396c402ba8beaa13f40d05d6e9f5c Mon Sep 17 00:00:00 2001 From: Konstantin Raev Date: Fri, 6 Jul 2018 19:21:16 -0700 Subject: [PATCH 43/65] =?UTF-8?q?Revert=20D8683555:=20[react-native][PR]?= =?UTF-8?q?=20fix:=20account=20for=20`ListHeaderComponent`=20length=20when?= =?UTF-8?q?=20calculating=20offset=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Differential Revision: D8683555 Original commit changeset: 05df7b79c16e fbshipit-source-id: 6deb14b99fe04e67e264455ff92a5d8c1c2dd406 --- Libraries/Lists/VirtualizedList.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 47b6b5f083e1d7..56364823f06d49 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -1217,9 +1217,7 @@ class VirtualizedList extends React.PureComponent { } _selectOffset(metrics: $ReadOnly<{x: number, y: number}>): number { - return ( - (!this.props.horizontal ? metrics.y : metrics.x) - this._headerLength - ); + return !this.props.horizontal ? metrics.y : metrics.x; } _maybeCallOnEndReached() { From b99609e9d242e5aaa2b0f14c08e8805b8903bc83 Mon Sep 17 00:00:00 2001 From: Wen-Chien Chen Date: Sun, 8 Jul 2018 00:18:31 -0700 Subject: [PATCH 44/65] Fix ScrollView logspew Summary: There was an inverted expression leading to logspew. Fix this. Reviewed By: TheSavior Differential Revision: D8758023 fbshipit-source-id: 7a83c68db6c95f2b5db6dcc7d7780fc66321b49e --- Libraries/Components/ScrollView/ScrollView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index 7665527f5ad8c4..27dd34f49f75fd 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -774,7 +774,7 @@ const ScrollView = createReactClass({ ScrollViewClass = RCTScrollView; ScrollContentContainerViewClass = RCTScrollContentView; warning( - this.props.snapToInterval != null || !this.props.pagingEnabled, + this.props.snapToInterval == null || !this.props.pagingEnabled, 'snapToInterval is currently ignored when pagingEnabled is true.', ); } From 781f1816101507b45bb1d93a4393c07aa7b24d26 Mon Sep 17 00:00:00 2001 From: Wenting Hu Date: Sun, 8 Jul 2018 13:06:38 -0700 Subject: [PATCH 45/65] Back out "[react-native][PR] Remove the deprecated `isIPhoneX_deprecated` constant" Summary: Original commit changeset: 0b0b3a2d7b80 This constant is still in use at Facebook. Its removal has been pushed to sometime in the future. Reviewed By: mdvacca Differential Revision: D8721213 fbshipit-source-id: d1197c96804e4d2dc96be27421e5248a2394cdac --- RNTester/js/SafeAreaViewExample.js | 4 ++-- React/Modules/RCTDeviceInfo.m | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/RNTester/js/SafeAreaViewExample.js b/RNTester/js/SafeAreaViewExample.js index 927a26651a4f8f..be7ce97fa3b6aa 100644 --- a/RNTester/js/SafeAreaViewExample.js +++ b/RNTester/js/SafeAreaViewExample.js @@ -90,8 +90,8 @@ exports.examples = [ title: 'isIPhoneX_deprecated Example', description: '`DeviceInfo.isIPhoneX_deprecated` returns true only on iPhone X. ' + - 'Note: This prop is deprecated and will be removed right after June 01, 2018. ' + - 'Please use this only for a quick and temporary solution. ' + + 'Note: This prop is deprecated and will be removed in a future ' + + 'release. Please use this only for a quick and temporary solution. ' + 'Use instead.', render: () => , }, diff --git a/React/Modules/RCTDeviceInfo.m b/React/Modules/RCTDeviceInfo.m index 20e53d55af611f..72803f3e121d50 100644 --- a/React/Modules/RCTDeviceInfo.m +++ b/React/Modules/RCTDeviceInfo.m @@ -103,7 +103,7 @@ - (void)invalidate return @{ @"Dimensions": RCTExportedDimensions(_bridge), // Note: - // This prop is deprecated and will be removed right after June 01, 2018. + // This prop is deprecated and will be removed in a future release. // Please use this only for a quick and temporary solution. // Use instead. @"isIPhoneX_deprecated": @(RCTIsIPhoneX()), From fc94f959625043d83830cca5db3456bd89e99536 Mon Sep 17 00:00:00 2001 From: Yan Soares Couto Date: Mon, 9 Jul 2018 03:21:05 -0700 Subject: [PATCH 46/65] Enable RCTDevLoadingView with another flag Reviewed By: javache Differential Revision: D8723591 fbshipit-source-id: 196cecd73ba0e1a1d34ec9a775cf03a25f352401 --- React/DevSupport/RCTDevLoadingView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/React/DevSupport/RCTDevLoadingView.m b/React/DevSupport/RCTDevLoadingView.m index 6d67c9d80a6e0d..15480ad6a69391 100644 --- a/React/DevSupport/RCTDevLoadingView.m +++ b/React/DevSupport/RCTDevLoadingView.m @@ -14,7 +14,7 @@ #import "RCTModalHostViewController.h" #import "RCTUtils.h" -#if RCT_DEV +#if RCT_DEV | RCT_ENABLE_LOADING_VIEW static BOOL isEnabled = YES; From eac34e30215d88b5fe9056f9678275b894032636 Mon Sep 17 00:00:00 2001 From: Gabe Levi Date: Mon, 9 Jul 2018 08:06:58 -0700 Subject: [PATCH 47/65] Flow v0.76.0 Summary: No new errors in this version. Just removed a bunch of unused suppressions Reviewed By: TheSavior Differential Revision: D8754160 fbshipit-source-id: 2f02240b6d65edecba5d9ed603c7703462547a7f --- .flowconfig | 2 +- Libraries/Components/ScrollView/ScrollView.js | 2 +- Libraries/Utilities/PerformanceLogger.js | 3 --- local-cli/server/runServer.js | 2 +- local-cli/templates/HelloWorld/_flowconfig | 2 +- package.json | 2 +- 6 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.flowconfig b/.flowconfig index a2afa6b9319997..7ba7b7ccf41d93 100644 --- a/.flowconfig +++ b/.flowconfig @@ -97,4 +97,4 @@ untyped-import untyped-type-import [version] -^0.75.0 +^0.76.0 diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index 27dd34f49f75fd..9f0688e87489f3 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -394,7 +394,7 @@ export type Props = $ReadOnly<{| * - `false`, deprecated, use 'never' instead * - `true`, deprecated, use 'always' instead */ - // $FlowFixMe Issues found when typing ScrollView + // $FlowFixMe(site=react_native_fb) Issues found when typing ScrollView keyboardShouldPersistTaps?: ?('always' | 'never' | 'handled' | false | true), /** * Called when the momentum scroll starts (scroll which occurs as the ScrollView glides to a stop). diff --git a/Libraries/Utilities/PerformanceLogger.js b/Libraries/Utilities/PerformanceLogger.js index 203e2412587932..8bd1cc638a2b21 100644 --- a/Libraries/Utilities/PerformanceLogger.js +++ b/Libraries/Utilities/PerformanceLogger.js @@ -13,9 +13,6 @@ const Systrace = require('Systrace'); const infoLog = require('infoLog'); const performanceNow = - /* $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 run Flow. */ global.nativeQPLTimestamp || global.nativePerformanceNow || require('fbjs/lib/performanceNow'); diff --git a/local-cli/server/runServer.js b/local-cli/server/runServer.js index 7dfaaed72a18ff..7f660bde298f31 100644 --- a/local-cli/server/runServer.js +++ b/local-cli/server/runServer.js @@ -80,7 +80,7 @@ async function runServer(args: Args, config: ConfigT) { // // For more info: https://github.com/nodejs/node/issues/13391 // - // $FlowFixMe + // $FlowFixMe (site=react_native_fb) serverInstance.keepAliveTimeout = 30000; } diff --git a/local-cli/templates/HelloWorld/_flowconfig b/local-cli/templates/HelloWorld/_flowconfig index 3c0adb56630031..db178bd0c093f8 100644 --- a/local-cli/templates/HelloWorld/_flowconfig +++ b/local-cli/templates/HelloWorld/_flowconfig @@ -64,4 +64,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError [version] -^0.75.0 +^0.76.0 diff --git a/package.json b/package.json index ef7f978438e24d..5c9be70aeb2379 100644 --- a/package.json +++ b/package.json @@ -212,7 +212,7 @@ "eslint-plugin-prettier": "2.6.0", "eslint-plugin-react": "7.8.2", "eslint-plugin-react-native": "^3.2.1", - "flow-bin": "^0.75.0", + "flow-bin": "^0.76.0", "jest": "23.2.0", "jest-junit": "5.1.0", "prettier": "1.13.6", From abf1188de225e4b7d36ecbad316af92ca29c85c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Mon, 9 Jul 2018 09:13:06 -0700 Subject: [PATCH 48/65] Upgraded babel-eslint to v9.0.0-beta.2 with better support for Flow Summary: Upgraded the library to fix an error in Babel causing wrong unused variable errors. Differential Revision: D8765952 fbshipit-source-id: 352d1bb50ada76caed247bf9aa4521eff2d510e9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5c9be70aeb2379..3c408150a84b90 100644 --- a/package.json +++ b/package.json @@ -201,7 +201,7 @@ "devDependencies": { "@babel/core": "7.0.0-beta.47", "async": "^2.4.0", - "babel-eslint": "8.2.1", + "babel-eslint": "9.0.0-beta.2", "babel-generator": "^6.26.0", "eslint": "5.0.1", "eslint-config-fb-strict": "22.1.0", From 5aa040dfb780c09a6efa5d3072232dea775d432f Mon Sep 17 00:00:00 2001 From: Ziqi Chen Date: Mon, 9 Jul 2018 10:50:53 -0700 Subject: [PATCH 49/65] added property accessibility IgnoresInvertColors to proptypes Summary: Added property accessibilityIgnoresInvertColors to ViewPropTypes. Reviewed By: PeteTheHeat Differential Revision: D8735443 fbshipit-source-id: ac526779b7f92ceab074de75a2bf61752e7e90c6 --- Libraries/Components/View/ViewPropTypes.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index 0f7dea210694ce..5cfcd45f24b9a6 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -87,6 +87,7 @@ export type ViewProps = $ReadOnly<{| accessibilityComponentType?: AccessibilityComponentType, accessibilityLiveRegion?: 'none' | 'polite' | 'assertive', importantForAccessibility?: 'auto' | 'yes' | 'no' | 'no-hide-descendants', + accessibilityIgnoresInvertColors?: boolean, accessibilityTraits?: AccessibilityTrait | Array, accessibilityViewIsModal?: boolean, accessibilityElementsHidden?: boolean, From 0f2f0cad41f632d1dbb0c676d5edea5db62eb01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Mon, 9 Jul 2018 12:31:17 -0700 Subject: [PATCH 50/65] Upgrade ESLint to 5.1.0 Summary: This release fixes several issues. Most importantly for us: - https://github.com/eslint/eslint/issues/10560 - https://github.com/eslint/eslint/issues/10512 Differential Revision: D8767118 fbshipit-source-id: 2048829d780b5f0f2f607114f803c8d0c3e02ca7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3c408150a84b90..7b8fd82f628b4a 100644 --- a/package.json +++ b/package.json @@ -203,7 +203,7 @@ "async": "^2.4.0", "babel-eslint": "9.0.0-beta.2", "babel-generator": "^6.26.0", - "eslint": "5.0.1", + "eslint": "5.1.0", "eslint-config-fb-strict": "22.1.0", "eslint-config-fbjs": "2.0.1", "eslint-plugin-eslint-comments": "^3.0.1", From a69c3303474e08eb0a3b428d261bb38714db1378 Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Tue, 10 Jul 2018 03:55:58 -0700 Subject: [PATCH 51/65] Bump metro@0.42.0 Summary: @public [skip-ci] Differential Revision: D8773719 fbshipit-source-id: d05f7060a45751ed14dc5479ff1135f35a38c432 --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 7b8fd82f628b4a..79ed118dda488b 100644 --- a/package.json +++ b/package.json @@ -167,10 +167,10 @@ "graceful-fs": "^4.1.3", "inquirer": "^3.0.6", "lodash": "^4.17.5", - "metro": "^0.40.1", - "metro-babel-register": "^0.40.1", - "metro-core": "^0.40.1", - "metro-memory-fs": "^0.40.1", + "metro": "^0.42.0", + "metro-babel-register": "^0.42.0", + "metro-core": "^0.42.0", + "metro-memory-fs": "^0.42.0", "mime": "^1.3.4", "minimist": "^1.2.0", "mkdirp": "^0.5.1", From 1bb2bead8bef850037c8b72209cd72a442572821 Mon Sep 17 00:00:00 2001 From: Noam Schachter Date: Tue, 10 Jul 2018 08:19:01 -0700 Subject: [PATCH 52/65] Fixing Crush on SDK 15 (ICS) on ReactTextInputLocalData Summary: We had a crush reprot from Loadstone (manual tests) for RN standalone app on ICS, see: https://our.intern.facebook.com/intern/tasks/view_inline_attachment/?attachment_id=2296063267087587&fbid=314266832445741 Seems like we are using TextView.getMinLines and TextView.getMaxLines - both added in SDK 16, witought a propert guard. see: https://developer.android.com/reference/android/widget/TextView#getMinLines() https://developer.android.com/reference/android/widget/TextView#getMaxLines() Reviewed By: shergin Differential Revision: D8763942 fbshipit-source-id: a56a6fc3e575b8ea97ddab983561df878b2f341c --- .../react/views/textinput/ReactTextInputLocalData.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputLocalData.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputLocalData.java index 3940e4f7c62043..ce7b2725bb690b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputLocalData.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputLocalData.java @@ -25,10 +25,16 @@ public final class ReactTextInputLocalData { public ReactTextInputLocalData(EditText editText) { mText = new SpannableStringBuilder(editText.getText()); mTextSize = editText.getTextSize(); - mMinLines = editText.getMinLines(); - mMaxLines = editText.getMaxLines(); mInputType = editText.getInputType(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + mMinLines = editText.getMinLines(); + mMaxLines = editText.getMaxLines(); + } else { + mMinLines = 1; + mMaxLines = 1; + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { mBreakStrategy = editText.getBreakStrategy(); } else { From 1ee6396c566f038a1081796c77a1ecad6a24cef6 Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Tue, 10 Jul 2018 08:50:42 -0700 Subject: [PATCH 53/65] Bump metro@0.42.1 Summary: @public [skip-ci] Reviewed By: mjesun Differential Revision: D8781445 fbshipit-source-id: 32f2cbfeadbd2fb763078a046b779a16359c8bbd --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 79ed118dda488b..acd729198cbb08 100644 --- a/package.json +++ b/package.json @@ -167,10 +167,10 @@ "graceful-fs": "^4.1.3", "inquirer": "^3.0.6", "lodash": "^4.17.5", - "metro": "^0.42.0", - "metro-babel-register": "^0.42.0", - "metro-core": "^0.42.0", - "metro-memory-fs": "^0.42.0", + "metro": "^0.42.1", + "metro-babel-register": "^0.42.1", + "metro-core": "^0.42.1", + "metro-memory-fs": "^0.42.1", "mime": "^1.3.4", "minimist": "^1.2.0", "mkdirp": "^0.5.1", From ef3d8b23c35246d4e088d532c41723e06b688f1b Mon Sep 17 00:00:00 2001 From: Ziqi Chen Date: Tue, 10 Jul 2018 11:14:51 -0700 Subject: [PATCH 54/65] Unreverting Marketplace change for Inverted Color Ignorance Summary: Un-reverted Diff D8528543 Context: Diff itself is the exact same as the old one. There's actually nothing wrong with this diff, it was originally reverted because of iOS compatibility issue on exposing `accessibilityIgnoresInvertcolors` API to javascript, which has now been handled and fixed in this D8599698. This means I can now set the property `accessibilityIgnoresInvertColors` -------------------------- Added Smart Inversion Compatibility to Marketplace on iOS so that photos don't appear inverted Added Property to View for Ignoring Color Inversion Applied Property to Images on marketplace. **Note: Android doesn't support smart inversion Reviewed By: PeteTheHeat Differential Revision: D8737594 fbshipit-source-id: 86080d45dec773ede4d3828fcda8870f546df691 --- Libraries/Image/ImageBackground.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Libraries/Image/ImageBackground.js b/Libraries/Image/ImageBackground.js index 7b86d9c5f5298d..a128880a17807c 100644 --- a/Libraries/Image/ImageBackground.js +++ b/Libraries/Image/ImageBackground.js @@ -60,7 +60,10 @@ class ImageBackground extends React.Component<$FlowFixMeProps> { const {children, style, imageStyle, imageRef, ...props} = this.props; return ( - + Date: Tue, 10 Jul 2018 12:09:02 -0700 Subject: [PATCH 55/65] added accessibilityRole Prop, added functionality support for role on android Summary: Added a new property to View for Accessibility called `accessibilityRole`. This property merges functionality of existing properties: `accessibilityTraits` (iOS) and `accessibilityComponentType` (android). Currently, nine values are supported with equivalent behavior as `accessibilityTraits` (iOS) when `accessibilityRole` is set on iOS Voiceover and Android TalkBack ``` | 'none' | 'button' | 'link' | 'search' | 'image' | 'keyboardkey' | 'text' | 'adjustable' | 'tabbar' ``` They currently support similar behavior on talkback on Android and voice over on iOS Does not break functionality of existing properties, but have not tested for behavior of setting both this one and the old one. * iOS - I added a property accessibilityRoles, and basically remapped it to the same thing as accessibilityTraits. I also added in enum mappings for keyboardkey and tabbar. * Android - Also added a property accessibilityRoles, from the Android side. For the underlying native functionality, I built a helper class that is based off of AccessibilityRolesUtil.java from the accessibility team. Biggest changes made are that I defined my own enums if needed, and also set some properties to match the functionality of iOS Accessibility Traits. I also handled the logic for switch/case statements of setting roles for the android side on this file. Also, I currently haven't localized strings for setRoleDescription, but plan to. * Javascript - I added a view property accessibilityRoles in ViewPropTypes. Reviewed By: blavalla Differential Revision: D8756225 fbshipit-source-id: e03eec40cce86042551764f433e1defe7ee41b35 --- .../Components/View/ViewAccessibility.js | 16 +++ Libraries/Components/View/ViewPropTypes.js | 9 ++ React/Views/RCTViewManager.m | 3 + .../uimanager/AccessibilityRoleUtil.java | 121 ++++++++++++++++++ .../react/uimanager/BaseViewManager.java | 6 + 5 files changed, 155 insertions(+) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/AccessibilityRoleUtil.java diff --git a/Libraries/Components/View/ViewAccessibility.js b/Libraries/Components/View/ViewAccessibility.js index 4a9ebc172a13c9..a12528fad5fc76 100644 --- a/Libraries/Components/View/ViewAccessibility.js +++ b/Libraries/Components/View/ViewAccessibility.js @@ -39,6 +39,14 @@ export type AccessibilityComponentType = | 'radiobutton_checked' | 'radiobutton_unchecked'; +export type AccessibilityRole = + | 'none' + | 'button' + | 'image' + | 'keyboardkey' + | 'text' + | 'tabbar'; + module.exports = { AccessibilityTraits: [ 'none', @@ -65,4 +73,12 @@ module.exports = { 'radiobutton_checked', 'radiobutton_unchecked', ], + AccessibilityRoles: [ + 'none', + 'button', + 'image', + 'keyboardkey', + 'text', + 'tabbar', + ], }; diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index 5cfcd45f24b9a6..73a39cf255fcbf 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -20,11 +20,13 @@ const ViewStylePropTypes = require('ViewStylePropTypes'); const { AccessibilityComponentTypes, AccessibilityTraits, + AccessibilityRoles, } = require('ViewAccessibility'); import type { AccessibilityComponentType, AccessibilityTrait, + AccessibilityRole, } from 'ViewAccessibility'; import type {EdgeInsetsProp} from 'EdgeInsetsPropType'; import type {TVViewProps} from 'TVViewPropTypes'; @@ -89,6 +91,7 @@ export type ViewProps = $ReadOnly<{| importantForAccessibility?: 'auto' | 'yes' | 'no' | 'no-hide-descendants', accessibilityIgnoresInvertColors?: boolean, accessibilityTraits?: AccessibilityTrait | Array, + accessibilityRole?: AccessibilityRole, accessibilityViewIsModal?: boolean, accessibilityElementsHidden?: boolean, children?: ?React.Node, @@ -139,6 +142,12 @@ module.exports = { */ accessibilityComponentType: PropTypes.oneOf(AccessibilityComponentTypes), + /** + * Indicates to accessibility services to treat UI component like a + * native one. Merging accessibilityComponentType and accessibilityTraits. + */ + accessibilityRole: PropTypes.oneOf(AccessibilityRoles), + /** * Indicates to accessibility services whether the user should be notified * when this view changes. Works for Android API >= 19 only. diff --git a/React/Views/RCTViewManager.m b/React/Views/RCTViewManager.m index ede084d1a5fb8b..4443f525a6abf3 100644 --- a/React/Views/RCTViewManager.m +++ b/React/Views/RCTViewManager.m @@ -33,9 +33,11 @@ @implementation RCTConvert(UIAccessibilityTraits) @"header": @(UIAccessibilityTraitHeader), @"search": @(UIAccessibilityTraitSearchField), @"image": @(UIAccessibilityTraitImage), + @"tabbar": @(UIAccessibilityTraitTabBar), @"selected": @(UIAccessibilityTraitSelected), @"plays": @(UIAccessibilityTraitPlaysSound), @"key": @(UIAccessibilityTraitKeyboardKey), + @"keyboardkey": @(UIAccessibilityTraitKeyboardKey), @"text": @(UIAccessibilityTraitStaticText), @"summary": @(UIAccessibilityTraitSummaryElement), @"disabled": @(UIAccessibilityTraitNotEnabled), @@ -110,6 +112,7 @@ - (RCTShadowView *)shadowView RCT_REMAP_VIEW_PROPERTY(accessibilityActions, reactAccessibilityElement.accessibilityActions, NSString) RCT_REMAP_VIEW_PROPERTY(accessibilityLabel, reactAccessibilityElement.accessibilityLabel, NSString) RCT_REMAP_VIEW_PROPERTY(accessibilityTraits, reactAccessibilityElement.accessibilityTraits, UIAccessibilityTraits) +RCT_REMAP_VIEW_PROPERTY(accessibilityRole, reactAccessibilityElement.accessibilityTraits, UIAccessibilityTraits) RCT_REMAP_VIEW_PROPERTY(accessibilityViewIsModal, reactAccessibilityElement.accessibilityViewIsModal, BOOL) RCT_REMAP_VIEW_PROPERTY(accessibilityElementsHidden, reactAccessibilityElement.accessibilityElementsHidden, BOOL) RCT_REMAP_VIEW_PROPERTY(accessibilityIgnoresInvertColors, reactAccessibilityElement.shouldAccessibilityIgnoresInvertColors, BOOL) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/AccessibilityRoleUtil.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/AccessibilityRoleUtil.java new file mode 100644 index 00000000000000..f063925a23b8f2 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/AccessibilityRoleUtil.java @@ -0,0 +1,121 @@ +// Copyright (c) 2004-present, Facebook, Inc. + +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +package com.facebook.react.uimanager; + +import android.annotation.TargetApi; +import android.os.Build; +import android.support.v4.view.AccessibilityDelegateCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; +import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; +import javax.annotation.Nullable; + +/** + * Utility class that handles the addition of a "role" for accessibility to either a View or + * AccessibilityNodeInfo. + */ + +public class AccessibilityRoleUtil { + + /** + * These roles are defined by Google's TalkBack screen reader, and this list should be kept up to + * date with their implementation. Details can be seen in their source code here: + * + *

https://github.com/google/talkback/blob/master/utils/src/main/java/Role.java + */ + + public enum AccessibilityRole { + NONE(null), + BUTTON("android.widget.Button"), + IMAGE("android.widget.ImageView"), + KEYBOARD_KEY("android.inputmethodservice.Keyboard$Key"), + TEXT("android.widget.ViewGroup"), + TAB_BAR("android.widget.TabWidget"); + + @Nullable private final String mValue; + + AccessibilityRole(String type) { + mValue = type; + } + + @Nullable + public String getValue() { + return mValue; + } + + public static AccessibilityRole fromValue(String value) { + for (AccessibilityRole role : AccessibilityRole.values()) { + if (role.getValue() != null && role.getValue().equals(value)) { + return role; + } + } + return AccessibilityRole.NONE; + } + } + + private AccessibilityRoleUtil() { + // No instances + } + + public static void setRole(View view, final AccessibilityRole role) { + // if a view already has an accessibility delegate, replacing it could cause problems, + // so leave it alone. + if (!ViewCompat.hasAccessibilityDelegate(view)) { + ViewCompat.setAccessibilityDelegate( + view, + new AccessibilityDelegateCompat() { + @Override + public void onInitializeAccessibilityNodeInfo( + View host, AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(host, info); + setRole(info, role); + } + }); + } + } + + public static void setRole(AccessibilityNodeInfoCompat nodeInfo, final AccessibilityRole role) { + nodeInfo.setClassName(role.getValue()); + } + + /** + * Variables and methods for setting accessibilityRole on view properties. + */ + private static final String NONE = "none"; + private static final String BUTTON = "button"; + private static final String IMAGE = "image"; + private static final String KEYBOARDKEY = "keyboardkey"; + private static final String TEXT = "text"; + private static final String TABBAR = "tabbar"; + + public static void updateAccessibilityRole(View view, String role) { + if (role == null) { + view.setAccessibilityDelegate(null); + } + switch (role) { + case NONE: + break; + case BUTTON: + setRole(view, AccessibilityRoleUtil.AccessibilityRole.BUTTON); + break; + case IMAGE: + setRole(view, AccessibilityRoleUtil.AccessibilityRole.IMAGE); + break; + case KEYBOARDKEY: + setRole(view, AccessibilityRoleUtil.AccessibilityRole.KEYBOARD_KEY); + break; + case TEXT: + setRole(view, AccessibilityRoleUtil.AccessibilityRole.TEXT); + break; + case TABBAR: + setRole(view, AccessibilityRoleUtil.AccessibilityRole.TAB_BAR); + break; + default: + view.setAccessibilityDelegate(null); + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java index 0fb71f1aa1a685..5b4c312ea5819f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java @@ -29,6 +29,7 @@ public abstract class BaseViewManager Date: Wed, 11 Jul 2018 04:09:39 -0700 Subject: [PATCH 56/65] Lint / reformat `YGJNI.cpp` Summary: Run clangformat on `YGJNI.cpp` @public Reviewed By: priteshrnandgaonkar Differential Revision: D8785660 fbshipit-source-id: 9748a5297e7b55e897de0280a79c2ea6ae1c1298 --- .../jni/first-party/yogajni/jni/YGJNI.cpp | 393 +++++++++++------- 1 file changed, 233 insertions(+), 160 deletions(-) diff --git a/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp b/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp index 5649ef7ea70e02..1d6f464cc88d37 100644 --- a/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp +++ b/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp @@ -33,13 +33,17 @@ struct YGConfigContext { } }; -static inline weak_ref *YGNodeJobject(YGNodeRef node) { +static inline weak_ref* YGNodeJobject(YGNodeRef node) { return reinterpret_cast*>(node->getContext()); } -static void YGTransferLayoutDirection(YGNodeRef node, alias_ref javaNode) { - static auto layoutDirectionField = javaNode->getClass()->getField("mLayoutDirection"); - javaNode->setFieldValue(layoutDirectionField, static_cast(YGNodeLayoutGetDirection(node))); +static void YGTransferLayoutDirection( + YGNodeRef node, + alias_ref javaNode) { + static auto layoutDirectionField = + javaNode->getClass()->getField("mLayoutDirection"); + javaNode->setFieldValue( + layoutDirectionField, static_cast(YGNodeLayoutGetDirection(node))); } static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { @@ -50,23 +54,37 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { static auto leftField = obj->getClass()->getField("mLeft"); static auto topField = obj->getClass()->getField("mTop"); - static auto marginLeftField = obj->getClass()->getField("mMarginLeft"); - static auto marginTopField = obj->getClass()->getField("mMarginTop"); - static auto marginRightField = obj->getClass()->getField("mMarginRight"); - static auto marginBottomField = obj->getClass()->getField("mMarginBottom"); - - static auto paddingLeftField = obj->getClass()->getField("mPaddingLeft"); - static auto paddingTopField = obj->getClass()->getField("mPaddingTop"); - static auto paddingRightField = obj->getClass()->getField("mPaddingRight"); - static auto paddingBottomField = obj->getClass()->getField("mPaddingBottom"); - - static auto borderLeftField = obj->getClass()->getField("mBorderLeft"); - static auto borderTopField = obj->getClass()->getField("mBorderTop"); - static auto borderRightField = obj->getClass()->getField("mBorderRight"); - static auto borderBottomField = obj->getClass()->getField("mBorderBottom"); - - static auto edgeSetFlagField = obj->getClass()->getField("mEdgeSetFlag"); - static auto hasNewLayoutField = obj->getClass()->getField("mHasNewLayout"); + static auto marginLeftField = + obj->getClass()->getField("mMarginLeft"); + static auto marginTopField = + obj->getClass()->getField("mMarginTop"); + static auto marginRightField = + obj->getClass()->getField("mMarginRight"); + static auto marginBottomField = + obj->getClass()->getField("mMarginBottom"); + + static auto paddingLeftField = + obj->getClass()->getField("mPaddingLeft"); + static auto paddingTopField = + obj->getClass()->getField("mPaddingTop"); + static auto paddingRightField = + obj->getClass()->getField("mPaddingRight"); + static auto paddingBottomField = + obj->getClass()->getField("mPaddingBottom"); + + static auto borderLeftField = + obj->getClass()->getField("mBorderLeft"); + static auto borderTopField = + obj->getClass()->getField("mBorderTop"); + static auto borderRightField = + obj->getClass()->getField("mBorderRight"); + static auto borderBottomField = + obj->getClass()->getField("mBorderBottom"); + + static auto edgeSetFlagField = + obj->getClass()->getField("mEdgeSetFlag"); + static auto hasNewLayoutField = + obj->getClass()->getField("mHasNewLayout"); static auto doesLegacyStretchBehaviour = obj->getClass()->getField( "mDoesLegacyStretchFlagAffectsLayout"); @@ -76,7 +94,7 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { const int PADDING = 2; const int BORDER = 4; - int hasEdgeSetFlag = (int) obj->getFieldValue(edgeSetFlagField); + int hasEdgeSetFlag = (int)obj->getFieldValue(edgeSetFlagField); obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root)); obj->setFieldValue(heightField, YGNodeLayoutGetHeight(root)); @@ -98,17 +116,25 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { } if ((hasEdgeSetFlag & PADDING) == PADDING) { - obj->setFieldValue(paddingLeftField, YGNodeLayoutGetPadding(root, YGEdgeLeft)); - obj->setFieldValue(paddingTopField, YGNodeLayoutGetPadding(root, YGEdgeTop)); - obj->setFieldValue(paddingRightField, YGNodeLayoutGetPadding(root, YGEdgeRight)); - obj->setFieldValue(paddingBottomField, YGNodeLayoutGetPadding(root, YGEdgeBottom)); + obj->setFieldValue( + paddingLeftField, YGNodeLayoutGetPadding(root, YGEdgeLeft)); + obj->setFieldValue( + paddingTopField, YGNodeLayoutGetPadding(root, YGEdgeTop)); + obj->setFieldValue( + paddingRightField, YGNodeLayoutGetPadding(root, YGEdgeRight)); + obj->setFieldValue( + paddingBottomField, YGNodeLayoutGetPadding(root, YGEdgeBottom)); } if ((hasEdgeSetFlag & BORDER) == BORDER) { - obj->setFieldValue(borderLeftField, YGNodeLayoutGetBorder(root, YGEdgeLeft)); - obj->setFieldValue(borderTopField, YGNodeLayoutGetBorder(root, YGEdgeTop)); - obj->setFieldValue(borderRightField, YGNodeLayoutGetBorder(root, YGEdgeRight)); - obj->setFieldValue(borderBottomField, YGNodeLayoutGetBorder(root, YGEdgeBottom)); + obj->setFieldValue( + borderLeftField, YGNodeLayoutGetBorder(root, YGEdgeLeft)); + obj->setFieldValue( + borderTopField, YGNodeLayoutGetBorder(root, YGEdgeTop)); + obj->setFieldValue( + borderRightField, YGNodeLayoutGetBorder(root, YGEdgeRight)); + obj->setFieldValue( + borderBottomField, YGNodeLayoutGetBorder(root, YGEdgeBottom)); } obj->setFieldValue(hasNewLayoutField, true); @@ -119,7 +145,10 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { YGTransferLayoutOutputsRecursive(YGNodeGetChild(root, i)); } } else { - YGLog(root, YGLogLevelError, "Java YGNode was GCed during layout calculation\n"); + YGLog( + root, + YGLogLevelError, + "Java YGNode was GCed during layout calculation\n"); } } } @@ -128,14 +157,18 @@ static void YGPrint(YGNodeRef node) { if (auto obj = YGNodeJobject(node)->lockLocal()) { cout << obj->toString() << endl; } else { - YGLog(node, YGLogLevelError, "Java YGNode was GCed during layout calculation\n"); + YGLog( + node, + YGLogLevelError, + "Java YGNode was GCed during layout calculation\n"); } } static float YGJNIBaselineFunc(YGNodeRef node, float width, float height) { if (auto obj = YGNodeJobject(node)->lockLocal()) { - static auto baselineFunc = findClassStatic("com/facebook/yoga/YogaNode") - ->getMethod("baseline"); + static auto baselineFunc = + findClassStatic("com/facebook/yoga/YogaNode") + ->getMethod("baseline"); return baselineFunc(obj, width, height); } else { return height; @@ -150,20 +183,17 @@ static inline YGConfigRef _jlong2YGConfigRef(jlong addr) { return reinterpret_cast(static_cast(addr)); } -static YGNodeRef YGJNIOnNodeClonedFunc( - YGNodeRef oldNode, - YGNodeRef owner, - int childIndex) { +static YGNodeRef +YGJNIOnNodeClonedFunc(YGNodeRef oldNode, YGNodeRef owner, int childIndex) { auto config = oldNode->getConfig(); if (!config) { return nullptr; } - static auto onNodeClonedFunc = findClassStatic("com/facebook/yoga/YogaConfig") - ->getMethod( - local_ref, - local_ref, - jint)>("cloneNode"); + static auto onNodeClonedFunc = + findClassStatic("com/facebook/yoga/YogaConfig") + ->getMethod( + local_ref, local_ref, jint)>("cloneNode"); auto context = reinterpret_cast(YGConfigGetContext(config)); auto javaConfig = context->config; @@ -174,15 +204,12 @@ static YGNodeRef YGJNIOnNodeClonedFunc( YGNodeJobject(owner)->lockLocal(), childIndex); - static auto replaceChild = findClassStatic("com/facebook/yoga/YogaNode") - ->getMethod, - jint)>("replaceChild"); + static auto replaceChild = + findClassStatic("com/facebook/yoga/YogaNode") + ->getMethod, jint)>("replaceChild"); - jlong newNodeNativePointer = replaceChild( - YGNodeJobject(owner)->lockLocal(), - newNode, - childIndex); + jlong newNodeNativePointer = + replaceChild(YGNodeJobject(owner)->lockLocal(), newNode, childIndex); return _jlong2YGNodeRef(newNodeNativePointer); } @@ -194,24 +221,30 @@ static YGSize YGJNIMeasureFunc( float height, YGMeasureMode heightMode) { if (auto obj = YGNodeJobject(node)->lockLocal()) { - static auto measureFunc = findClassStatic("com/facebook/yoga/YogaNode") - ->getMethod("measure"); + static auto measureFunc = + findClassStatic("com/facebook/yoga/YogaNode") + ->getMethod("measure"); YGTransferLayoutDirection(node, obj); - const auto measureResult = measureFunc(obj, width, widthMode, height, heightMode); + const auto measureResult = + measureFunc(obj, width, widthMode, height, heightMode); - static_assert(sizeof(measureResult) == 8, - "Expected measureResult to be 8 bytes, or two 32 bit ints"); + static_assert( + sizeof(measureResult) == 8, + "Expected measureResult to be 8 bytes, or two 32 bit ints"); int32_t wBits = 0xFFFFFFFF & (measureResult >> 32); int32_t hBits = 0xFFFFFFFF & measureResult; - const float *measuredWidth = reinterpret_cast(&wBits); - const float *measuredHeight = reinterpret_cast(&hBits); + const float* measuredWidth = reinterpret_cast(&wBits); + const float* measuredHeight = reinterpret_cast(&hBits); return YGSize{*measuredWidth, *measuredHeight}; } else { - YGLog(node, YGLogLevelError, "Java YGNode was GCed during layout calculation\n"); + YGLog( + node, + YGLogLevelError, + "Java YGNode was GCed during layout calculation\n"); return YGSize{ widthMode == YGMeasureModeUndefined ? 0 : width, heightMode == YGMeasureModeUndefined ? 0 : height, @@ -223,24 +256,28 @@ struct JYogaLogLevel : public JavaClass { static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaLogLevel;"; }; -static int YGJNILogFunc(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args) { +static int YGJNILogFunc( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args) { int result = vsnprintf(NULL, 0, format, args); std::vector buffer(1 + result); vsnprintf(buffer.data(), buffer.size(), format, args); static auto logFunc = findClassStatic("com/facebook/yoga/YogaLogger") - ->getMethod, local_ref, jstring)>("log"); + ->getMethod, local_ref, jstring)>("log"); static auto logLevelFromInt = - JYogaLogLevel::javaClassStatic()->getStaticMethod("fromInt"); + JYogaLogLevel::javaClassStatic() + ->getStaticMethod("fromInt"); if (auto obj = YGNodeJobject(node)->lockLocal()) { - auto jlogger = reinterpret_cast *>(YGConfigGetContext(config)); + auto jlogger = + reinterpret_cast*>(YGConfigGetContext(config)); logFunc( jlogger->get(), obj, @@ -309,13 +346,19 @@ void jni_YGNodeReset(alias_ref thiz, jlong nativePointer) { void jni_YGNodePrint(alias_ref thiz, jlong nativePointer) { const YGNodeRef node = _jlong2YGNodeRef(nativePointer); - YGNodePrint(node, - (YGPrintOptions)(YGPrintOptionsStyle | YGPrintOptionsLayout | - YGPrintOptionsChildren)); + YGNodePrint( + node, + (YGPrintOptions)( + YGPrintOptionsStyle | YGPrintOptionsLayout | YGPrintOptionsChildren)); } -void jni_YGNodeInsertChild(alias_ref, jlong nativePointer, jlong childPointer, jint index) { - YGNodeInsertChild(_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); +void jni_YGNodeInsertChild( + alias_ref, + jlong nativePointer, + jlong childPointer, + jint index) { + YGNodeInsertChild( + _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); } void jni_YGNodeInsertSharedChild( @@ -327,19 +370,25 @@ void jni_YGNodeInsertSharedChild( _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); } -void jni_YGNodeRemoveChild(alias_ref, jlong nativePointer, jlong childPointer) { - YGNodeRemoveChild(_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer)); +void jni_YGNodeRemoveChild( + alias_ref, + jlong nativePointer, + jlong childPointer) { + YGNodeRemoveChild( + _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer)); } -void jni_YGNodeCalculateLayout(alias_ref, - jlong nativePointer, - jfloat width, - jfloat height) { +void jni_YGNodeCalculateLayout( + alias_ref, + jlong nativePointer, + jfloat width, + jfloat height) { const YGNodeRef root = _jlong2YGNodeRef(nativePointer); - YGNodeCalculateLayout(root, - static_cast(width), - static_cast(height), - YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer))); + YGNodeCalculateLayout( + root, + static_cast(width), + static_cast(height), + YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer))); YGTransferLayoutOutputsRecursive(root); } @@ -357,20 +406,28 @@ jboolean jni_YGNodeIsDirty(alias_ref, jlong nativePointer) { return (jboolean)_jlong2YGNodeRef(nativePointer)->isDirty(); } -void jni_YGNodeSetHasMeasureFunc(alias_ref, jlong nativePointer, jboolean hasMeasureFunc) { +void jni_YGNodeSetHasMeasureFunc( + alias_ref, + jlong nativePointer, + jboolean hasMeasureFunc) { _jlong2YGNodeRef(nativePointer) ->setMeasureFunc(hasMeasureFunc ? YGJNIMeasureFunc : nullptr); } -void jni_YGNodeSetHasBaselineFunc(alias_ref, - jlong nativePointer, - jboolean hasBaselineFunc) { +void jni_YGNodeSetHasBaselineFunc( + alias_ref, + jlong nativePointer, + jboolean hasBaselineFunc) { _jlong2YGNodeRef(nativePointer) ->setBaseLineFunc(hasBaselineFunc ? YGJNIBaselineFunc : nullptr); } -void jni_YGNodeCopyStyle(alias_ref, jlong dstNativePointer, jlong srcNativePointer) { - YGNodeCopyStyle(_jlong2YGNodeRef(dstNativePointer), _jlong2YGNodeRef(srcNativePointer)); +void jni_YGNodeCopyStyle( + alias_ref, + jlong dstNativePointer, + jlong srcNativePointer) { + YGNodeCopyStyle( + _jlong2YGNodeRef(dstNativePointer), _jlong2YGNodeRef(srcNativePointer)); } struct JYogaValue : public JavaClass { @@ -392,67 +449,76 @@ struct JYogaValue : public JavaClass { _jlong2YGNodeRef(nativePointer), static_cast(value)); \ } -#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \ - local_ref jni_YGNodeStyleGet##name(alias_ref, jlong nativePointer) { \ - return JYogaValue::create(YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \ - } \ - \ - void jni_YGNodeStyleSet##name(alias_ref, jlong nativePointer, jfloat value) { \ - YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), static_cast(value)); \ - } \ - \ - void jni_YGNodeStyleSet##name##Percent(alias_ref, jlong nativePointer, jfloat value) { \ - YGNodeStyleSet##name##Percent(_jlong2YGNodeRef(nativePointer), static_cast(value)); \ +#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \ + local_ref jni_YGNodeStyleGet##name( \ + alias_ref, jlong nativePointer) { \ + return JYogaValue::create( \ + YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \ + } \ + \ + void jni_YGNodeStyleSet##name( \ + alias_ref, jlong nativePointer, jfloat value) { \ + YGNodeStyleSet##name( \ + _jlong2YGNodeRef(nativePointer), static_cast(value)); \ + } \ + \ + void jni_YGNodeStyleSet##name##Percent( \ + alias_ref, jlong nativePointer, jfloat value) { \ + YGNodeStyleSet##name##Percent( \ + _jlong2YGNodeRef(nativePointer), static_cast(value)); \ } -#define YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(name) \ - YG_NODE_JNI_STYLE_UNIT_PROP(name) \ - void jni_YGNodeStyleSet##name##Auto(alias_ref, jlong nativePointer) { \ - YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer)); \ +#define YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(name) \ + YG_NODE_JNI_STYLE_UNIT_PROP(name) \ + void jni_YGNodeStyleSet##name##Auto( \ + alias_ref, jlong nativePointer) { \ + YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer)); \ } -#define YG_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \ - javatype jni_YGNodeStyleGet##name(alias_ref, jlong nativePointer, jint edge) { \ - return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer), \ - static_cast(edge)); \ - } \ - \ - void jni_YGNodeStyleSet##name(alias_ref, \ - jlong nativePointer, \ - jint edge, \ - javatype value) { \ - YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), \ - static_cast(edge), \ - static_cast(value)); \ +#define YG_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \ + javatype jni_YGNodeStyleGet##name( \ + alias_ref, jlong nativePointer, jint edge) { \ + return (javatype)YGNodeStyleGet##name( \ + _jlong2YGNodeRef(nativePointer), static_cast(edge)); \ + } \ + \ + void jni_YGNodeStyleSet##name( \ + alias_ref, jlong nativePointer, jint edge, javatype value) { \ + YGNodeStyleSet##name( \ + _jlong2YGNodeRef(nativePointer), \ + static_cast(edge), \ + static_cast(value)); \ } -#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ - local_ref jni_YGNodeStyleGet##name(alias_ref, \ - jlong nativePointer, \ - jint edge) { \ - return JYogaValue::create( \ - YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer), static_cast(edge))); \ - } \ - \ - void jni_YGNodeStyleSet##name(alias_ref, jlong nativePointer, jint edge, jfloat value) { \ - YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), \ - static_cast(edge), \ - static_cast(value)); \ - } \ - \ - void jni_YGNodeStyleSet##name##Percent(alias_ref, \ - jlong nativePointer, \ - jint edge, \ - jfloat value) { \ - YGNodeStyleSet##name##Percent(_jlong2YGNodeRef(nativePointer), \ - static_cast(edge), \ - static_cast(value)); \ +#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ + local_ref jni_YGNodeStyleGet##name( \ + alias_ref, jlong nativePointer, jint edge) { \ + return JYogaValue::create(YGNodeStyleGet##name( \ + _jlong2YGNodeRef(nativePointer), static_cast(edge))); \ + } \ + \ + void jni_YGNodeStyleSet##name( \ + alias_ref, jlong nativePointer, jint edge, jfloat value) { \ + YGNodeStyleSet##name( \ + _jlong2YGNodeRef(nativePointer), \ + static_cast(edge), \ + static_cast(value)); \ + } \ + \ + void jni_YGNodeStyleSet##name##Percent( \ + alias_ref, jlong nativePointer, jint edge, jfloat value) { \ + YGNodeStyleSet##name##Percent( \ + _jlong2YGNodeRef(nativePointer), \ + static_cast(edge), \ + static_cast(value)); \ } -#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(name) \ - YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ - void jni_YGNodeStyleSet##name##Auto(alias_ref, jlong nativePointer, jint edge) { \ - YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer), static_cast(edge)); \ +#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(name) \ + YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ + void jni_YGNodeStyleSet##name##Auto( \ + alias_ref, jlong nativePointer, jint edge) { \ + YGNodeStyleSet##name##Auto( \ + _jlong2YGNodeRef(nativePointer), static_cast(edge)); \ } YG_NODE_JNI_STYLE_PROP(jint, YGDirection, Direction); @@ -466,8 +532,12 @@ YG_NODE_JNI_STYLE_PROP(jint, YGWrap, FlexWrap); YG_NODE_JNI_STYLE_PROP(jint, YGOverflow, Overflow); YG_NODE_JNI_STYLE_PROP(jint, YGDisplay, Display); -void jni_YGNodeStyleSetFlex(alias_ref, jlong nativePointer, jfloat value) { - YGNodeStyleSetFlex(_jlong2YGNodeRef(nativePointer), static_cast(value)); +void jni_YGNodeStyleSetFlex( + alias_ref, + jlong nativePointer, + jfloat value) { + YGNodeStyleSetFlex( + _jlong2YGNodeRef(nativePointer), static_cast(value)); } YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexGrow); YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexShrink); @@ -501,14 +571,14 @@ void jni_YGConfigFree(alias_ref, jlong nativePointer) { YGConfigFree(config); } -void jni_YGConfigSetExperimentalFeatureEnabled(alias_ref, - jlong nativePointer, - jint feature, - jboolean enabled) { +void jni_YGConfigSetExperimentalFeatureEnabled( + alias_ref, + jlong nativePointer, + jint feature, + jboolean enabled) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); - YGConfigSetExperimentalFeatureEnabled(config, - static_cast(feature), - enabled); + YGConfigSetExperimentalFeatureEnabled( + config, static_cast(feature), enabled); } void jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( @@ -519,23 +589,26 @@ void jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour(config, enabled); } -void jni_YGConfigSetUseWebDefaults(alias_ref, - jlong nativePointer, - jboolean useWebDefaults) { +void jni_YGConfigSetUseWebDefaults( + alias_ref, + jlong nativePointer, + jboolean useWebDefaults) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetUseWebDefaults(config, useWebDefaults); } -void jni_YGConfigSetPointScaleFactor(alias_ref, - jlong nativePointer, - jfloat pixelsInPoint) { +void jni_YGConfigSetPointScaleFactor( + alias_ref, + jlong nativePointer, + jfloat pixelsInPoint) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetPointScaleFactor(config, pixelsInPoint); } -void jni_YGConfigSetUseLegacyStretchBehaviour(alias_ref, - jlong nativePointer, - jboolean useLegacyStretchBehaviour) { +void jni_YGConfigSetUseLegacyStretchBehaviour( + alias_ref, + jlong nativePointer, + jboolean useLegacyStretchBehaviour) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetUseLegacyStretchBehaviour(config, useLegacyStretchBehaviour); } @@ -592,7 +665,7 @@ jint jni_YGNodeGetInstanceCount(alias_ref clazz) { #define YGMakeNativeMethod(name) makeNativeMethod(#name, name) -jint JNI_OnLoad(JavaVM *vm, void *) { +jint JNI_OnLoad(JavaVM* vm, void*) { return initialize(vm, [] { registerNatives( "com/facebook/yoga/YogaNode", From 1535ecfa548cab2a4fa4500b446897733cde3014 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 11 Jul 2018 04:09:40 -0700 Subject: [PATCH 57/65] guards instead of nested if Summary: Replaces two nested if-blocks with guards. This is intended to help with restructuring this function in follow-ups. @public Reviewed By: priteshrnandgaonkar Differential Revision: D8785659 fbshipit-source-id: 7b9d63e9814b83b999397c016ad67ad348bb0f72 --- .../jni/first-party/yogajni/jni/YGJNI.cpp | 204 +++++++++--------- 1 file changed, 101 insertions(+), 103 deletions(-) diff --git a/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp b/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp index 1d6f464cc88d37..0b5520558a188c 100644 --- a/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp +++ b/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp @@ -47,109 +47,107 @@ static void YGTransferLayoutDirection( } static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { - if (root->getHasNewLayout()) { - if (auto obj = YGNodeJobject(root)->lockLocal()) { - static auto widthField = obj->getClass()->getField("mWidth"); - static auto heightField = obj->getClass()->getField("mHeight"); - static auto leftField = obj->getClass()->getField("mLeft"); - static auto topField = obj->getClass()->getField("mTop"); - - static auto marginLeftField = - obj->getClass()->getField("mMarginLeft"); - static auto marginTopField = - obj->getClass()->getField("mMarginTop"); - static auto marginRightField = - obj->getClass()->getField("mMarginRight"); - static auto marginBottomField = - obj->getClass()->getField("mMarginBottom"); - - static auto paddingLeftField = - obj->getClass()->getField("mPaddingLeft"); - static auto paddingTopField = - obj->getClass()->getField("mPaddingTop"); - static auto paddingRightField = - obj->getClass()->getField("mPaddingRight"); - static auto paddingBottomField = - obj->getClass()->getField("mPaddingBottom"); - - static auto borderLeftField = - obj->getClass()->getField("mBorderLeft"); - static auto borderTopField = - obj->getClass()->getField("mBorderTop"); - static auto borderRightField = - obj->getClass()->getField("mBorderRight"); - static auto borderBottomField = - obj->getClass()->getField("mBorderBottom"); - - static auto edgeSetFlagField = - obj->getClass()->getField("mEdgeSetFlag"); - static auto hasNewLayoutField = - obj->getClass()->getField("mHasNewLayout"); - static auto doesLegacyStretchBehaviour = - obj->getClass()->getField( - "mDoesLegacyStretchFlagAffectsLayout"); - - /* Those flags needs be in sync with YogaNode.java */ - const int MARGIN = 1; - const int PADDING = 2; - const int BORDER = 4; - - int hasEdgeSetFlag = (int)obj->getFieldValue(edgeSetFlagField); - - obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root)); - obj->setFieldValue(heightField, YGNodeLayoutGetHeight(root)); - obj->setFieldValue(leftField, YGNodeLayoutGetLeft(root)); - obj->setFieldValue(topField, YGNodeLayoutGetTop(root)); - obj->setFieldValue( - doesLegacyStretchBehaviour, - YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(root)); - - if ((hasEdgeSetFlag & MARGIN) == MARGIN) { - obj->setFieldValue( - marginLeftField, YGNodeLayoutGetMargin(root, YGEdgeLeft)); - obj->setFieldValue( - marginTopField, YGNodeLayoutGetMargin(root, YGEdgeTop)); - obj->setFieldValue( - marginRightField, YGNodeLayoutGetMargin(root, YGEdgeRight)); - obj->setFieldValue( - marginBottomField, YGNodeLayoutGetMargin(root, YGEdgeBottom)); - } - - if ((hasEdgeSetFlag & PADDING) == PADDING) { - obj->setFieldValue( - paddingLeftField, YGNodeLayoutGetPadding(root, YGEdgeLeft)); - obj->setFieldValue( - paddingTopField, YGNodeLayoutGetPadding(root, YGEdgeTop)); - obj->setFieldValue( - paddingRightField, YGNodeLayoutGetPadding(root, YGEdgeRight)); - obj->setFieldValue( - paddingBottomField, YGNodeLayoutGetPadding(root, YGEdgeBottom)); - } - - if ((hasEdgeSetFlag & BORDER) == BORDER) { - obj->setFieldValue( - borderLeftField, YGNodeLayoutGetBorder(root, YGEdgeLeft)); - obj->setFieldValue( - borderTopField, YGNodeLayoutGetBorder(root, YGEdgeTop)); - obj->setFieldValue( - borderRightField, YGNodeLayoutGetBorder(root, YGEdgeRight)); - obj->setFieldValue( - borderBottomField, YGNodeLayoutGetBorder(root, YGEdgeBottom)); - } - - obj->setFieldValue(hasNewLayoutField, true); - YGTransferLayoutDirection(root, obj); - root->setHasNewLayout(false); - - for (uint32_t i = 0; i < YGNodeGetChildCount(root); i++) { - YGTransferLayoutOutputsRecursive(YGNodeGetChild(root, i)); - } - } else { - YGLog( - root, - YGLogLevelError, - "Java YGNode was GCed during layout calculation\n"); - } + if (!root->getHasNewLayout()) { + return; + } + auto obj = YGNodeJobject(root)->lockLocal(); + if (!obj) { + YGLog( + root, + YGLogLevelError, + "Java YGNode was GCed during layout calculation\n"); + return; + } + + static auto widthField = obj->getClass()->getField("mWidth"); + static auto heightField = obj->getClass()->getField("mHeight"); + static auto leftField = obj->getClass()->getField("mLeft"); + static auto topField = obj->getClass()->getField("mTop"); + + static auto marginLeftField = + obj->getClass()->getField("mMarginLeft"); + static auto marginTopField = obj->getClass()->getField("mMarginTop"); + static auto marginRightField = + obj->getClass()->getField("mMarginRight"); + static auto marginBottomField = + obj->getClass()->getField("mMarginBottom"); + + static auto paddingLeftField = + obj->getClass()->getField("mPaddingLeft"); + static auto paddingTopField = + obj->getClass()->getField("mPaddingTop"); + static auto paddingRightField = + obj->getClass()->getField("mPaddingRight"); + static auto paddingBottomField = + obj->getClass()->getField("mPaddingBottom"); + + static auto borderLeftField = + obj->getClass()->getField("mBorderLeft"); + static auto borderTopField = obj->getClass()->getField("mBorderTop"); + static auto borderRightField = + obj->getClass()->getField("mBorderRight"); + static auto borderBottomField = + obj->getClass()->getField("mBorderBottom"); + + static auto edgeSetFlagField = + obj->getClass()->getField("mEdgeSetFlag"); + static auto hasNewLayoutField = + obj->getClass()->getField("mHasNewLayout"); + static auto doesLegacyStretchBehaviour = obj->getClass()->getField( + "mDoesLegacyStretchFlagAffectsLayout"); + + /* Those flags needs be in sync with YogaNode.java */ + const int MARGIN = 1; + const int PADDING = 2; + const int BORDER = 4; + + int hasEdgeSetFlag = (int)obj->getFieldValue(edgeSetFlagField); + + obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root)); + obj->setFieldValue(heightField, YGNodeLayoutGetHeight(root)); + obj->setFieldValue(leftField, YGNodeLayoutGetLeft(root)); + obj->setFieldValue(topField, YGNodeLayoutGetTop(root)); + obj->setFieldValue( + doesLegacyStretchBehaviour, + YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(root)); + + if ((hasEdgeSetFlag & MARGIN) == MARGIN) { + obj->setFieldValue( + marginLeftField, YGNodeLayoutGetMargin(root, YGEdgeLeft)); + obj->setFieldValue(marginTopField, YGNodeLayoutGetMargin(root, YGEdgeTop)); + obj->setFieldValue( + marginRightField, YGNodeLayoutGetMargin(root, YGEdgeRight)); + obj->setFieldValue( + marginBottomField, YGNodeLayoutGetMargin(root, YGEdgeBottom)); + } + + if ((hasEdgeSetFlag & PADDING) == PADDING) { + obj->setFieldValue( + paddingLeftField, YGNodeLayoutGetPadding(root, YGEdgeLeft)); + obj->setFieldValue( + paddingTopField, YGNodeLayoutGetPadding(root, YGEdgeTop)); + obj->setFieldValue( + paddingRightField, YGNodeLayoutGetPadding(root, YGEdgeRight)); + obj->setFieldValue( + paddingBottomField, YGNodeLayoutGetPadding(root, YGEdgeBottom)); + } + + if ((hasEdgeSetFlag & BORDER) == BORDER) { + obj->setFieldValue( + borderLeftField, YGNodeLayoutGetBorder(root, YGEdgeLeft)); + obj->setFieldValue(borderTopField, YGNodeLayoutGetBorder(root, YGEdgeTop)); + obj->setFieldValue( + borderRightField, YGNodeLayoutGetBorder(root, YGEdgeRight)); + obj->setFieldValue( + borderBottomField, YGNodeLayoutGetBorder(root, YGEdgeBottom)); + } + + obj->setFieldValue(hasNewLayoutField, true); + YGTransferLayoutDirection(root, obj); + root->setHasNewLayout(false); + + for (uint32_t i = 0; i < YGNodeGetChildCount(root); i++) { + YGTransferLayoutOutputsRecursive(YGNodeGetChild(root, i)); } } From 578b0b2a51fc0c2aba5d27cdd5335396d5351463 Mon Sep 17 00:00:00 2001 From: Martin Sherburn Date: Wed, 11 Jul 2018 04:18:34 -0700 Subject: [PATCH 58/65] Fixed issue with reloading bundle from remote debugger Summary: This is a follow up to D8316215. That diff had a flaw in that once appExecuted was set to true it would never be reset back to false. This fixes that so if another bundle is loaded after the first one it will work. Reviewed By: rafeca Differential Revision: D8661523 fbshipit-source-id: 5f6024102248383f64952fd33b37368732d5f900 --- local-cli/server/util/debugger-ui/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/local-cli/server/util/debugger-ui/index.html b/local-cli/server/util/debugger-ui/index.html index 8a7f2b3206fec9..c4f825145acbb1 100644 --- a/local-cli/server/util/debugger-ui/index.html +++ b/local-cli/server/util/debugger-ui/index.html @@ -179,6 +179,7 @@ shutdownJSRuntime(); Page.setState({status: {type: 'disconnected'}}); } else if (object.method === 'executeApplicationScript') { + appExecuted = false; worker.postMessage({ ...object, url: await getBlobUrl(object.url), From 90a408ea6ff7833e33b4058f490073e04460d00b Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Wed, 11 Jul 2018 05:55:02 -0700 Subject: [PATCH 59/65] Fix SingleFlex Child condition Summary: Fixes the improper `singleFlexChild` optimization. In the case when all the childs have `flex-grow:0 flex-grow:0` except one child with `flex-grow:1 flex-shrink:1`, then one can simply measure all the non-flexing children and then give the flexing child all the remaining space. Also added a test case which reproduced the bug Reviewed By: IanChilds Differential Revision: D8782684 fbshipit-source-id: ffd4d35b6122f82111b987540efb23bd2a8da5a2 --- ReactCommon/yoga/yoga/Yoga.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index e5d1aabb048981..3684aae4fd5033 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -1788,16 +1788,17 @@ static void YGNodeComputeFlexBasisForChildren( // child to exactly match the remaining space if (measureModeMainDim == YGMeasureModeExactly) { for (auto child : children) { - if (singleFlexChild != nullptr) { - if (child->isNodeFlexible()) { - // There is already a flexible child, abort + if (child->isNodeFlexible()) { + if (singleFlexChild != nullptr || + YGFloatsEqual(child->resolveFlexGrow(), 0.0f) || + YGFloatsEqual(child->resolveFlexShrink(), 0.0f)) { + // There is already a flexible child, or this flexible child doesn't + // have flexGrow and flexShrink, abort singleFlexChild = nullptr; break; + } else { + singleFlexChild = child; } - } else if ( - child->resolveFlexGrow() > 0.0f && - child->resolveFlexShrink() > 0.0f) { - singleFlexChild = child; } } } From 00936a003cf619e4836e2c205fd24e695e8c97d5 Mon Sep 17 00:00:00 2001 From: Miguel Jimenez Esun Date: Wed, 11 Jul 2018 06:36:44 -0700 Subject: [PATCH 60/65] Upgrade Jest to v23.4.0 Summary: Upgrade Jest to the latest version. Differential Revision: D8784710 fbshipit-source-id: 2319bf0d11506c1c0ad0506ba38a76e07f8feb3b --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index acd729198cbb08..66ba68b1f42bea 100644 --- a/package.json +++ b/package.json @@ -213,7 +213,7 @@ "eslint-plugin-react": "7.8.2", "eslint-plugin-react-native": "^3.2.1", "flow-bin": "^0.76.0", - "jest": "23.2.0", + "jest": "23.4.0", "jest-junit": "5.1.0", "prettier": "1.13.6", "react": "16.4.1", From 4db8160f253d7aa7c54fe7f552e1d14392d09407 Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Sat, 16 Jun 2018 22:24:12 +0800 Subject: [PATCH 61/65] use js instead of bash to start RNTester dev server --- local-cli/bundle/bundleCommandLineArgs.js | 1 + local-cli/dependencies/dependencies.js | 1 + local-cli/runAndroid/runAndroid.js | 1 + local-cli/runIOS/runIOS.js | 1 + package.json | 1 + scripts/packager.sh | 11 ----------- 6 files changed, 5 insertions(+), 11 deletions(-) delete mode 100755 scripts/packager.sh diff --git a/local-cli/bundle/bundleCommandLineArgs.js b/local-cli/bundle/bundleCommandLineArgs.js index 4853f877ab7d6f..d0e85bb53f3d65 100644 --- a/local-cli/bundle/bundleCommandLineArgs.js +++ b/local-cli/bundle/bundleCommandLineArgs.js @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format + * @flow */ 'use strict'; diff --git a/local-cli/dependencies/dependencies.js b/local-cli/dependencies/dependencies.js index baa6ec4a7a4da4..86c8d093a34b0d 100644 --- a/local-cli/dependencies/dependencies.js +++ b/local-cli/dependencies/dependencies.js @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format + * @flow */ 'use strict'; diff --git a/local-cli/runAndroid/runAndroid.js b/local-cli/runAndroid/runAndroid.js index 6835c97bcb0bf0..f6dc3db1de3a69 100644 --- a/local-cli/runAndroid/runAndroid.js +++ b/local-cli/runAndroid/runAndroid.js @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format + * @flow */ 'use strict'; diff --git a/local-cli/runIOS/runIOS.js b/local-cli/runIOS/runIOS.js index dfabb92b894a4b..b79898b9e2d5b8 100644 --- a/local-cli/runIOS/runIOS.js +++ b/local-cli/runIOS/runIOS.js @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format + * @flow */ 'use strict'; diff --git a/package.json b/package.json index 66ba68b1f42bea..88970f38d6b078 100644 --- a/package.json +++ b/package.json @@ -122,6 +122,7 @@ "third-party-podspecs" ], "scripts": { + "start": "flow-node ./local-cli/cli.js start -- --reset-cache", "test": "jest", "test-ci": "JEST_JUNIT_OUTPUT=\"reports/junit/js-test-results.xml\" jest --maxWorkers=2 --ci --testResultsProcessor=\"jest-junit\"", "flow": "flow", diff --git a/scripts/packager.sh b/scripts/packager.sh deleted file mode 100755 index ee3966923a2bb0..00000000000000 --- a/scripts/packager.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) 2015-present, Facebook, Inc. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -THIS_DIR=$(dirname "$0") -source "${THIS_DIR}/.packager.env" -cd "$THIS_DIR/.." -node "./local-cli/cli.js" start "$@" From d038c2ea120e56f5f87dc7678dc6fee1be53cae6 Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Sat, 16 Jun 2018 22:50:09 +0800 Subject: [PATCH 62/65] remove redundant type --- local-cli/bundle/bundleCommandLineArgs.js | 3 +-- local-cli/dependencies/dependencies.js | 3 +-- local-cli/runAndroid/runAndroid.js | 3 +-- local-cli/runIOS/runIOS.js | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/local-cli/bundle/bundleCommandLineArgs.js b/local-cli/bundle/bundleCommandLineArgs.js index d0e85bb53f3d65..445654234e7eb5 100644 --- a/local-cli/bundle/bundleCommandLineArgs.js +++ b/local-cli/bundle/bundleCommandLineArgs.js @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow */ 'use strict'; @@ -56,7 +55,7 @@ module.exports = [ 'Specifies the maximum number of workers the worker-pool ' + 'will spawn for transforming files. This defaults to the number of the ' + 'cores available on your machine.', - parse: (workers: string) => Number(workers), + parse: (workers) => Number(workers), }, { command: '--sourcemap-output [string]', diff --git a/local-cli/dependencies/dependencies.js b/local-cli/dependencies/dependencies.js index 86c8d093a34b0d..03d190833bec3f 100644 --- a/local-cli/dependencies/dependencies.js +++ b/local-cli/dependencies/dependencies.js @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow */ 'use strict'; @@ -120,7 +119,7 @@ module.exports = { 'Specifies the maximum number of workers the worker-pool ' + 'will spawn for transforming files. This defaults to the number of the ' + 'cores available on your machine.', - parse: (workers: string) => Number(workers), + parse: (workers) => Number(workers), }, { command: '--dev [boolean]', diff --git a/local-cli/runAndroid/runAndroid.js b/local-cli/runAndroid/runAndroid.js index f6dc3db1de3a69..d33767857f67f4 100644 --- a/local-cli/runAndroid/runAndroid.js +++ b/local-cli/runAndroid/runAndroid.js @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow */ 'use strict'; @@ -473,7 +472,7 @@ module.exports = { { command: '--port [number]', default: process.env.RCT_METRO_PORT || 8081, - parse: (val: string) => Number(val), + parse: (val) => Number(val), }, ], }; diff --git a/local-cli/runIOS/runIOS.js b/local-cli/runIOS/runIOS.js index b79898b9e2d5b8..02c5e8213dfcbc 100644 --- a/local-cli/runIOS/runIOS.js +++ b/local-cli/runIOS/runIOS.js @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow */ 'use strict'; @@ -448,7 +447,7 @@ module.exports = { { command: '--port [number]', default: process.env.RCT_METRO_PORT || 8081, - parse: (val: string) => Number(val), + parse: (val) => Number(val), }, ], }; From 5ea9776a4deffac61ba8c8c1a1c488bd1a78ad69 Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Sat, 16 Jun 2018 22:50:18 +0800 Subject: [PATCH 63/65] fix script --- scripts/objc-test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/objc-test.sh b/scripts/objc-test.sh index c2a9a94d182e7b..f52f38737a9c34 100755 --- a/scripts/objc-test.sh +++ b/scripts/objc-test.sh @@ -56,7 +56,7 @@ function waitForPackager { if [ "$1" = "test" ]; then # Start the packager -./scripts/packager.sh --max-workers=1 || echo "Can't start packager automatically" & +npm run start || echo "Can't start packager automatically" & # Start the WebSocket test server open "./IntegrationTests/launchWebSocketServer.command" || echo "Can't start web socket server automatically" From 853209267a325a8635aafccd3ca48f224484a1f4 Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Wed, 27 Jun 2018 21:12:12 +0800 Subject: [PATCH 64/65] remove obsolete file --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 88970f38d6b078..11c34eb625154f 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,6 @@ "scripts/ios-install-third-party.sh", "scripts/launchPackager.bat", "scripts/launchPackager.command", - "scripts/packager.sh", "scripts/react-native-xcode.sh", "jest-preset.json", "jest", @@ -122,7 +121,7 @@ "third-party-podspecs" ], "scripts": { - "start": "flow-node ./local-cli/cli.js start -- --reset-cache", + "start": "flow-node ./local-cli/cli.js start", "test": "jest", "test-ci": "JEST_JUNIT_OUTPUT=\"reports/junit/js-test-results.xml\" jest --maxWorkers=2 --ci --testResultsProcessor=\"jest-junit\"", "flow": "flow", From 7b2e22cccdca069a2098ecf96a5108723cb94395 Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Thu, 12 Jul 2018 20:41:30 +0800 Subject: [PATCH 65/65] revert flow-node --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 11c34eb625154f..969f292972beb5 100644 --- a/package.json +++ b/package.json @@ -121,13 +121,12 @@ "third-party-podspecs" ], "scripts": { - "start": "flow-node ./local-cli/cli.js start", + "start": "node ./local-cli/cli.js start", "test": "jest", "test-ci": "JEST_JUNIT_OUTPUT=\"reports/junit/js-test-results.xml\" jest --maxWorkers=2 --ci --testResultsProcessor=\"jest-junit\"", "flow": "flow", "lint": "eslint .", "prettier": "prettier \"./**/*.js\" --write", - "start": "/usr/bin/env bash -c './scripts/packager.sh \"$@\" || true' --", "docker-setup-android": "docker pull reactnativeci/android-base:latest", "docker-build-android-base": "docker build -t reactnativeci/android-base -f ContainerShip/Dockerfile.android-base .", "docker-build-android": "docker build -t reactnativeci/android -f ContainerShip/Dockerfile.android .",