From 078d6e3a9d36d8e58201e0e33e58ca5137ec8c10 Mon Sep 17 00:00:00 2001 From: Oleksandr Sokolov Date: Fri, 8 Jun 2018 08:24:47 -0700 Subject: [PATCH 01/22] QuickPerformanceLogger.js: markerPoint + iOS/Android JS binding Reviewed By: alexeylang Differential Revision: D8125546 fbshipit-source-id: bb02921c7d89faba64001bff3b9aaf13f64a7f8b --- .../Performance/QuickPerformanceLogger.js | 11 +++++ .../src/main/jni/react/jni/JSCPerfLogging.cpp | 41 ++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/Libraries/Performance/QuickPerformanceLogger.js b/Libraries/Performance/QuickPerformanceLogger.js index 360d5b96a8a510..6d50626b1fe700 100644 --- a/Libraries/Performance/QuickPerformanceLogger.js +++ b/Libraries/Performance/QuickPerformanceLogger.js @@ -81,6 +81,17 @@ const QuickPerformanceLogger = { } }, + markerPoint( + markerId: number, + name: string, + instanceKey: number = DUMMY_INSTANCE_KEY, + timestamp: number = AUTO_SET_TIMESTAMP, + ): void { + if (global.nativeQPLMarkerPoint) { + global.nativeQPLMarkerPoint(markerId, name, instanceKey, timestamp); + } + }, + currentTimestamp(): number { if (global.nativeQPLTimestamp) { return global.nativeQPLTimestamp(); diff --git a/ReactAndroid/src/main/jni/react/jni/JSCPerfLogging.cpp b/ReactAndroid/src/main/jni/react/jni/JSCPerfLogging.cpp index ea9c7285ec8045..6516932e196163 100644 --- a/ReactAndroid/src/main/jni/react/jni/JSCPerfLogging.cpp +++ b/ReactAndroid/src/main/jni/react/jni/JSCPerfLogging.cpp @@ -62,6 +62,12 @@ struct JQuickPerformanceLogger : JavaClass { javaClassStatic()->getMethod("currentMonotonicTimestamp"); return currentTimestampMethod(self()); } + + void markerPoint(int markerId, alias_ref name, int instanceKey) { + static auto markerPointMethod = + javaClassStatic()->getMethod)>("markerPoint"); + markerPointMethod(self(), markerId, instanceKey, name); + } }; struct JQuickPerformanceLoggerProvider : JavaClass { @@ -106,6 +112,14 @@ static bool isNan(double value) { return (value != value); } +static double grabDouble( + JSContextRef ctx, + const JSValueRef arguments[], + size_t argumentIndex, + JSValueRef* exception) { + return JSValueToNumber(ctx, arguments[argumentIndex], exception); +} + // Safely translates JSValues to an array of doubles. static bool grabDoubles( size_t targetsCount, @@ -118,7 +132,7 @@ static bool grabDoubles( return false; } for (size_t i = 0 ; i < targetsCount ; i++) { - targets[i] = JSValueToNumber(ctx, arguments[i], exception); + targets[i] = grabDouble(ctx, arguments, i, exception); if (isNan(targets[i])) { return false; } @@ -254,6 +268,30 @@ static JSValueRef nativeQPLTimestamp( return JSValueMakeNumber(ctx, timestamp); } +static JSValueRef nativeQPLMarkerPoint( + JSContextRef ctx, + JSObjectRef function, + JSObjectRef thisObject, + size_t argumentCount, + const JSValueRef arguments[], + JSValueRef* exception) { + if (isReady() && argumentCount == 4) { + double markerIdArgument = grabDouble(ctx, arguments, 0, exception); + double instanceKeyArgument = grabDouble(ctx, arguments, 2, exception); + if (isNan(markerIdArgument) || isNan(instanceKeyArgument)) { + return JSValueMakeUndefined(ctx); + } + + int32_t markerId = (int32_t) markerIdArgument; + local_ref name = getJStringFromJSValueRef(ctx, arguments[1]); + int32_t instanceKey = (int32_t) instanceKeyArgument; + // timestamp is not used as QuickPerformanceLogger::markerPoint with all + // params is missing + JQuickPerformanceLoggerProvider::get()->markerPoint(markerId, name, instanceKey); + } + return JSValueMakeUndefined(ctx); +} + void addNativePerfLoggingHooks(JSGlobalContextRef ctx) { installGlobalFunction(ctx, "nativeQPLMarkerStart", nativeQPLMarkerStart); installGlobalFunction(ctx, "nativeQPLMarkerEnd", nativeQPLMarkerEnd); @@ -262,6 +300,7 @@ void addNativePerfLoggingHooks(JSGlobalContextRef ctx) { installGlobalFunction(ctx, "nativeQPLMarkerNote", nativeQPLMarkerNote); installGlobalFunction(ctx, "nativeQPLMarkerCancel", nativeQPLMarkerCancel); installGlobalFunction(ctx, "nativeQPLTimestamp", nativeQPLTimestamp); + installGlobalFunction(ctx, "nativeQPLMarkerPoint", nativeQPLMarkerPoint); } } } From 8b62e7a5506f335c35ce3bd33dbf599426cb3fbf Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Fri, 8 Jun 2018 20:16:13 -0700 Subject: [PATCH 02/22] Fabric: Using Size instead of Point as textShadowOffset's type Summary: The current implementation of React Native uses `Size` as the underlying type of `textShadowOffset` which is clearly terribly wrong (especially because negative size values makes no sense). This mistake was borrowed from `NSShadow`, I believe. I don't have time to fix this in every implementation of RN now, so let's use `Size` in Fabric as well. Reviewed By: fkgozali Differential Revision: D8246714 fbshipit-source-id: 1f0bf9b9dfa83802ef3faef2971fed5510494bfd --- ReactCommon/fabric/attributedstring/TextAttributes.h | 3 ++- ReactCommon/fabric/textlayoutmanager/RCTAttributedTextUtils.mm | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ReactCommon/fabric/attributedstring/TextAttributes.h b/ReactCommon/fabric/attributedstring/TextAttributes.h index c474e7e2aa6ad8..584387bf5471eb 100644 --- a/ReactCommon/fabric/attributedstring/TextAttributes.h +++ b/ReactCommon/fabric/attributedstring/TextAttributes.h @@ -57,7 +57,8 @@ class TextAttributes: folly::Optional textDecorationLinePattern {}; // Shadow - folly::Optional textShadowOffset {}; + // TODO: Use `Point` type instead of `Size` for `textShadowOffset` attribute. + folly::Optional textShadowOffset {}; Float textShadowRadius {std::numeric_limits::quiet_NaN()}; SharedColor textShadowColor {nullptr}; diff --git a/ReactCommon/fabric/textlayoutmanager/RCTAttributedTextUtils.mm b/ReactCommon/fabric/textlayoutmanager/RCTAttributedTextUtils.mm index 11d4db50c07560..542b7859f0713e 100644 --- a/ReactCommon/fabric/textlayoutmanager/RCTAttributedTextUtils.mm +++ b/ReactCommon/fabric/textlayoutmanager/RCTAttributedTextUtils.mm @@ -154,7 +154,7 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex if (textAttributes.textShadowOffset.hasValue()) { auto textShadowOffset = textAttributes.textShadowOffset.value(); NSShadow *shadow = [NSShadow new]; - shadow.shadowOffset = CGSize {textShadowOffset.x, textShadowOffset.y}; + shadow.shadowOffset = CGSize {textShadowOffset.width, textShadowOffset.height}; shadow.shadowBlurRadius = textAttributes.textShadowRadius; shadow.shadowColor = RCTUIColorFromSharedColor(textAttributes.textShadowColor); attributes[NSShadowAttributeName] = shadow; From bb9bf2616956cfc3559642a847b113ea905aa6e6 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Fri, 8 Jun 2018 20:16:15 -0700 Subject: [PATCH 03/22] Fabric: Using exact UIFontWeight* constants instead of CGFloat Summary: SUDDENLY, `-[UIFont systemFontOfSize:weight:]` returns incorrect result if `weight` is not exactly equal to any of built-in constants. Reviewed By: fkgozali Differential Revision: D8246712 fbshipit-source-id: 13d59cc8d66a4494437f28d791fd93fa83ebe6fb --- .../fabric/textlayoutmanager/RCTFontUtils.mm | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/ReactCommon/fabric/textlayoutmanager/RCTFontUtils.mm b/ReactCommon/fabric/textlayoutmanager/RCTFontUtils.mm index 38a3d80f5a5d6f..954051f864bd3a 100644 --- a/ReactCommon/fabric/textlayoutmanager/RCTFontUtils.mm +++ b/ReactCommon/fabric/textlayoutmanager/RCTFontUtils.mm @@ -7,6 +7,7 @@ #import "RCTFontUtils.h" +#import #import static RCTFontProperties RCTDefaultFontProperties() { @@ -55,6 +56,25 @@ static RCTFontStyle RCTGetFontStyle(UIFont *font) { return @[]; } +static UIFontWeight RCTUIFontWeightFromFloat(CGFloat fontWeight) { + // Note: Even if the underlying type of `UIFontWeight` is `CGFloat` + // and UIKit uses the same numerical notation, we have to use exact + // `UIFontWeight*` constants to make it work properly (because + // float values comparison is tricky). + static UIFontWeight weights[] = { + /* ~100 */ UIFontWeightUltraLight, + /* ~200 */ UIFontWeightThin, + /* ~300 */ UIFontWeightLight, + /* ~400 */ UIFontWeightRegular, + /* ~500 */ UIFontWeightMedium, + /* ~600 */ UIFontWeightSemibold, + /* ~700 */ UIFontWeightBold, + /* ~800 */ UIFontWeightHeavy, + /* ~900 */ UIFontWeightBlack + }; + return weights[std::llround((fontWeight / 100) - 1)]; +} + static UIFont *RCTDefaultFontWithFontProperties(RCTFontProperties fontProperties) { static NSCache *fontCache; static std::mutex fontCacheMutex; @@ -72,7 +92,7 @@ static RCTFontStyle RCTGetFontStyle(UIFont *font) { if (!font) { font = [UIFont systemFontOfSize:fontProperties.size - weight:fontProperties.weight]; + weight:RCTUIFontWeightFromFloat(fontProperties.weight)]; if (fontProperties.variant == RCTFontStyleItalic) { UIFontDescriptor *fontDescriptor = [font fontDescriptor]; @@ -114,7 +134,7 @@ static RCTFontStyle RCTGetFontStyle(UIFont *font) { if (!font) { // Failback to system font. - font = [UIFont systemFontOfSize:effectiveFontSize weight:fontProperties.weight]; + font = [UIFont systemFontOfSize:effectiveFontSize weight:RCTUIFontWeightFromFloat(fontProperties.weight)]; } } else { // Get the closest font that matches the given weight for the fontFamily From d01290dd34c0274f49adcd75b7488c90fe70f562 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Fri, 8 Jun 2018 20:16:17 -0700 Subject: [PATCH 04/22] Fabric: Data model of Touch Events Summary: The data model of Touch events and payload serialization. The implementation mimics W3C standard and current React Native implementation. Reviewed By: fkgozali Differential Revision: D8246711 fbshipit-source-id: 955b2068674f290d8bdb82da1ebfb796dd32971b --- ReactCommon/fabric/view/ViewEventHandlers.cpp | 49 ++++++++++ ReactCommon/fabric/view/ViewEventHandlers.h | 90 +++++++++++++++++++ 2 files changed, 139 insertions(+) diff --git a/ReactCommon/fabric/view/ViewEventHandlers.cpp b/ReactCommon/fabric/view/ViewEventHandlers.cpp index e673d077efb94d..3cdadd3527c68d 100644 --- a/ReactCommon/fabric/view/ViewEventHandlers.cpp +++ b/ReactCommon/fabric/view/ViewEventHandlers.cpp @@ -38,5 +38,54 @@ void ViewEventHandlers::onLayout(const LayoutMetrics &layoutMetrics) const { dispatchEvent("layout", payload); } +#pragma mark - Touches + +static folly::dynamic touchPayload(const Touch &touch) { + folly::dynamic object = folly::dynamic::object(); + object["locationX"] = touch.offsetPoint.x; + object["locationY"] = touch.offsetPoint.x; + object["pageX"] = touch.pagePoint.x; + object["pageY"] = touch.pagePoint.x; + object["screenX"] = touch.screenPoint.x; + object["screenY"] = touch.screenPoint.x; + object["identifier"] = touch.identifier; + object["target"] = touch.target; + object["timestamp"] = touch.timestamp * 1000; + object["force"] = touch.force; + return object; +} + +static folly::dynamic touchesPayload(const Touches &touches) { + folly::dynamic array = folly::dynamic::array(); + for (auto &&touch : touches) { + array.push_back(touchPayload(touch)); + } + return array; +} + +static folly::dynamic touchEventPayload(const TouchEvent &event) { + folly::dynamic object = folly::dynamic::object(); + object["touches"] = touchesPayload(event.touches); + object["changedTouches"] = touchesPayload(event.changedTouches); + object["targetTouches"] = touchesPayload(event.targetTouches); + return object; +} + +void ViewEventHandlers::onTouchStart(const TouchEvent &event) const { + dispatchEvent("touchStart", touchEventPayload(event)); +} + +void ViewEventHandlers::onTouchMove(const TouchEvent &event) const { + dispatchEvent("touchMove", touchEventPayload(event)); +} + +void ViewEventHandlers::onTouchEnd(const TouchEvent &event) const { + dispatchEvent("touchEnd", touchEventPayload(event)); +} + +void ViewEventHandlers::onTouchCancel(const TouchEvent &event) const { + dispatchEvent("touchCancel", touchEventPayload(event)); +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/fabric/view/ViewEventHandlers.h b/ReactCommon/fabric/view/ViewEventHandlers.h index e72e41f345b82b..654649ed384ab8 100644 --- a/ReactCommon/fabric/view/ViewEventHandlers.h +++ b/ReactCommon/fabric/view/ViewEventHandlers.h @@ -10,10 +10,93 @@ #include #include +#include namespace facebook { namespace react { +/* + * Describes an individual touch point for a touch event. + * See https://www.w3.org/TR/touch-events/ for more details. + */ +struct Touch { + /* + * The coordinate of point relative to the root component in points. + */ + Point pagePoint; + + /* + * The coordinate of point relative to the target component in points. + */ + Point offsetPoint; + + /* + * The coordinate of point relative to the screen component in points. + */ + Point screenPoint; + + /* + * An identification number for each touch point. + */ + int identifier; + + /* + * The tag of a component on which the touch point started when it was first placed on the surface, + * even if the touch point has since moved outside the interactive area of that element. + */ + Tag target; + + /* + * The force of the touch. + */ + Float force; + + /* + * The time in seconds when the touch occurred or when it was last mutated. + */ + Float timestamp; + + /* + * The particular implementation of `Hasher` and (especially) `Comparator` + * make sense only when `Touch` object is used as a *key* in indexed collections. + * Because of that they are expressed as separate classes. + */ + struct Hasher { + size_t operator()(const Touch &touch) const { + return std::hash()(touch.identifier); + } + }; + + struct Comparator { + bool operator()(const Touch &lhs, const Touch &rhs) const { + return lhs.identifier == rhs.identifier; + } + }; +}; + +using Touches = std::unordered_set; + +/* + * Defines the `touchstart`, `touchend`, `touchmove`, and `touchcancel` event types. + */ +struct TouchEvent { + /* + * A list of Touches for every point of contact currently touching the surface. + */ + Touches touches; + + /* + * A list of Touches for every point of contact which contributed to the event. + */ + Touches changedTouches; + + /* + * A list of Touches for every point of contact that is touching the surface + * and started on the element that is the target of the current event. + */ + Touches targetTouches; +}; + class ViewEventHandlers; using SharedViewEventHandlers = std::shared_ptr; @@ -34,6 +117,13 @@ class ViewEventHandlers: #pragma mark - Layout void onLayout(const LayoutMetrics &layoutMetrics) const; + +#pragma mark - Touches + + void onTouchStart(const TouchEvent &event) const; + void onTouchMove(const TouchEvent &event) const; + void onTouchEnd(const TouchEvent &event) const; + void onTouchCancel(const TouchEvent &event) const; }; } // namespace react From a32be38017fa635152b40ede35d9a5c06f69aa72 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Fri, 8 Jun 2018 20:16:19 -0700 Subject: [PATCH 05/22] Fabric: Introducing RCTSurfaceTouchHandler Summary: RCTSurfaceTouchHandler is a complete rewrite of RCTTouchHandler which uses direct Fabric-specific event dispatching pipeline and several new approaches to managing active events (such as high-performant C++ collections, better management of identifier pool, and so on). Besides that, the new implementation is much more W3C compliant that it used to be (see old TODOs near `receiveTouches()` implementation in Javascript). So, touch events work now! Reviewed By: fkgozali Differential Revision: D8246713 fbshipit-source-id: 218dc15cd8f982237de7e2497ff36a7bfe6d37cc --- .../View/RCTViewComponentView.mm | 5 + React/Fabric/RCTSurfaceTouchHandler.h | 19 + React/Fabric/RCTSurfaceTouchHandler.mm | 360 ++++++++++++++++++ React/Fabric/Surface/RCTFabricSurface.mm | 7 +- 4 files changed, 389 insertions(+), 2 deletions(-) create mode 100644 React/Fabric/RCTSurfaceTouchHandler.h create mode 100644 React/Fabric/RCTSurfaceTouchHandler.mm diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 189850df909503..fb688d03192492 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -67,4 +67,9 @@ - (BOOL)didActivateAccessibilityCustomAction:(UIAccessibilityCustomAction *)acti return YES; } +- (SharedEventHandlers)touchEventHandlers +{ + return _eventHandlers; +} + @end diff --git a/React/Fabric/RCTSurfaceTouchHandler.h b/React/Fabric/RCTSurfaceTouchHandler.h new file mode 100644 index 00000000000000..670ef284832ca9 --- /dev/null +++ b/React/Fabric/RCTSurfaceTouchHandler.h @@ -0,0 +1,19 @@ +/** + * 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. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface RCTSurfaceTouchHandler : UIGestureRecognizer + +- (void)attachToView:(UIView *)view; +- (void)detachFromView:(UIView *)view; + +@end + +NS_ASSUME_NONNULL_END diff --git a/React/Fabric/RCTSurfaceTouchHandler.mm b/React/Fabric/RCTSurfaceTouchHandler.mm new file mode 100644 index 00000000000000..09f586646d7fa3 --- /dev/null +++ b/React/Fabric/RCTSurfaceTouchHandler.mm @@ -0,0 +1,360 @@ +/** + * 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. + */ + +#import "RCTSurfaceTouchHandler.h" + +#import +#import +#import +#import + +#import "RCTConversions.h" + +using namespace facebook::react; + +template +class IdentifierPool { +public: + + void enqueue(int index) { + usage[index] = false; + } + + int dequeue() { + while (true) { + if (!usage[lastIndex]) { + usage[lastIndex] = true; + return lastIndex; + } + lastIndex = (lastIndex + 1) % size; + } + } + + void reset() { + for (int i = 0; i < size; i++) { + usage[i] = false; + } + } + +private: + + bool usage[size]; + int lastIndex; +}; + +@protocol RCTTouchableComponentViewProtocol + - (SharedViewEventHandlers)touchEventHandlers; +@end + +typedef NS_ENUM(NSInteger, RCTTouchEventType) { + RCTTouchEventTypeTouchStart, + RCTTouchEventTypeTouchMove, + RCTTouchEventTypeTouchEnd, + RCTTouchEventTypeTouchCancel, +}; + +struct ActiveTouch { + Touch touch; + SharedViewEventHandlers eventHandlers; + + struct Hasher { + size_t operator()(const ActiveTouch &activeTouch) const { + return std::hash()(activeTouch.touch.identifier); + } + }; + + struct Comparator { + bool operator()(const ActiveTouch &lhs, const ActiveTouch &rhs) const { + return lhs.touch.identifier == rhs.touch.identifier; + } + }; +}; + +static void UpdateActiveTouchWithUITouch(ActiveTouch &activeTouch, UITouch *uiTouch, UIView *rootComponentView) { + CGPoint offsetPoint = [uiTouch locationInView:uiTouch.view]; + CGPoint screenPoint = [uiTouch locationInView:uiTouch.window]; + CGPoint pagePoint = [uiTouch locationInView:rootComponentView]; + + activeTouch.touch.offsetPoint = RCTPointFromCGPoint(offsetPoint); + activeTouch.touch.screenPoint = RCTPointFromCGPoint(screenPoint); + activeTouch.touch.pagePoint = RCTPointFromCGPoint(pagePoint); + + activeTouch.touch.timestamp = uiTouch.timestamp; + + if (RCTForceTouchAvailable()) { + activeTouch.touch.force = uiTouch.force / uiTouch.maximumPossibleForce; + } +} + +static ActiveTouch CreateTouchWithUITouch(UITouch *uiTouch, UIView *rootComponentView) { + UIView *componentView = uiTouch.view; + + ActiveTouch activeTouch = {}; + + if ([componentView respondsToSelector:@selector(touchEventHandlers)]) { + activeTouch.eventHandlers = [(id)componentView touchEventHandlers]; + activeTouch.touch.target = (Tag)componentView.tag; + } + + UpdateActiveTouchWithUITouch(activeTouch, uiTouch, rootComponentView); + return activeTouch; +} + +static BOOL AllTouchesAreCancelledOrEnded(NSSet *touches) { + for (UITouch *touch in touches) { + if (touch.phase == UITouchPhaseBegan || + touch.phase == UITouchPhaseMoved || + touch.phase == UITouchPhaseStationary) { + return NO; + } + } + return YES; +} + +static BOOL AnyTouchesChanged(NSSet *touches) { + for (UITouch *touch in touches) { + if (touch.phase == UITouchPhaseBegan || + touch.phase == UITouchPhaseMoved) { + return YES; + } + } + return NO; +} + +/** + * Surprisingly, `__unsafe_unretained id` pointers are not regular pointers + * and `std::hash<>` cannot hash them. + * This is quite trivial but decent implementation of hasher function + * inspired by this research: https://stackoverflow.com/a/21062520/496389. + */ +template +struct PointerHasher { + constexpr std::size_t operator()(const PointerT &value) const { + return reinterpret_cast(&value); + } +}; + +@interface RCTSurfaceTouchHandler () +@end + +@implementation RCTSurfaceTouchHandler { + std::unordered_map< + __unsafe_unretained UITouch *, + ActiveTouch, + PointerHasher<__unsafe_unretained UITouch *> + > _activeTouches; + + UIView *_rootComponentView; + IdentifierPool<11> _identifierPool; +} + +- (instancetype)init +{ + if (self = [super initWithTarget:nil action:nil]) { + // `cancelsTouchesInView` and `delaysTouches*` are needed in order + // to be used as a top level event delegated recognizer. + // Otherwise, lower-level components not built using React Native, + // will fail to recognize gestures. + self.cancelsTouchesInView = NO; + self.delaysTouchesBegan = NO; // This is default value. + self.delaysTouchesEnded = NO; + + self.delegate = self; + } + + return self; +} + +RCT_NOT_IMPLEMENTED(- (instancetype)initWithTarget:(id)target action:(SEL)action) + +- (void)attachToView:(UIView *)view +{ + RCTAssert(self.view == nil, @"RCTTouchHandler already has attached view."); + + [view addGestureRecognizer:self]; + _rootComponentView = view; +} + +- (void)detachFromView:(UIView *)view +{ + RCTAssertParam(view); + RCTAssert(self.view == view, @"RCTTouchHandler attached to another view."); + + [view removeGestureRecognizer:self]; + _rootComponentView = nil; +} + +- (void)_registerTouches:(NSSet *)touches +{ + for (UITouch *touch in touches) { + auto &&activeTouch = CreateTouchWithUITouch(touch, _rootComponentView); + activeTouch.touch.identifier = _identifierPool.dequeue(); + _activeTouches.emplace(touch, activeTouch); + } +} + +- (void)_updateTouches:(NSSet *)touches +{ + for (UITouch *touch in touches) { + UpdateActiveTouchWithUITouch(_activeTouches[touch], touch, _rootComponentView); + } +} + +- (void)_unregisterTouches:(NSSet *)touches +{ + for (UITouch *touch in touches) { + auto &&activeTouch = _activeTouches[touch]; + _identifierPool.enqueue(activeTouch.touch.identifier); + _activeTouches.erase(touch); + } +} + +- (void)_dispatchTouches:(NSSet *)touches eventType:(RCTTouchEventType)eventType +{ + TouchEvent event = {}; + std::unordered_set changedActiveTouches = {}; + std::unordered_set uniqueEventHandlers = {}; + BOOL isEndishEventType = eventType == RCTTouchEventTypeTouchEnd || eventType == RCTTouchEventTypeTouchCancel; + + for (UITouch *touch in touches) { + auto &&activeTouch = _activeTouches[touch]; + + if (!activeTouch.eventHandlers) { + continue; + } + + changedActiveTouches.insert(activeTouch); + event.changedTouches.insert(activeTouch.touch); + uniqueEventHandlers.insert(activeTouch.eventHandlers); + } + + for (auto &&pair : _activeTouches) { + if (!pair.second.eventHandlers) { + continue; + } + + if ( + isEndishEventType && + event.changedTouches.find(pair.second.touch) != event.changedTouches.end() + ) { + continue; + } + + event.touches.insert(pair.second.touch); + } + + for (auto &&eventHandlers : uniqueEventHandlers) { + event.targetTouches.clear(); + + for (auto &&pair : _activeTouches) { + if (pair.second.eventHandlers == eventHandlers) { + event.targetTouches.insert(pair.second.touch); + } + } + + switch (eventType) { + case RCTTouchEventTypeTouchStart: + eventHandlers->onTouchStart(event); + break; + case RCTTouchEventTypeTouchMove: + eventHandlers->onTouchMove(event); + break; + case RCTTouchEventTypeTouchEnd: + eventHandlers->onTouchEnd(event); + break; + case RCTTouchEventTypeTouchCancel: + eventHandlers->onTouchCancel(event); + break; + } + } +} + +#pragma mark - `UIResponder`-ish touch-delivery methods + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesBegan:touches withEvent:event]; + + [self _registerTouches:touches]; + [self _dispatchTouches:touches eventType:RCTTouchEventTypeTouchStart]; + + if (self.state == UIGestureRecognizerStatePossible) { + self.state = UIGestureRecognizerStateBegan; + } else if (self.state == UIGestureRecognizerStateBegan) { + self.state = UIGestureRecognizerStateChanged; + } +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesMoved:touches withEvent:event]; + + [self _updateTouches:touches]; + [self _dispatchTouches:touches eventType:RCTTouchEventTypeTouchMove]; + + self.state = UIGestureRecognizerStateChanged; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesEnded:touches withEvent:event]; + + [self _updateTouches:touches]; + [self _dispatchTouches:touches eventType:RCTTouchEventTypeTouchEnd]; + [self _unregisterTouches:touches]; + + if (AllTouchesAreCancelledOrEnded(event.allTouches)) { + self.state = UIGestureRecognizerStateEnded; + } else if (AnyTouchesChanged(event.allTouches)) { + self.state = UIGestureRecognizerStateChanged; + } +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesCancelled:touches withEvent:event]; + + [self _updateTouches:touches]; + [self _dispatchTouches:touches eventType:RCTTouchEventTypeTouchCancel]; + [self _unregisterTouches:touches]; + + if (AllTouchesAreCancelledOrEnded(event.allTouches)) { + self.state = UIGestureRecognizerStateCancelled; + } else if (AnyTouchesChanged(event.allTouches)) { + self.state = UIGestureRecognizerStateChanged; + } +} + +- (void)reset +{ + // Technically, `_activeTouches` must be already empty at this point, + // but just to be sure, we clear it explicitly. + _activeTouches.clear(); + _identifierPool.reset(); +} + +- (BOOL)canPreventGestureRecognizer:(__unused UIGestureRecognizer *)preventedGestureRecognizer +{ + return NO; +} + +- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer +{ + // We fail in favour of other external gesture recognizers. + // iOS will ask `delegate`'s opinion about this gesture recognizer little bit later. + return ![preventingGestureRecognizer.view isDescendantOfView:self.view]; +} + +#pragma mark - UIGestureRecognizerDelegate + +- (BOOL)gestureRecognizer:(__unused UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer +{ + // Same condition for `failure of` as for `be prevented by`. + return [self canBePreventedByGestureRecognizer:otherGestureRecognizer]; +} + +@end diff --git a/React/Fabric/Surface/RCTFabricSurface.mm b/React/Fabric/Surface/RCTFabricSurface.mm index 3028a204e97e53..2e06d361d01e31 100644 --- a/React/Fabric/Surface/RCTFabricSurface.mm +++ b/React/Fabric/Surface/RCTFabricSurface.mm @@ -17,7 +17,7 @@ #import #import #import -#import +#import #import #import @@ -39,7 +39,7 @@ @implementation RCTFabricSurface { // The Main thread only RCTSurfaceView *_Nullable _view; - RCTTouchHandler *_Nullable _touchHandler; + RCTSurfaceTouchHandler *_Nullable _touchHandler; } - (instancetype)initWithBridge:(RCTBridge *)bridge @@ -71,6 +71,8 @@ - (instancetype)initWithSurfacePresenter:(RCTSurfacePresenter *)surfacePresenter _stage = RCTSurfaceStageSurfaceDidInitialize; + _touchHandler = [RCTSurfaceTouchHandler new]; + [self _run]; } @@ -102,6 +104,7 @@ - (RCTSurfaceView *)view if (!_view) { _view = [[RCTSurfaceView alloc] initWithSurface:(RCTSurface *)self]; + [_touchHandler attachToView:_view]; } return _view; From 7f1ed6848f89bdccc7f7a5cc76019eec67e76b2f Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Fri, 8 Jun 2018 20:16:22 -0700 Subject: [PATCH 06/22] Fabric: `convertRawProp` was extended to accept an optional default value Summary: During transforming raw prop (`rawProps[]`) to typed props (`MyProps.`) we can face three different cases: * `rawProps` collection has proper serialized value for the key. In this case, we have to set a new value of the typed prop converting value using `fromDynamic`. * `rawProps` collection does not have value for the key. In this case, we have to copy a value from source prop (`sourceValue`). * `rawProps` collection has `null` value for the key. This is the special case which means that the prop was removed from the particular component instance and we have to reset it to some *default* value (which is *not* the same as `sourceValue`). Now the default value of the `defaultValue` (sic!) argument is a default value of the type of the value (which may be different from logical default value). We didn't handle the last case previously and this caused crashes (and unexpected behavior) because `fromDynamic` often cannot handle `null` value. And yes, all this mean that we also have to update all `convertRawProp` call sites where logical default values are not equal to type-specific default values. This is a potential error-prone place, especially because now we have to specify logical default values in two places (in a prop declaration and in a parameterized constructor). And seems there is no way to avoid that without performance loss (because both of those places are basically constructors). My hope is that codegen (where default values are also defined in JavaScript) will help with it eventually. Reviewed By: fkgozali Differential Revision: D8247652 fbshipit-source-id: 2cbe65f5f5cccd7a0d34aaa19e385aacebfe8cb1 --- ReactCommon/fabric/core/propsConversions.h | 30 +++++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/ReactCommon/fabric/core/propsConversions.h b/ReactCommon/fabric/core/propsConversions.h index f4a25f8dff9e2e..548b88f3de4aa0 100644 --- a/ReactCommon/fabric/core/propsConversions.h +++ b/ReactCommon/fabric/core/propsConversions.h @@ -21,33 +21,49 @@ inline void fromDynamic(const folly::dynamic &value, int &result) { result = val inline void fromDynamic(const folly::dynamic &value, std::string &result) { result = value.getString(); } template -inline T convertRawProp(const RawProps &rawProps, const std::string &name, const T &defaultValue) { +inline T convertRawProp( + const RawProps &rawProps, + const std::string &name, + const T &sourceValue, + const T &defaultValue = T() +) { auto &&iterator = rawProps.find(name); if (iterator == rawProps.end()) { - return defaultValue; + return sourceValue; } auto &&value = iterator->second; + + // Special case: `null` always means `the prop was removed, use default value`. + if (value.isNull()) { + return defaultValue; + } + T result; fromDynamic(value, result); return result; } template -inline static folly::Optional convertRawProp(const RawProps &rawProps, const std::string &name, const folly::Optional &defaultValue) { +inline static folly::Optional convertRawProp( + const RawProps &rawProps, + const std::string &name, + const folly::Optional &sourceValue, + const folly::Optional &defaultValue = {} +) { auto &&iterator = rawProps.find(name); if (iterator == rawProps.end()) { - return defaultValue; + return sourceValue; } auto &&value = iterator->second; - T result; - // Special case for optionals: `null` always means `no value`. + // Special case: `null` always means `the prop was removed, use default value`. if (value.isNull()) { - return {}; + return defaultValue; } + T result; fromDynamic(value, result); return result; } From 63540874eccba29cff42d33088ebe8c92c602647 Mon Sep 17 00:00:00 2001 From: Eli White Date: Fri, 8 Jun 2018 20:24:34 -0700 Subject: [PATCH 07/22] Bump eslint-plugin-react in FBSource Reviewed By: yungsters Differential Revision: D8247892 fbshipit-source-id: 4072e65ccf2fdc654f58087a16b4c7709ce393f8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f36d371e663014..db192e67092c6f 100644 --- a/package.json +++ b/package.json @@ -210,7 +210,7 @@ "eslint-plugin-flowtype": "2.43.0", "eslint-plugin-jest": "21.8.0", "eslint-plugin-prettier": "2.6.0", - "eslint-plugin-react": "7.6.1", + "eslint-plugin-react": "7.8.2", "eslint-plugin-react-native": "^3.2.1", "flow-bin": "^0.73.0", "jest": "23.1.0", From c55bcd6ea729cdf57fc14a5478b7c2e3f6b2a94d Mon Sep 17 00:00:00 2001 From: Joshua Wang Date: Sat, 9 Jun 2018 00:19:06 -0700 Subject: [PATCH 08/22] have circle ci use xcode 9.4 (#19629) Summary: Circle CI just released Xcode 9.4 https://discuss.circleci.com/t/xcode-9-4-availability-on-circleci/22648/5 Make sure react native still works with Xcode 9.4. None [IOS][MINOR] Upgrade CI Closes https://github.com/facebook/react-native/pull/19629 Differential Revision: D8343236 Pulled By: hramos fbshipit-source-id: 2266aeafc9a1b1c77ad842f06c9a137bb05b135d --- .circleci/config.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 31ea483c70c86d..f77c7392272bb2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -316,7 +316,7 @@ android_defaults: &android_defaults macos_defaults: &macos_defaults <<: *defaults macos: - xcode: "9.2.0" + xcode: "9.4.0" version: 2 jobs: @@ -374,9 +374,8 @@ jobs: - attach_workspace: at: ~/react-native - - run: xcrun instruments -w "iPhone 5s (11.2)" || true + - run: xcrun instruments -w "iPhone 5s (11.4)" || true # See https://github.com/Homebrew/homebrew-core/issues/26358. - - run: brew upgrade python > /dev/null - run: brew install watchman - run: *run-objc-ios-tests @@ -390,9 +389,8 @@ jobs: - attach_workspace: at: ~/react-native - - run: xcrun instruments -w "Apple TV 1080p (11.2)" || true + - run: xcrun instruments -w "Apple TV (11.4)" || true # See https://github.com/Homebrew/homebrew-core/issues/26358. - - run: brew upgrade python > /dev/null - run: brew install watchman - run: *run-objc-tvos-tests @@ -406,7 +404,7 @@ jobs: - attach_workspace: at: ~/react-native - - run: xcrun instruments -w "iPhone 5s (11.2)" || true + - run: xcrun instruments -w "iPhone 5s (11.4)" || true - run: *run-objc-ios-e2e-tests - store_test_results: From 521fb6d041167ec8a8d0e98ac606db1f27f0c5c8 Mon Sep 17 00:00:00 2001 From: Eli White Date: Sat, 9 Jun 2018 10:57:39 -0700 Subject: [PATCH 09/22] Disallow requiring from invariant/warning (#19634) Summary: In this repo we have to require from fbjs/lib/invariant and issues occur when we require directly from invariant/warning. Flow doesn't complain about those requires right now because we have a transitive dependency on invariant and warning causing them to happen to be at the root of node_modules. This change blacklists requiring directly from invariant and warning using Flow. janicduplessis opened a pull request to do this with ESLint back in 2017: https://github.com/facebook/react-native/pull/13014 Closes https://github.com/facebook/react-native/pull/19634 Reviewed By: hramos Differential Revision: D8343060 Pulled By: TheSavior fbshipit-source-id: 9cfc7915b2fb68a567355fc2f5edc4dfcd46f4af --- .flowconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.flowconfig b/.flowconfig index 0d576609315e64..10c13ea400f5ec 100644 --- a/.flowconfig +++ b/.flowconfig @@ -25,6 +25,11 @@ ; Ignore metro .*/node_modules/metro/.* +; These should not be required directly +; require from fbjs/lib instead: require('fbjs/lib/invariant') +.*/node_modules/invariant/.* +.*/node_modules/warning/.* + [include] [libs] From d49ebbcf6278ef54739be0f99b43c743d898a582 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sat, 9 Jun 2018 13:02:55 -0700 Subject: [PATCH 10/22] Fabric: All *EventHandlers were renamed to *EventEmitter Summary: Using `EventHandlers` name was a bad idea, and I cannot tolerate it anymore. The worst part of it is that when you have a collection of `EventHandlers` objects you cannot use plural word to describe it because `EventHandlers` is an already plural word. And, this object is actually an event emitter, the thing on which we call events. Reviewed By: fkgozali Differential Revision: D8247723 fbshipit-source-id: b3303a4b9529bd6d32bb8ca0378287ebefaedda8 --- .../ScrollView/RCTScrollViewComponentView.mm | 20 ++++++------- .../View/RCTViewComponentView.h | 6 ++-- .../View/RCTViewComponentView.mm | 18 +++++------ ...tem.h => RCTUpdateEventEmitterMountItem.h} | 6 ++-- ...m.mm => RCTUpdateEventEmitterMountItem.mm} | 12 ++++---- .../Mounting/RCTComponentViewProtocol.h | 6 ++-- React/Fabric/Mounting/RCTMountingManager.mm | 18 +++++------ .../Mounting/UIView+ComponentViewProtocol.h | 2 +- .../Mounting/UIView+ComponentViewProtocol.mm | 2 +- React/Fabric/RCTSurfaceTouchHandler.mm | 30 +++++++++---------- .../componentdescriptor/ComponentDescriptor.h | 8 ++--- .../ConcreteComponentDescriptor.h | 22 +++++++------- .../fabric/core/events/EventDispatcher.h | 2 +- .../{EventHandlers.cpp => EventEmitter.cpp} | 12 ++++---- .../{EventHandlers.h => EventEmitter.h} | 10 +++---- .../core/shadownode/ConcreteShadowNode.h | 14 ++++----- .../fabric/core/shadownode/ShadowNode.cpp | 16 +++++----- .../fabric/core/shadownode/ShadowNode.h | 12 ++++---- .../fabric/core/tests/ShadowNodeTest.cpp | 6 ++-- ...andlers.cpp => ScrollViewEventEmitter.cpp} | 14 ++++----- ...entHandlers.h => ScrollViewEventEmitter.h} | 14 ++++----- .../fabric/scrollview/ScrollViewShadowNode.h | 4 +-- .../fabric/uimanager/FabricUIManager.cpp | 10 +++---- ReactCommon/fabric/uimanager/ShadowTree.cpp | 14 ++++----- .../fabric/view/ConcreteViewShadowNode.h | 22 +++++++------- ...EventHandlers.cpp => ViewEventEmitter.cpp} | 18 +++++------ ...ViewEventHandlers.h => ViewEventEmitter.h} | 12 ++++---- ReactCommon/fabric/view/ViewShadowNode.h | 2 +- 28 files changed, 166 insertions(+), 166 deletions(-) rename React/Fabric/Mounting/MountItems/{RCTUpdateEventHandlersMountItem.h => RCTUpdateEventEmitterMountItem.h} (68%) rename React/Fabric/Mounting/MountItems/{RCTUpdateEventHandlersMountItem.mm => RCTUpdateEventEmitterMountItem.mm} (65%) rename ReactCommon/fabric/core/events/{EventHandlers.cpp => EventEmitter.cpp} (80%) rename ReactCommon/fabric/core/events/{EventHandlers.h => EventEmitter.h} (83%) rename ReactCommon/fabric/scrollview/{ScrollViewEventHandlers.cpp => ScrollViewEventEmitter.cpp} (69%) rename ReactCommon/fabric/scrollview/{ScrollViewEventHandlers.h => ScrollViewEventEmitter.h} (77%) rename ReactCommon/fabric/view/{ViewEventHandlers.cpp => ViewEventEmitter.cpp} (79%) rename ReactCommon/fabric/view/{ViewEventHandlers.h => ViewEventEmitter.h} (92%) diff --git a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index e3b157a57dc84e..90e47e77f5d695 100644 --- a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -11,7 +11,7 @@ #import #import #import -#import +#import #import "RCTConversions.h" #import "RCTEnhancedScrollView.h" @@ -135,47 +135,47 @@ - (ScrollViewMetrics)_scrollViewMetrics - (void)scrollViewDidScroll:(UIScrollView *)scrollView { - std::static_pointer_cast(_eventHandlers)->onScroll([self _scrollViewMetrics]); + std::static_pointer_cast(_eventEmitter)->onScroll([self _scrollViewMetrics]); } - (void)scrollViewDidZoom:(UIScrollView *)scrollView { - std::static_pointer_cast(_eventHandlers)->onScroll([self _scrollViewMetrics]); + std::static_pointer_cast(_eventEmitter)->onScroll([self _scrollViewMetrics]); } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { - std::static_pointer_cast(_eventHandlers)->onScrollBeginDrag([self _scrollViewMetrics]); + std::static_pointer_cast(_eventEmitter)->onScrollBeginDrag([self _scrollViewMetrics]); } - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { - std::static_pointer_cast(_eventHandlers)->onScrollEndDrag([self _scrollViewMetrics]); + std::static_pointer_cast(_eventEmitter)->onScrollEndDrag([self _scrollViewMetrics]); } - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView { - std::static_pointer_cast(_eventHandlers)->onMomentumScrollBegin([self _scrollViewMetrics]); + std::static_pointer_cast(_eventEmitter)->onMomentumScrollBegin([self _scrollViewMetrics]); } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { - std::static_pointer_cast(_eventHandlers)->onMomentumScrollEnd([self _scrollViewMetrics]); + std::static_pointer_cast(_eventEmitter)->onMomentumScrollEnd([self _scrollViewMetrics]); } - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { - std::static_pointer_cast(_eventHandlers)->onMomentumScrollEnd([self _scrollViewMetrics]); + std::static_pointer_cast(_eventEmitter)->onMomentumScrollEnd([self _scrollViewMetrics]); } - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view { - std::static_pointer_cast(_eventHandlers)->onScrollBeginDrag([self _scrollViewMetrics]); + std::static_pointer_cast(_eventEmitter)->onScrollBeginDrag([self _scrollViewMetrics]); } - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale { - std::static_pointer_cast(_eventHandlers)->onScrollEndDrag([self _scrollViewMetrics]); + std::static_pointer_cast(_eventEmitter)->onScrollEndDrag([self _scrollViewMetrics]); } @end diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h index f0d482347e86ff..73c3302a65bcea 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h @@ -9,10 +9,10 @@ #import #import -#import +#import #import #import -#import +#import NS_ASSUME_NONNULL_BEGIN @@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN @protected facebook::react::LayoutMetrics _layoutMetrics; facebook::react::SharedProps _props; - facebook::react::SharedViewEventHandlers _eventHandlers; + facebook::react::SharedViewEventEmitter _eventEmitter; } @end diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index fb688d03192492..f6e74eda4b12a3 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -8,7 +8,7 @@ #import "RCTViewComponentView.h" #import -#import +#import using namespace facebook::react; @@ -33,10 +33,10 @@ - (void)updateProps:(SharedProps)props // TODO: Implement all sutable non-layout props. } -- (void)updateEventHandlers:(SharedEventHandlers)eventHandlers +- (void)updateEventEmitter:(SharedEventEmitter)eventEmitter { - assert(std::dynamic_pointer_cast(eventHandlers)); - _eventHandlers = std::static_pointer_cast(eventHandlers); + assert(std::dynamic_pointer_cast(eventEmitter)); + _eventEmitter = std::static_pointer_cast(eventEmitter); } - (void)updateLayoutMetrics:(LayoutMetrics)layoutMetrics @@ -51,25 +51,25 @@ - (void)updateLayoutMetrics:(LayoutMetrics)layoutMetrics - (BOOL)accessibilityActivate { - _eventHandlers->onAccessibilityTap(); + _eventEmitter->onAccessibilityTap(); return YES; } - (BOOL)accessibilityPerformMagicTap { - _eventHandlers->onAccessibilityMagicTap(); + _eventEmitter->onAccessibilityMagicTap(); return YES; } - (BOOL)didActivateAccessibilityCustomAction:(UIAccessibilityCustomAction *)action { - _eventHandlers->onAccessibilityAction([action.name cStringUsingEncoding:NSASCIIStringEncoding]); + _eventEmitter->onAccessibilityAction([action.name cStringUsingEncoding:NSASCIIStringEncoding]); return YES; } -- (SharedEventHandlers)touchEventHandlers +- (SharedEventEmitter)touchEventEmitter { - return _eventHandlers; + return _eventEmitter; } @end diff --git a/React/Fabric/Mounting/MountItems/RCTUpdateEventHandlersMountItem.h b/React/Fabric/Mounting/MountItems/RCTUpdateEventEmitterMountItem.h similarity index 68% rename from React/Fabric/Mounting/MountItems/RCTUpdateEventHandlersMountItem.h rename to React/Fabric/Mounting/MountItems/RCTUpdateEventEmitterMountItem.h index dd11971b8494b0..7db403b1dd33ae 100644 --- a/React/Fabric/Mounting/MountItems/RCTUpdateEventHandlersMountItem.h +++ b/React/Fabric/Mounting/MountItems/RCTUpdateEventEmitterMountItem.h @@ -9,17 +9,17 @@ #import #import -#import +#import NS_ASSUME_NONNULL_BEGIN /** * Updates event handlers of a component view. */ -@interface RCTUpdateEventHandlersMountItem : NSObject +@interface RCTUpdateEventEmitterMountItem : NSObject - (instancetype)initWithTag:(ReactTag)tag - eventHandlers:(facebook::react::SharedEventHandlers)eventHandlers; + eventEmitter:(facebook::react::SharedEventEmitter)eventEmitter; @end diff --git a/React/Fabric/Mounting/MountItems/RCTUpdateEventHandlersMountItem.mm b/React/Fabric/Mounting/MountItems/RCTUpdateEventEmitterMountItem.mm similarity index 65% rename from React/Fabric/Mounting/MountItems/RCTUpdateEventHandlersMountItem.mm rename to React/Fabric/Mounting/MountItems/RCTUpdateEventEmitterMountItem.mm index cc3066b059cf41..18de9cc3a5d097 100644 --- a/React/Fabric/Mounting/MountItems/RCTUpdateEventHandlersMountItem.mm +++ b/React/Fabric/Mounting/MountItems/RCTUpdateEventEmitterMountItem.mm @@ -5,23 +5,23 @@ * LICENSE file in the root directory of this source tree. */ -#import "RCTUpdateEventHandlersMountItem.h" +#import "RCTUpdateEventEmitterMountItem.h" #import "RCTComponentViewRegistry.h" using namespace facebook::react; -@implementation RCTUpdateEventHandlersMountItem { +@implementation RCTUpdateEventEmitterMountItem { ReactTag _tag; - SharedEventHandlers _eventHandlers; + SharedEventEmitter _eventEmitter; } - (instancetype)initWithTag:(ReactTag)tag - eventHandlers:(SharedEventHandlers)eventHandlers + eventEmitter:(SharedEventEmitter)eventEmitter { if (self = [super init]) { _tag = tag; - _eventHandlers = eventHandlers; + _eventEmitter = eventEmitter; } return self; @@ -31,7 +31,7 @@ - (void)executeWithRegistry:(RCTComponentViewRegistry *)registry { UIView *componentView = [registry componentViewByTag:_tag]; - [componentView updateEventHandlers:_eventHandlers]; + [componentView updateEventEmitter:_eventEmitter]; } @end diff --git a/React/Fabric/Mounting/RCTComponentViewProtocol.h b/React/Fabric/Mounting/RCTComponentViewProtocol.h index 47048efa1b5778..a426bfd081fe8e 100644 --- a/React/Fabric/Mounting/RCTComponentViewProtocol.h +++ b/React/Fabric/Mounting/RCTComponentViewProtocol.h @@ -7,7 +7,7 @@ #import -#import +#import #import #import #import @@ -55,10 +55,10 @@ NS_ASSUME_NONNULL_BEGIN /* * Called for updating component's event handlers set. - * Receiver must cache `eventHandlers` object inside and use it for emitting + * Receiver must cache `eventEmitter` object inside and use it for emitting * events when needed. */ -- (void)updateEventHandlers:(facebook::react::SharedEventHandlers)eventHandlers; +- (void)updateEventEmitter:(facebook::react::SharedEventEmitter)eventEmitter; /* * Called for updating component's layout metrics. diff --git a/React/Fabric/Mounting/RCTMountingManager.mm b/React/Fabric/Mounting/RCTMountingManager.mm index 93e8f0ea809aab..8df452c0c5b2e0 100644 --- a/React/Fabric/Mounting/RCTMountingManager.mm +++ b/React/Fabric/Mounting/RCTMountingManager.mm @@ -20,7 +20,7 @@ #import "RCTInsertMountItem.h" #import "RCTRemoveMountItem.h" #import "RCTUpdatePropsMountItem.h" -#import "RCTUpdateEventHandlersMountItem.h" +#import "RCTUpdateEventEmitterMountItem.h" #import "RCTUpdateLocalDataMountItem.h" #import "RCTUpdateLayoutMetricsMountItem.h" @@ -71,9 +71,9 @@ - (void)mutateComponentViewTreeWithMutationInstructions:(facebook::react::TreeMu oldProps:nullptr newProps:instruction.getNewChildNode()->getProps()]]; - // EventHandlers - [mountItems addObject:[[RCTUpdateEventHandlersMountItem alloc] initWithTag:instruction.getNewChildNode()->getTag() - eventHandlers:instruction.getNewChildNode()->getEventHandlers()]]; + // EventEmitter + [mountItems addObject:[[RCTUpdateEventEmitterMountItem alloc] initWithTag:instruction.getNewChildNode()->getTag() + eventEmitter:instruction.getNewChildNode()->getEventEmitter()]]; // LocalData if (instruction.getNewChildNode()->getLocalData()) { @@ -124,11 +124,11 @@ - (void)mutateComponentViewTreeWithMutationInstructions:(facebook::react::TreeMu [mountItems addObject:mountItem]; } - // EventHandlers - if (oldShadowNode->getEventHandlers() != newShadowNode->getEventHandlers()) { - RCTUpdateEventHandlersMountItem *mountItem = - [[RCTUpdateEventHandlersMountItem alloc] initWithTag:instruction.getOldChildNode()->getTag() - eventHandlers:instruction.getOldChildNode()->getEventHandlers()]; + // EventEmitter + if (oldShadowNode->getEventEmitter() != newShadowNode->getEventEmitter()) { + RCTUpdateEventEmitterMountItem *mountItem = + [[RCTUpdateEventEmitterMountItem alloc] initWithTag:instruction.getOldChildNode()->getTag() + eventEmitter:instruction.getOldChildNode()->getEventEmitter()]; [mountItems addObject:mountItem]; } diff --git a/React/Fabric/Mounting/UIView+ComponentViewProtocol.h b/React/Fabric/Mounting/UIView+ComponentViewProtocol.h index 75524cef771f9e..61c981b59563df 100644 --- a/React/Fabric/Mounting/UIView+ComponentViewProtocol.h +++ b/React/Fabric/Mounting/UIView+ComponentViewProtocol.h @@ -26,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)updateProps:(facebook::react::SharedProps)props oldProps:(facebook::react::SharedProps)oldProps; -- (void)updateEventHandlers:(facebook::react::SharedEventHandlers)eventHandlers; +- (void)updateEventEmitter:(facebook::react::SharedEventEmitter)eventEmitter; - (void)updateLocalData:(facebook::react::SharedLocalData)localData oldLocalData:(facebook::react::SharedLocalData)oldLocalData; diff --git a/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm b/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm index 223bb7c9b92eb4..eeb64581167fbb 100644 --- a/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm +++ b/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm @@ -31,7 +31,7 @@ - (void)updateProps:(facebook::react::SharedProps)props // Default implementation does nothing. } -- (void)updateEventHandlers:(facebook::react::SharedEventHandlers)eventHandlers +- (void)updateEventEmitter:(facebook::react::SharedEventEmitter)eventEmitter { // Default implementation does nothing. } diff --git a/React/Fabric/RCTSurfaceTouchHandler.mm b/React/Fabric/RCTSurfaceTouchHandler.mm index 09f586646d7fa3..b668da0d8b5736 100644 --- a/React/Fabric/RCTSurfaceTouchHandler.mm +++ b/React/Fabric/RCTSurfaceTouchHandler.mm @@ -8,7 +8,7 @@ #import "RCTSurfaceTouchHandler.h" #import -#import +#import #import #import @@ -47,7 +47,7 @@ void reset() { }; @protocol RCTTouchableComponentViewProtocol - - (SharedViewEventHandlers)touchEventHandlers; + - (SharedViewEventEmitter)touchEventEmitter; @end typedef NS_ENUM(NSInteger, RCTTouchEventType) { @@ -59,7 +59,7 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) { struct ActiveTouch { Touch touch; - SharedViewEventHandlers eventHandlers; + SharedViewEventEmitter eventEmitter; struct Hasher { size_t operator()(const ActiveTouch &activeTouch) const { @@ -95,8 +95,8 @@ static ActiveTouch CreateTouchWithUITouch(UITouch *uiTouch, UIView *rootComponen ActiveTouch activeTouch = {}; - if ([componentView respondsToSelector:@selector(touchEventHandlers)]) { - activeTouch.eventHandlers = [(id)componentView touchEventHandlers]; + if ([componentView respondsToSelector:@selector(touchEventEmitter)]) { + activeTouch.eventEmitter = [(id)componentView touchEventEmitter]; activeTouch.touch.target = (Tag)componentView.tag; } @@ -217,23 +217,23 @@ - (void)_dispatchTouches:(NSSet *)touches eventType:(RCTTouchEventTyp { TouchEvent event = {}; std::unordered_set changedActiveTouches = {}; - std::unordered_set uniqueEventHandlers = {}; + std::unordered_set uniqueEventEmitter = {}; BOOL isEndishEventType = eventType == RCTTouchEventTypeTouchEnd || eventType == RCTTouchEventTypeTouchCancel; for (UITouch *touch in touches) { auto &&activeTouch = _activeTouches[touch]; - if (!activeTouch.eventHandlers) { + if (!activeTouch.eventEmitter) { continue; } changedActiveTouches.insert(activeTouch); event.changedTouches.insert(activeTouch.touch); - uniqueEventHandlers.insert(activeTouch.eventHandlers); + uniqueEventEmitter.insert(activeTouch.eventEmitter); } for (auto &&pair : _activeTouches) { - if (!pair.second.eventHandlers) { + if (!pair.second.eventEmitter) { continue; } @@ -247,27 +247,27 @@ - (void)_dispatchTouches:(NSSet *)touches eventType:(RCTTouchEventTyp event.touches.insert(pair.second.touch); } - for (auto &&eventHandlers : uniqueEventHandlers) { + for (auto &&eventEmitter : uniqueEventEmitter) { event.targetTouches.clear(); for (auto &&pair : _activeTouches) { - if (pair.second.eventHandlers == eventHandlers) { + if (pair.second.eventEmitter == eventEmitter) { event.targetTouches.insert(pair.second.touch); } } switch (eventType) { case RCTTouchEventTypeTouchStart: - eventHandlers->onTouchStart(event); + eventEmitter->onTouchStart(event); break; case RCTTouchEventTypeTouchMove: - eventHandlers->onTouchMove(event); + eventEmitter->onTouchMove(event); break; case RCTTouchEventTypeTouchEnd: - eventHandlers->onTouchEnd(event); + eventEmitter->onTouchEnd(event); break; case RCTTouchEventTypeTouchCancel: - eventHandlers->onTouchCancel(event); + eventEmitter->onTouchCancel(event); break; } } diff --git a/ReactCommon/fabric/core/componentdescriptor/ComponentDescriptor.h b/ReactCommon/fabric/core/componentdescriptor/ComponentDescriptor.h index 669f8475fa4fd3..1718860b43430e 100644 --- a/ReactCommon/fabric/core/componentdescriptor/ComponentDescriptor.h +++ b/ReactCommon/fabric/core/componentdescriptor/ComponentDescriptor.h @@ -47,7 +47,7 @@ class ComponentDescriptor { virtual SharedShadowNode createShadowNode( const Tag &tag, const Tag &rootTag, - const SharedEventHandlers &eventHandlers, + const SharedEventEmitter &eventEmitter, const SharedProps &props ) const = 0; @@ -57,7 +57,7 @@ class ComponentDescriptor { virtual SharedShadowNode cloneShadowNode( const SharedShadowNode &shadowNode, const SharedProps &props = nullptr, - const SharedEventHandlers &eventHandlers = nullptr, + const SharedEventEmitter &eventEmitter = nullptr, const SharedShadowNodeSharedList &children = nullptr ) const = 0; @@ -81,10 +81,10 @@ class ComponentDescriptor { ) const = 0; /* - * Creates a new `EventHandlers` object compatible with particular type of + * Creates a new `EventEmitter` object compatible with particular type of * shadow nodes. */ - virtual SharedEventHandlers createEventHandlers( + virtual SharedEventEmitter createEventEmitter( const InstanceHandle &instanceHandle, const Tag &tag ) const = 0; diff --git a/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h b/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h index 8b5ab2ce7cea1a..4af3582c1795a5 100644 --- a/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h +++ b/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h @@ -29,8 +29,8 @@ class ConcreteComponentDescriptor: public ComponentDescriptor { using SharedShadowNodeT = std::shared_ptr; using ConcreteProps = typename ShadowNodeT::ConcreteProps; using SharedConcreteProps = typename ShadowNodeT::SharedConcreteProps; - using ConcreteEventHandlers = typename ShadowNodeT::ConcreteEventHandlers; - using SharedConcreteEventHandlers = typename ShadowNodeT::SharedConcreteEventHandlers; + using ConcreteEventEmitter = typename ShadowNodeT::ConcreteEventEmitter; + using SharedConcreteEventEmitter = typename ShadowNodeT::SharedConcreteEventEmitter; public: ConcreteComponentDescriptor(SharedEventDispatcher eventDispatcher): @@ -58,17 +58,17 @@ class ConcreteComponentDescriptor: public ComponentDescriptor { SharedShadowNode createShadowNode( const Tag &tag, const Tag &rootTag, - const SharedEventHandlers &eventHandlers, + const SharedEventEmitter &eventEmitter, const SharedProps &props ) const override { assert(std::dynamic_pointer_cast(props)); - assert(std::dynamic_pointer_cast(eventHandlers)); + assert(std::dynamic_pointer_cast(eventEmitter)); auto &&shadowNode = std::make_shared( tag, rootTag, std::static_pointer_cast(props), - std::static_pointer_cast(eventHandlers), + std::static_pointer_cast(eventEmitter), ShadowNode::emptySharedShadowNodeSharedList(), getCloneFunction() ); @@ -80,7 +80,7 @@ class ConcreteComponentDescriptor: public ComponentDescriptor { SharedShadowNode cloneShadowNode( const SharedShadowNode &sourceShadowNode, const SharedProps &props = nullptr, - const SharedEventHandlers &eventHandlers = nullptr, + const SharedEventEmitter &eventEmitter = nullptr, const SharedShadowNodeSharedList &children = nullptr ) const override { assert(std::dynamic_pointer_cast(sourceShadowNode)); @@ -88,7 +88,7 @@ class ConcreteComponentDescriptor: public ComponentDescriptor { auto &&shadowNode = std::make_shared( std::static_pointer_cast(sourceShadowNode), std::static_pointer_cast(props), - std::static_pointer_cast(eventHandlers), + std::static_pointer_cast(eventEmitter), children ); @@ -112,11 +112,11 @@ class ConcreteComponentDescriptor: public ComponentDescriptor { return ShadowNodeT::Props(rawProps, props); }; - virtual SharedEventHandlers createEventHandlers( + virtual SharedEventEmitter createEventEmitter( const InstanceHandle &instanceHandle, const Tag &tag ) const override { - return std::make_shared(instanceHandle, tag, eventDispatcher_); + return std::make_shared(instanceHandle, tag, eventDispatcher_); } protected: @@ -133,9 +133,9 @@ class ConcreteComponentDescriptor: public ComponentDescriptor { ShadowNodeCloneFunction getCloneFunction() const { if (!cloneFunction_) { - cloneFunction_ = [this](const SharedShadowNode &shadowNode, const SharedProps &props, const SharedEventHandlers &eventHandlers, const SharedShadowNodeSharedList &children) { + cloneFunction_ = [this](const SharedShadowNode &shadowNode, const SharedProps &props, const SharedEventEmitter &eventEmitter, const SharedShadowNodeSharedList &children) { assert(std::dynamic_pointer_cast(shadowNode)); - return this->cloneShadowNode(shadowNode, props, eventHandlers, children); + return this->cloneShadowNode(shadowNode, props, eventEmitter, children); }; } diff --git a/ReactCommon/fabric/core/events/EventDispatcher.h b/ReactCommon/fabric/core/events/EventDispatcher.h index 40e5184a212450..930a547f4ae679 100644 --- a/ReactCommon/fabric/core/events/EventDispatcher.h +++ b/ReactCommon/fabric/core/events/EventDispatcher.h @@ -21,7 +21,7 @@ using SharedEventDispatcher = std::shared_ptr; /* * Abstract class that represent event-delivery infrastructure. - * Particular `EventHandlers` clases use an object of this class to invoke + * Particular `EventEmitter` clases use an object of this class to invoke * events. */ class EventDispatcher { diff --git a/ReactCommon/fabric/core/events/EventHandlers.cpp b/ReactCommon/fabric/core/events/EventEmitter.cpp similarity index 80% rename from ReactCommon/fabric/core/events/EventHandlers.cpp rename to ReactCommon/fabric/core/events/EventEmitter.cpp index 3d4ecc80488524..b4b3b8db38bea0 100644 --- a/ReactCommon/fabric/core/events/EventHandlers.cpp +++ b/ReactCommon/fabric/core/events/EventEmitter.cpp @@ -5,23 +5,23 @@ * LICENSE file in the root directory of this source tree. */ -#include "EventHandlers.h" +#include "EventEmitter.h" #include namespace facebook { namespace react { -EventHandlers::EventHandlers(const InstanceHandle &instanceHandle, const Tag &tag, const SharedEventDispatcher &eventDispatcher): +EventEmitter::EventEmitter(const InstanceHandle &instanceHandle, const Tag &tag, const SharedEventDispatcher &eventDispatcher): instanceHandle_(instanceHandle), tag_(tag), eventDispatcher_(eventDispatcher) {} -EventHandlers::~EventHandlers() { +EventEmitter::~EventEmitter() { releaseEventTargetIfNeeded(); } -void EventHandlers::dispatchEvent( +void EventEmitter::dispatchEvent( const std::string &type, const folly::dynamic &payload, const EventPriority &priority @@ -42,7 +42,7 @@ void EventHandlers::dispatchEvent( eventDispatcher->dispatchEvent(eventTarget_, type, extendedPayload, priority); } -void EventHandlers::createEventTargetIfNeeded() const { +void EventEmitter::createEventTargetIfNeeded() const { std::lock_guard lock(mutex_); if (eventTarget_) { @@ -54,7 +54,7 @@ void EventHandlers::createEventTargetIfNeeded() const { eventTarget_ = eventDispatcher->createEventTarget(instanceHandle_); } -void EventHandlers::releaseEventTargetIfNeeded() const { +void EventEmitter::releaseEventTargetIfNeeded() const { std::lock_guard lock(mutex_); if (!eventTarget_) { diff --git a/ReactCommon/fabric/core/events/EventHandlers.h b/ReactCommon/fabric/core/events/EventEmitter.h similarity index 83% rename from ReactCommon/fabric/core/events/EventHandlers.h rename to ReactCommon/fabric/core/events/EventEmitter.h index b55db7dc7e48d0..eb05bd1c62577f 100644 --- a/ReactCommon/fabric/core/events/EventHandlers.h +++ b/ReactCommon/fabric/core/events/EventEmitter.h @@ -17,9 +17,9 @@ namespace facebook { namespace react { -class EventHandlers; +class EventEmitter; -using SharedEventHandlers = std::shared_ptr; +using SharedEventEmitter = std::shared_ptr; /* * Base class for all particular typed event handlers. @@ -28,11 +28,11 @@ using SharedEventHandlers = std::shared_ptr; * * TODO: Reconsider naming of all event-related things. */ -class EventHandlers { +class EventEmitter { public: - EventHandlers(const InstanceHandle &instanceHandle, const Tag &tag, const SharedEventDispatcher &eventDispatcher); - virtual ~EventHandlers(); + EventEmitter(const InstanceHandle &instanceHandle, const Tag &tag, const SharedEventDispatcher &eventDispatcher); + virtual ~EventEmitter(); protected: diff --git a/ReactCommon/fabric/core/shadownode/ConcreteShadowNode.h b/ReactCommon/fabric/core/shadownode/ConcreteShadowNode.h index 86c0976b8ce675..c4f08a45a65e71 100644 --- a/ReactCommon/fabric/core/shadownode/ConcreteShadowNode.h +++ b/ReactCommon/fabric/core/shadownode/ConcreteShadowNode.h @@ -19,15 +19,15 @@ namespace react { * `ConcreteShadowNode` is a default implementation of `ShadowNode` interface * with many handy features. */ -template +template class ConcreteShadowNode: public ShadowNode { static_assert(std::is_base_of::value, "PropsT must be a descendant of Props"); public: using ConcreteProps = PropsT; using SharedConcreteProps = std::shared_ptr; - using ConcreteEventHandlers = EventHandlersT; - using SharedConcreteEventHandlers = std::shared_ptr; + using ConcreteEventEmitter = EventEmitterT; + using SharedConcreteEventEmitter = std::shared_ptr; using SharedConcreteShadowNode = std::shared_ptr; static SharedConcreteProps Props(const RawProps &rawProps, const SharedProps &baseProps = nullptr) { @@ -43,7 +43,7 @@ class ConcreteShadowNode: public ShadowNode { const Tag &tag, const Tag &rootTag, const SharedConcreteProps &props, - const SharedConcreteEventHandlers &eventHandlers, + const SharedConcreteEventEmitter &eventEmitter, const SharedShadowNodeSharedList &children, const ShadowNodeCloneFunction &cloneFunction ): @@ -51,7 +51,7 @@ class ConcreteShadowNode: public ShadowNode { tag, rootTag, (SharedProps)props, - eventHandlers, + eventEmitter, children, cloneFunction ) {}; @@ -59,13 +59,13 @@ class ConcreteShadowNode: public ShadowNode { ConcreteShadowNode( const SharedConcreteShadowNode &shadowNode, const SharedProps &props, - const SharedEventHandlers &eventHandlers, + const SharedEventEmitter &eventEmitter, const SharedShadowNodeSharedList &children ): ShadowNode( shadowNode, (SharedProps)props, - eventHandlers, + eventEmitter, children ) {} diff --git a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp index e18ae2e387d209..54e1465eb19e94 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp +++ b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp @@ -24,14 +24,14 @@ ShadowNode::ShadowNode( const Tag &tag, const Tag &rootTag, const SharedProps &props, - const SharedEventHandlers &eventHandlers, + const SharedEventEmitter &eventEmitter, const SharedShadowNodeSharedList &children, const ShadowNodeCloneFunction &cloneFunction ): tag_(tag), rootTag_(rootTag), props_(props), - eventHandlers_(eventHandlers), + eventEmitter_(eventEmitter), children_(std::make_shared(*children)), cloneFunction_(cloneFunction), revision_(1) {} @@ -39,13 +39,13 @@ ShadowNode::ShadowNode( ShadowNode::ShadowNode( const SharedShadowNode &shadowNode, const SharedProps &props, - const SharedEventHandlers &eventHandlers, + const SharedEventEmitter &eventEmitter, const SharedShadowNodeSharedList &children ): tag_(shadowNode->tag_), rootTag_(shadowNode->rootTag_), props_(props ? props : shadowNode->props_), - eventHandlers_(eventHandlers ? eventHandlers : shadowNode->eventHandlers_), + eventEmitter_(eventEmitter ? eventEmitter : shadowNode->eventEmitter_), children_(std::make_shared(*(children ? children : shadowNode->children_))), sourceNode_(shadowNode), localData_(shadowNode->localData_), @@ -57,7 +57,7 @@ SharedShadowNode ShadowNode::clone( const SharedShadowNodeSharedList &children ) const { assert(cloneFunction_); - return cloneFunction_(shared_from_this(), props_, eventHandlers_, children_); + return cloneFunction_(shared_from_this(), props_, eventEmitter_, children_); } #pragma mark - Getters @@ -70,8 +70,8 @@ SharedProps ShadowNode::getProps() const { return props_; } -SharedEventHandlers ShadowNode::getEventHandlers() const { - return eventHandlers_; +SharedEventEmitter ShadowNode::getEventEmitter() const { + return eventEmitter_; } Tag ShadowNode::getTag() const { @@ -147,7 +147,7 @@ bool ShadowNode::operator==(const ShadowNode& rhs) const { tag_ == rhs.tag_ && rootTag_ == rhs.rootTag_ && props_ == rhs.props_ && - eventHandlers_ == rhs.eventHandlers_ && + eventEmitter_ == rhs.eventEmitter_ && localData_ == rhs.localData_; } diff --git a/ReactCommon/fabric/core/shadownode/ShadowNode.h b/ReactCommon/fabric/core/shadownode/ShadowNode.h index 9fa1b9341d9f64..a526fd698692a6 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNode.h +++ b/ReactCommon/fabric/core/shadownode/ShadowNode.h @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include @@ -33,7 +33,7 @@ using WeakShadowNode = std::weak_ptr; using ShadowNodeCloneFunction = std::function; @@ -50,7 +50,7 @@ class ShadowNode: const Tag &tag, const Tag &rootTag, const SharedProps &props, - const SharedEventHandlers &eventHandlers, + const SharedEventEmitter &eventEmitter, const SharedShadowNodeSharedList &children, const ShadowNodeCloneFunction &cloneFunction ); @@ -58,7 +58,7 @@ class ShadowNode: ShadowNode( const SharedShadowNode &shadowNode, const SharedProps &props, - const SharedEventHandlers &eventHandlers, + const SharedEventEmitter &eventEmitter, const SharedShadowNodeSharedList &children ); @@ -77,7 +77,7 @@ class ShadowNode: SharedShadowNodeSharedList getChildren() const; SharedProps getProps() const; - SharedEventHandlers getEventHandlers() const; + SharedEventEmitter getEventEmitter() const; Tag getTag() const; Tag getRootTag() const; @@ -143,7 +143,7 @@ class ShadowNode: Tag tag_; Tag rootTag_; SharedProps props_; - SharedEventHandlers eventHandlers_; + SharedEventEmitter eventEmitter_; SharedShadowNodeSharedList children_; WeakShadowNode sourceNode_; SharedLocalData localData_; diff --git a/ReactCommon/fabric/core/tests/ShadowNodeTest.cpp b/ReactCommon/fabric/core/tests/ShadowNodeTest.cpp index 7afbafbb5f8a00..a1f7d16b6ffa77 100644 --- a/ReactCommon/fabric/core/tests/ShadowNodeTest.cpp +++ b/ReactCommon/fabric/core/tests/ShadowNodeTest.cpp @@ -34,7 +34,7 @@ TEST(ShadowNodeTest, handleShadowNodeCreation) { ASSERT_STREQ(node->getComponentName().c_str(), "Test"); ASSERT_EQ(node->getTag(), 9); ASSERT_EQ(node->getRootTag(), 1); - ASSERT_EQ(node->getEventHandlers(), nullptr); + ASSERT_EQ(node->getEventEmitter(), nullptr); TestShadowNode *nodePtr = node.get(); ASSERT_EQ(node->getComponentHandle(), typeid(*nodePtr).hash_code()); ASSERT_EQ(node->getSourceNode(), nullptr); @@ -54,7 +54,7 @@ TEST(ShadowNodeTest, handleShadowNodeSimpleCloning) { ASSERT_STREQ(node->getComponentName().c_str(), "Test"); ASSERT_EQ(node->getTag(), 9); ASSERT_EQ(node->getRootTag(), 1); - ASSERT_EQ(node->getEventHandlers(), nullptr); + ASSERT_EQ(node->getEventEmitter(), nullptr); ASSERT_EQ(node2->getSourceNode(), node); } @@ -128,7 +128,7 @@ TEST(ShadowNodeTest, handleCloneFunction) { std::make_shared(), nullptr, ShadowNode::emptySharedShadowNodeSharedList(), - [](const SharedShadowNode &shadowNode, const SharedProps &props, const SharedEventHandlers &eventHandlers, const SharedShadowNodeSharedList &children) { + [](const SharedShadowNode &shadowNode, const SharedProps &props, const SharedEventEmitter &eventEmitter, const SharedShadowNodeSharedList &children) { return std::make_shared( std::static_pointer_cast(shadowNode), props, diff --git a/ReactCommon/fabric/scrollview/ScrollViewEventHandlers.cpp b/ReactCommon/fabric/scrollview/ScrollViewEventEmitter.cpp similarity index 69% rename from ReactCommon/fabric/scrollview/ScrollViewEventHandlers.cpp rename to ReactCommon/fabric/scrollview/ScrollViewEventEmitter.cpp index c331f6b03c87b2..c416b98b4dde37 100644 --- a/ReactCommon/fabric/scrollview/ScrollViewEventHandlers.cpp +++ b/ReactCommon/fabric/scrollview/ScrollViewEventEmitter.cpp @@ -5,32 +5,32 @@ * LICENSE file in the root directory of this source tree. */ -#include "ScrollViewEventHandlers.h" +#include "ScrollViewEventEmitter.h" namespace facebook { namespace react { -void ScrollViewEventHandlers::onScroll(const ScrollViewMetrics &scrollViewMetrics) const { +void ScrollViewEventEmitter::onScroll(const ScrollViewMetrics &scrollViewMetrics) const { dispatchScrollViewEvent("scroll", scrollViewMetrics); } -void ScrollViewEventHandlers::onScrollBeginDrag(const ScrollViewMetrics &scrollViewMetrics) const { +void ScrollViewEventEmitter::onScrollBeginDrag(const ScrollViewMetrics &scrollViewMetrics) const { dispatchScrollViewEvent("scrollBeginDrag", scrollViewMetrics); } -void ScrollViewEventHandlers::onScrollEndDrag(const ScrollViewMetrics &scrollViewMetrics) const { +void ScrollViewEventEmitter::onScrollEndDrag(const ScrollViewMetrics &scrollViewMetrics) const { dispatchScrollViewEvent("scrollEndDrag", scrollViewMetrics); } -void ScrollViewEventHandlers::onMomentumScrollBegin(const ScrollViewMetrics &scrollViewMetrics) const { +void ScrollViewEventEmitter::onMomentumScrollBegin(const ScrollViewMetrics &scrollViewMetrics) const { dispatchScrollViewEvent("momentumScrollBegin", scrollViewMetrics); } -void ScrollViewEventHandlers::onMomentumScrollEnd(const ScrollViewMetrics &scrollViewMetrics) const { +void ScrollViewEventEmitter::onMomentumScrollEnd(const ScrollViewMetrics &scrollViewMetrics) const { dispatchScrollViewEvent("momentumScrollEnd", scrollViewMetrics); } -void ScrollViewEventHandlers::dispatchScrollViewEvent(const std::string &name, const ScrollViewMetrics &scrollViewMetrics, const folly::dynamic &payload) const { +void ScrollViewEventEmitter::dispatchScrollViewEvent(const std::string &name, const ScrollViewMetrics &scrollViewMetrics, const folly::dynamic &payload) const { folly::dynamic compoundPayload = folly::dynamic::object(); compoundPayload["contentOffset"] = folly::dynamic::object diff --git a/ReactCommon/fabric/scrollview/ScrollViewEventHandlers.h b/ReactCommon/fabric/scrollview/ScrollViewEventEmitter.h similarity index 77% rename from ReactCommon/fabric/scrollview/ScrollViewEventHandlers.h rename to ReactCommon/fabric/scrollview/ScrollViewEventEmitter.h index 8f6a93e7221a64..c9bd52543ad2bb 100644 --- a/ReactCommon/fabric/scrollview/ScrollViewEventHandlers.h +++ b/ReactCommon/fabric/scrollview/ScrollViewEventEmitter.h @@ -9,8 +9,8 @@ #include #include -#include -#include +#include +#include #include @@ -26,16 +26,16 @@ class ScrollViewMetrics { Float zoomScale; }; -class ScrollViewEventHandlers; +class ScrollViewEventEmitter; -using SharedScrollViewEventHandlers = std::shared_ptr; +using SharedScrollViewEventEmitter = std::shared_ptr; -class ScrollViewEventHandlers: - public ViewEventHandlers { +class ScrollViewEventEmitter: + public ViewEventEmitter { public: - using ViewEventHandlers::ViewEventHandlers; + using ViewEventEmitter::ViewEventEmitter; void onScroll(const ScrollViewMetrics &scrollViewMetrics) const; void onScrollBeginDrag(const ScrollViewMetrics &scrollViewMetrics) const; diff --git a/ReactCommon/fabric/scrollview/ScrollViewShadowNode.h b/ReactCommon/fabric/scrollview/ScrollViewShadowNode.h index 5a74f0c320df22..c2db4ed66c8ff2 100644 --- a/ReactCommon/fabric/scrollview/ScrollViewShadowNode.h +++ b/ReactCommon/fabric/scrollview/ScrollViewShadowNode.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include @@ -25,7 +25,7 @@ using SharedScrollViewShadowNode = std::shared_ptr; * `ShadowNode` for component. */ class ScrollViewShadowNode final: - public ConcreteViewShadowNode { + public ConcreteViewShadowNode { public: diff --git a/ReactCommon/fabric/uimanager/FabricUIManager.cpp b/ReactCommon/fabric/uimanager/FabricUIManager.cpp index 41115a191eeb90..30df1137cbfb4c 100644 --- a/ReactCommon/fabric/uimanager/FabricUIManager.cpp +++ b/ReactCommon/fabric/uimanager/FabricUIManager.cpp @@ -134,7 +134,7 @@ SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int componentDescriptor->createShadowNode( tag, rootTag, - componentDescriptor->createEventHandlers(instanceHandle, tag), + componentDescriptor->createEventEmitter(instanceHandle, tag), componentDescriptor->cloneProps(nullptr, rawProps) ); @@ -155,7 +155,7 @@ SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode, componentDescriptor->cloneShadowNode( shadowNode, nullptr, - componentDescriptor->createEventHandlers(instanceHandle, shadowNode->getTag()), + componentDescriptor->createEventEmitter(instanceHandle, shadowNode->getTag()), nullptr ); @@ -172,7 +172,7 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNod componentDescriptor->cloneShadowNode( shadowNode, nullptr, - componentDescriptor->createEventHandlers(instanceHandle, shadowNode->getTag()), + componentDescriptor->createEventEmitter(instanceHandle, shadowNode->getTag()), ShadowNode::emptySharedShadowNodeSharedList() ); @@ -190,7 +190,7 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode & componentDescriptor->cloneShadowNode( shadowNode, componentDescriptor->cloneProps(shadowNode->getProps(), rawProps), - componentDescriptor->createEventHandlers(instanceHandle, shadowNode->getTag()), + componentDescriptor->createEventEmitter(instanceHandle, shadowNode->getTag()), nullptr ); @@ -208,7 +208,7 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewChildrenAndProps(const SharedS componentDescriptor->cloneShadowNode( shadowNode, componentDescriptor->cloneProps(shadowNode->getProps(), rawProps), - componentDescriptor->createEventHandlers(instanceHandle, shadowNode->getTag()), + componentDescriptor->createEventEmitter(instanceHandle, shadowNode->getTag()), ShadowNode::emptySharedShadowNodeSharedList() ); diff --git a/ReactCommon/fabric/uimanager/ShadowTree.cpp b/ReactCommon/fabric/uimanager/ShadowTree.cpp index 140ff8071e1c28..bc19c1b329bf01 100644 --- a/ReactCommon/fabric/uimanager/ShadowTree.cpp +++ b/ReactCommon/fabric/uimanager/ShadowTree.cpp @@ -18,12 +18,12 @@ namespace react { ShadowTree::ShadowTree(Tag rootTag): rootTag_(rootTag) { - auto &&noopEventHandlers = std::make_shared(nullptr, rootTag, nullptr); + auto &&noopEventEmitter = std::make_shared(nullptr, rootTag, nullptr); rootShadowNode_ = std::make_shared( rootTag, rootTag, RootShadowNode::defaultSharedProps(), - noopEventHandlers, + noopEventEmitter, ShadowNode::emptySharedShadowNodeSharedList(), nullptr ); @@ -108,11 +108,11 @@ void ShadowTree::emitLayoutEvents(const TreeMutationInstructionList &instruction type == TreeMutationInstruction::Replacement ) { auto &&newShadowNode = instruction.getNewChildNode(); - auto &&eventHandlers = newShadowNode->getEventHandlers(); - auto &&viewEventHandlers = std::dynamic_pointer_cast(eventHandlers); + auto &&eventEmitter = newShadowNode->getEventEmitter(); + auto &&viewEventEmitter = std::dynamic_pointer_cast(eventEmitter); - // Checking if particular shadow node supports `onLayout` event (part of `ViewEventHandlers`). - if (viewEventHandlers) { + // Checking if particular shadow node supports `onLayout` event (part of `ViewEventEmitter`). + if (viewEventEmitter) { // Now we know that both (old and new) shadow nodes must be `LayoutableShadowNode` subclasses. assert(std::dynamic_pointer_cast(newShadowNode)); // TODO(T29661055): Consider using `std::reinterpret_pointer_cast`. @@ -132,7 +132,7 @@ void ShadowTree::emitLayoutEvents(const TreeMutationInstructionList &instruction } } - viewEventHandlers->onLayout(newLayoutableShadowNode->getLayoutMetrics()); + viewEventEmitter->onLayout(newLayoutableShadowNode->getLayoutMetrics()); } } } diff --git a/ReactCommon/fabric/view/ConcreteViewShadowNode.h b/ReactCommon/fabric/view/ConcreteViewShadowNode.h index df1707ea5d7c8d..dc898dcdd7bc9a 100644 --- a/ReactCommon/fabric/view/ConcreteViewShadowNode.h +++ b/ReactCommon/fabric/view/ConcreteViewShadowNode.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include @@ -24,9 +24,9 @@ namespace react { * as and similar basic behaviour). * For example: , , but not , . */ -template +template class ConcreteViewShadowNode: - public ConcreteShadowNode, + public ConcreteShadowNode, public AccessibleShadowNode, public YogaLayoutableShadowNode { @@ -38,23 +38,23 @@ class ConcreteViewShadowNode: using ConcreteViewProps = ViewPropsT; using SharedConcreteViewProps = std::shared_ptr; - using ConcreteViewEventHandlers = ViewEventHandlersT; - using SharedConcreteViewEventHandlers = std::shared_ptr; + using ConcreteViewEventEmitter = ViewEventEmitterT; + using SharedConcreteViewEventEmitter = std::shared_ptr; using SharedConcreteViewShadowNode = std::shared_ptr; ConcreteViewShadowNode( const Tag &tag, const Tag &rootTag, const SharedConcreteViewProps &props, - const SharedConcreteViewEventHandlers &eventHandlers, + const SharedConcreteViewEventEmitter &eventEmitter, const SharedShadowNodeSharedList &children, const ShadowNodeCloneFunction &cloneFunction ): - ConcreteShadowNode( + ConcreteShadowNode( tag, rootTag, props, - eventHandlers, + eventEmitter, children, cloneFunction ), @@ -69,13 +69,13 @@ class ConcreteViewShadowNode: ConcreteViewShadowNode( const SharedConcreteViewShadowNode &shadowNode, const SharedConcreteViewProps &props, - const SharedConcreteViewEventHandlers &eventHandlers, + const SharedConcreteViewEventEmitter &eventEmitter, const SharedShadowNodeSharedList &children ): - ConcreteShadowNode( + ConcreteShadowNode( shadowNode, props, - eventHandlers, + eventEmitter, children ), AccessibleShadowNode( diff --git a/ReactCommon/fabric/view/ViewEventHandlers.cpp b/ReactCommon/fabric/view/ViewEventEmitter.cpp similarity index 79% rename from ReactCommon/fabric/view/ViewEventHandlers.cpp rename to ReactCommon/fabric/view/ViewEventEmitter.cpp index 3cdadd3527c68d..fe1b246db98380 100644 --- a/ReactCommon/fabric/view/ViewEventHandlers.cpp +++ b/ReactCommon/fabric/view/ViewEventEmitter.cpp @@ -5,28 +5,28 @@ * LICENSE file in the root directory of this source tree. */ -#include "ViewEventHandlers.h" +#include "ViewEventEmitter.h" namespace facebook { namespace react { #pragma mark - Accessibility -void ViewEventHandlers::onAccessibilityAction(const std::string &name) const { +void ViewEventEmitter::onAccessibilityAction(const std::string &name) const { dispatchEvent("accessibilityAction", folly::dynamic::object("action", name)); } -void ViewEventHandlers::onAccessibilityTap() const { +void ViewEventEmitter::onAccessibilityTap() const { dispatchEvent("accessibilityTap"); } -void ViewEventHandlers::onAccessibilityMagicTap() const { +void ViewEventEmitter::onAccessibilityMagicTap() const { dispatchEvent("magicTap"); } #pragma mark - Layout -void ViewEventHandlers::onLayout(const LayoutMetrics &layoutMetrics) const { +void ViewEventEmitter::onLayout(const LayoutMetrics &layoutMetrics) const { folly::dynamic payload = folly::dynamic::object(); auto &&frame = layoutMetrics.frame; payload["layout"] = folly::dynamic::object @@ -71,19 +71,19 @@ static folly::dynamic touchEventPayload(const TouchEvent &event) { return object; } -void ViewEventHandlers::onTouchStart(const TouchEvent &event) const { +void ViewEventEmitter::onTouchStart(const TouchEvent &event) const { dispatchEvent("touchStart", touchEventPayload(event)); } -void ViewEventHandlers::onTouchMove(const TouchEvent &event) const { +void ViewEventEmitter::onTouchMove(const TouchEvent &event) const { dispatchEvent("touchMove", touchEventPayload(event)); } -void ViewEventHandlers::onTouchEnd(const TouchEvent &event) const { +void ViewEventEmitter::onTouchEnd(const TouchEvent &event) const { dispatchEvent("touchEnd", touchEventPayload(event)); } -void ViewEventHandlers::onTouchCancel(const TouchEvent &event) const { +void ViewEventEmitter::onTouchCancel(const TouchEvent &event) const { dispatchEvent("touchCancel", touchEventPayload(event)); } diff --git a/ReactCommon/fabric/view/ViewEventHandlers.h b/ReactCommon/fabric/view/ViewEventEmitter.h similarity index 92% rename from ReactCommon/fabric/view/ViewEventHandlers.h rename to ReactCommon/fabric/view/ViewEventEmitter.h index 654649ed384ab8..04af2fee6e10cb 100644 --- a/ReactCommon/fabric/view/ViewEventHandlers.h +++ b/ReactCommon/fabric/view/ViewEventEmitter.h @@ -8,7 +8,7 @@ #include -#include +#include #include #include @@ -97,16 +97,16 @@ struct TouchEvent { Touches targetTouches; }; -class ViewEventHandlers; +class ViewEventEmitter; -using SharedViewEventHandlers = std::shared_ptr; +using SharedViewEventEmitter = std::shared_ptr; -class ViewEventHandlers: - public EventHandlers { +class ViewEventEmitter: + public EventEmitter { public: - using EventHandlers::EventHandlers; + using EventEmitter::EventEmitter; #pragma mark - Accessibility diff --git a/ReactCommon/fabric/view/ViewShadowNode.h b/ReactCommon/fabric/view/ViewShadowNode.h index 4ad05c83f9211d..a406f34de8a979 100644 --- a/ReactCommon/fabric/view/ViewShadowNode.h +++ b/ReactCommon/fabric/view/ViewShadowNode.h @@ -20,7 +20,7 @@ class ViewShadowNode; using SharedViewShadowNode = std::shared_ptr; class ViewShadowNode final: - public ConcreteViewShadowNode { + public ConcreteViewShadowNode { public: From e79b945f75ae7fa0fe3858082f6b4006df19ae50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Sat, 9 Jun 2018 18:01:25 -0700 Subject: [PATCH 11/22] Add MIT License Header Summary: When a third party library is vendored, both the original copyright header as well as React Native's header are required. Reviewed By: fkgozali Differential Revision: D8284116 fbshipit-source-id: 1748eb011c843a87e9ed421597571b66334edfd2 --- Libraries/vendor/core/whatwg-fetch.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Libraries/vendor/core/whatwg-fetch.js b/Libraries/vendor/core/whatwg-fetch.js index 1b5603201686e3..cdfa4fc69a447e 100644 --- a/Libraries/vendor/core/whatwg-fetch.js +++ b/Libraries/vendor/core/whatwg-fetch.js @@ -1,3 +1,12 @@ +/** +* 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. +* +* @format +*/ + // Fork of https://github.com/github/fetch/blob/master/fetch.js that does not // use reponseType: 'blob' by default. RN already has specific native implementations // for different response types so there is no need to add the extra blob overhead. From ad67f556fb145d38fe547e1e8baa73ccc7a431b0 Mon Sep 17 00:00:00 2001 From: Eli White Date: Sat, 9 Jun 2018 18:05:12 -0700 Subject: [PATCH 12/22] Migrate PickerIOS to ES6 Class Reviewed By: sahrens Differential Revision: D8343380 fbshipit-source-id: 9432f0810c67034f20b44ba9f4955d4ffd2ef1d2 --- Libraries/Components/Picker/PickerIOS.ios.js | 142 +++++++++---------- Libraries/StyleSheet/processColor.js | 2 +- 2 files changed, 70 insertions(+), 74 deletions(-) diff --git a/Libraries/Components/Picker/PickerIOS.ios.js b/Libraries/Components/Picker/PickerIOS.ios.js index 6eef251e5b4c11..62ebe53e89a3ea 100644 --- a/Libraries/Components/Picker/PickerIOS.ios.js +++ b/Libraries/Components/Picker/PickerIOS.ios.js @@ -8,57 +8,90 @@ * This is a controlled component version of RCTPickerIOS * * @format + * @flow */ 'use strict'; -const NativeMethodsMixin = require('NativeMethodsMixin'); const React = require('React'); const ReactNative = require('ReactNative'); -const PropTypes = require('prop-types'); const StyleSheet = require('StyleSheet'); -const StyleSheetPropType = require('StyleSheetPropType'); -const TextStylePropTypes = require('TextStylePropTypes'); const View = require('View'); -const ViewPropTypes = require('ViewPropTypes'); const processColor = require('processColor'); - -const createReactClass = require('create-react-class'); -const itemStylePropType = StyleSheetPropType(TextStylePropTypes); const requireNativeComponent = require('requireNativeComponent'); +import type {SyntheticEvent} from 'CoreEventTypes'; import type {ColorValue} from 'StyleSheetTypes'; import type {ViewProps} from 'ViewPropTypes'; +import type {TextStyleProp} from 'StyleSheet'; + +type PickerIOSChangeEvent = SyntheticEvent< + $ReadOnly<{| + newValue: any, + newIndex: number, + |}>, +>; + +type RCTPickerIOSItemType = $ReadOnly<{| + label: ?Label, + value: ?any, + textColor: ?number, +|}>; + +type RCTPickerIOSType = Class< + ReactNative.NativeComponent< + $ReadOnly<{| + items: $ReadOnlyArray, + onChange: (event: PickerIOSChangeEvent) => void, + onResponderTerminationRequest: () => boolean, + onStartShouldSetResponder: () => boolean, + selectedIndex: number, + style?: ?TextStyleProp, + |}>, + >, +>; + +const RCTPickerIOS: RCTPickerIOSType = (requireNativeComponent( + 'RCTPicker', +): any); + +type Label = Stringish | number; type Props = $ReadOnly<{| ...ViewProps, - color?: ?ColorValue, - label: string, - testID?: ?string, + children: React.ChildrenArray>, + itemStyle?: ?TextStyleProp, + onChange?: ?(event: PickerIOSChangeEvent) => mixed, + onValueChange?: ?(newValue: any, newIndex: number) => mixed, + selectedValue: any, +|}>; + +type State = {| + selectedIndex: number, + items: $ReadOnlyArray, +|}; + +type ItemProps = $ReadOnly<{| + label: ?Label, value?: ?any, + color?: ?ColorValue, |}>; -const PickerIOS = createReactClass({ - displayName: 'PickerIOS', - mixins: [NativeMethodsMixin], +const PickerIOSItem = (props: ItemProps) => { + return null; +}; - propTypes: { - ...ViewPropTypes, - itemStyle: itemStylePropType, - onValueChange: PropTypes.func, - selectedValue: PropTypes.any, // string or integer basically - }, +class PickerIOS extends React.Component { + _picker: ?React.ElementRef = null; - getInitialState: function() { - return this._stateFromProps(this.props); - }, + state = { + selectedIndex: 0, + items: [], + }; - UNSAFE_componentWillReceiveProps: function(nextProps) { - this.setState(this._stateFromProps(nextProps)); - }, + static Item = PickerIOSItem; - // Translate PickerIOS prop and children into stuff that RCTPickerIOS understands. - _stateFromProps: function(props) { + static getDerivedStateFromProps(props: Props): State { let selectedIndex = 0; const items = []; React.Children.toArray(props.children).forEach(function(child, index) { @@ -72,13 +105,15 @@ const PickerIOS = createReactClass({ }); }); return {selectedIndex, items}; - }, + } - render: function() { + render() { return ( (this._picker = picker)} + ref={picker => { + this._picker = picker; + }} style={[styles.pickerIOS, this.props.itemStyle]} items={this.state.items} selectedIndex={this.state.selectedIndex} @@ -88,9 +123,9 @@ const PickerIOS = createReactClass({ /> ); - }, + } - _onChange: function(event) { + _onChange = event => { if (this.props.onChange) { this.props.onChange(event); } @@ -115,30 +150,7 @@ const PickerIOS = createReactClass({ selectedIndex: this.state.selectedIndex, }); } - }, -}); - -PickerIOS.Item = class extends React.Component< - $ReadOnly<{| - label: string, - value?: ?any, - color?: ?ColorValue, - |}>, -> { - static propTypes = { - value: PropTypes.any, // string or integer basically - label: PropTypes.string, - color: PropTypes.string, }; - - render() { - // These items don't get rendered directly. - return null; - } -}; - -class TypedPickerIOS extends ReactNative.NativeComponent { - static Item = PickerIOS.Item; } const styles = StyleSheet.create({ @@ -150,20 +162,4 @@ const styles = StyleSheet.create({ }, }); -const RCTPickerIOS = requireNativeComponent( - 'RCTPicker', - { - propTypes: { - style: itemStylePropType, - }, - }, - { - nativeOnly: { - items: true, - onChange: true, - selectedIndex: true, - }, - }, -); - -module.exports = ((PickerIOS: any): Class); +module.exports = PickerIOS; diff --git a/Libraries/StyleSheet/processColor.js b/Libraries/StyleSheet/processColor.js index 99b5ecf468cb83..77ba69ded17eb3 100644 --- a/Libraries/StyleSheet/processColor.js +++ b/Libraries/StyleSheet/processColor.js @@ -15,7 +15,7 @@ const Platform = require('Platform'); const normalizeColor = require('normalizeColor'); /* eslint no-bitwise: 0 */ -function processColor(color?: string | number): ?number { +function processColor(color?: ?(string | number)): ?number { if (color === undefined || color === null) { return color; } From 5fbb307e24e144614b559bac57d1dfab6f52f2f4 Mon Sep 17 00:00:00 2001 From: Felix Yan Date: Sat, 9 Jun 2018 20:07:08 -0700 Subject: [PATCH 13/22] Fix some typos in dumpReactTree.js (#19636) Summary: Simple doc fixes Closes https://github.com/facebook/react-native/pull/19636 Differential Revision: D8344481 Pulled By: TheSavior fbshipit-source-id: b6fa064f70793bdaf1d6346b2775373b74c2ae3b --- Libraries/BugReporting/dumpReactTree.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Libraries/BugReporting/dumpReactTree.js b/Libraries/BugReporting/dumpReactTree.js index 844585714703c6..7cbb2530f2055c 100644 --- a/Libraries/BugReporting/dumpReactTree.js +++ b/Libraries/BugReporting/dumpReactTree.js @@ -51,14 +51,14 @@ function getReactTree() { } /* -function dumpNode(node: Object, identation: number) { +function dumpNode(node: Object, indentation: number) { const data = getReactData(node); if (data.nodeType === 'Text') { - return indent(identation) + data.text + '\n'; + return indent(indentation) + data.text + '\n'; } else if (data.nodeType === 'Empty') { return ''; } - let output = indent(identation) + `<${data.name}`; + let output = indent(indentation) + `<${data.name}`; if (data.nodeType === 'Composite') { for (const propName of Object.getOwnPropertyNames(data.props || {})) { if (isNormalProp(propName)) { @@ -76,11 +76,11 @@ function dumpNode(node: Object, identation: number) { } let childOutput = ''; for (const child of data.children || []) { - childOutput += dumpNode(child, identation + 1); + childOutput += dumpNode(child, indentation + 1); } if (childOutput) { - output += '>\n' + childOutput + indent(identation) + `\n`; + output += '>\n' + childOutput + indent(indentation) + `\n`; } else { output += ' />\n'; } From f573ea8a6679e8d32bbff05750148b942591c4c3 Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Sat, 9 Jun 2018 21:18:23 -0700 Subject: [PATCH 14/22] iOS: fix fabric core test Reviewed By: shergin Differential Revision: D8344613 fbshipit-source-id: 10c604e7fbe2ff3b8c47babedea12a197c0c56b2 --- .../fabric/core/tests/ComponentDescriptorTest.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ReactCommon/fabric/core/tests/ComponentDescriptorTest.cpp b/ReactCommon/fabric/core/tests/ComponentDescriptorTest.cpp index 99fb54201f0207..12e09787a7ad25 100644 --- a/ReactCommon/fabric/core/tests/ComponentDescriptorTest.cpp +++ b/ReactCommon/fabric/core/tests/ComponentDescriptorTest.cpp @@ -20,7 +20,7 @@ TEST(ComponentDescriptorTest, createShadowNode) { RawProps raw; raw["nativeID"] = "abc"; SharedProps props = descriptor->cloneProps(nullptr, raw); - SharedShadowNode node = descriptor->createShadowNode(9, 1, nullptr, props); + SharedShadowNode node = descriptor->createShadowNode(9, 1, descriptor->createEventEmitter(0, 9), props); ASSERT_EQ(node->getComponentHandle(), typeid(TestShadowNode).hash_code()); ASSERT_STREQ(node->getComponentName().c_str(), "Test"); @@ -35,7 +35,7 @@ TEST(ComponentDescriptorTest, cloneShadowNode) { RawProps raw; raw["nativeID"] = "abc"; SharedProps props = descriptor->cloneProps(nullptr, raw); - SharedShadowNode node = descriptor->createShadowNode(9, 1, nullptr, props); + SharedShadowNode node = descriptor->createShadowNode(9, 1, descriptor->createEventEmitter(0, 9), props); SharedShadowNode cloned = descriptor->cloneShadowNode(node); ASSERT_EQ(cloned->getComponentHandle(), typeid(TestShadowNode).hash_code()); @@ -51,9 +51,9 @@ TEST(ComponentDescriptorTest, appendChild) { RawProps raw; raw["nativeID"] = "abc"; SharedProps props = descriptor->cloneProps(nullptr, raw); - SharedShadowNode node1 = descriptor->createShadowNode(1, 1, nullptr, props); - SharedShadowNode node2 = descriptor->createShadowNode(2, 1, nullptr, props); - SharedShadowNode node3 = descriptor->createShadowNode(3, 1, nullptr, props); + SharedShadowNode node1 = descriptor->createShadowNode(1, 1, descriptor->createEventEmitter(0, 1), props); + SharedShadowNode node2 = descriptor->createShadowNode(2, 1, descriptor->createEventEmitter(0, 2), props); + SharedShadowNode node3 = descriptor->createShadowNode(3, 1, descriptor->createEventEmitter(0, 3), props); descriptor->appendChild(node1, node2); descriptor->appendChild(node1, node3); From 160bf731e5daa0d2932aa3c4d1165aecb7ba9ff0 Mon Sep 17 00:00:00 2001 From: Eli White Date: Sun, 10 Jun 2018 13:37:53 -0700 Subject: [PATCH 15/22] Switch to Platform.isTV to pass Android Flow Reviewed By: sahrens Differential Revision: D8345911 fbshipit-source-id: 9af7a25127e7c35844a6c59b267a77cf8adba535 --- Libraries/Components/ScrollView/ScrollView.js | 2 +- Libraries/Components/Touchable/TouchableHighlight.js | 2 +- Libraries/Components/View/ViewPropTypes.js | 2 +- Libraries/Modal/Modal.js | 2 +- Libraries/Utilities/BackHandler.ios.js | 2 +- RNTester/js/ARTExample.js | 2 +- RNTester/js/ListExampleShared.js | 2 +- RNTester/js/ModalExample.js | 4 ++-- RNTester/js/RNTesterExampleList.js | 2 +- RNTester/js/TVEventHandlerExample.js | 2 +- RNTester/js/TextExample.ios.js | 12 ++++++------ 11 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index 6e9e40d60e7332..a2be38422765ef 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -1041,7 +1041,7 @@ const ScrollView = createReactClass({ return ( // $FlowFixMe Invalid prop usage - {Platform.isTVOS ? null : refreshControl} + {Platform.isTV ? null : refreshControl} {contentContainer} ); diff --git a/Libraries/Components/Touchable/TouchableHighlight.js b/Libraries/Components/Touchable/TouchableHighlight.js index 117884faf864e5..5a681c099125ac 100644 --- a/Libraries/Components/Touchable/TouchableHighlight.js +++ b/Libraries/Components/Touchable/TouchableHighlight.js @@ -269,7 +269,7 @@ const TouchableHighlight = ((createReactClass({ touchableHandlePress: function(e: PressEvent) { clearTimeout(this._hideTimeout); - if (!Platform.isTVOS) { + if (!Platform.isTV) { this._showUnderlay(); this._hideTimeout = setTimeout( this._hideUnderlay, diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index addbc6e7e81db6..0f7dea210694ce 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -72,7 +72,7 @@ export type ViewProps = $ReadOnly<{| ...GestureResponderEventProps, ...TouchEventProps, - // There's no easy way to create a different type if (Platform.isTVOS): + // There's no easy way to create a different type if (Platform.isTV): // so we must include TVViewProps ...TVViewProps, diff --git a/Libraries/Modal/Modal.js b/Libraries/Modal/Modal.js index fcc3900da443a6..1af6fec61486d6 100644 --- a/Libraries/Modal/Modal.js +++ b/Libraries/Modal/Modal.js @@ -90,7 +90,7 @@ class Modal extends React.Component { * See https://facebook.github.io/react-native/docs/modal.html#onrequestclose */ onRequestClose: - Platform.isTVOS || Platform.OS === 'android' + Platform.isTV || Platform.OS === 'android' ? PropTypes.func.isRequired : PropTypes.func, /** diff --git a/Libraries/Utilities/BackHandler.ios.js b/Libraries/Utilities/BackHandler.ios.js index 968b707d690fd4..969a031ab62a96 100644 --- a/Libraries/Utilities/BackHandler.ios.js +++ b/Libraries/Utilities/BackHandler.ios.js @@ -53,7 +53,7 @@ function emptyFunction() {} */ let BackHandler; -if (Platform.isTVOS) { +if (Platform.isTV) { const _tvEventHandler = new TVEventHandler(); const _backPressSubscriptions = new Set(); diff --git a/RNTester/js/ARTExample.js b/RNTester/js/ARTExample.js index 15ae6de031ee86..1a0745ec43f210 100644 --- a/RNTester/js/ARTExample.js +++ b/RNTester/js/ARTExample.js @@ -16,7 +16,7 @@ var {ART, Platform, View} = ReactNative; const {Surface, Path, Group, Transform, Shape} = ART; -var scale = Platform.isTVOS ? 4 : 1; +var scale = Platform.isTV ? 4 : 1; class ARTExample extends React.Component<{}> { render() { diff --git a/RNTester/js/ListExampleShared.js b/RNTester/js/ListExampleShared.js index 905985b52b28af..62654e78e18192 100644 --- a/RNTester/js/ListExampleShared.js +++ b/RNTester/js/ListExampleShared.js @@ -237,7 +237,7 @@ function pressItem(context: Object, key: string) { } function renderSmallSwitchOption(context: Object, key: string) { - if (Platform.isTVOS) { + if (Platform.isTV) { return null; } return ( diff --git a/RNTester/js/ModalExample.js b/RNTester/js/ModalExample.js index cfb51abe6297eb..a66d331d03c9cc 100644 --- a/RNTester/js/ModalExample.js +++ b/RNTester/js/ModalExample.js @@ -94,7 +94,7 @@ class ModalExample extends React.Component<{}, $FlowFixMeState> { }; renderSwitch() { - if (Platform.isTVOS) { + if (Platform.isTV) { return null; } return ( @@ -191,7 +191,7 @@ class ModalExample extends React.Component<{}, $FlowFixMeState> { ); } renderPickers() { - if (Platform.isTVOS) { + if (Platform.isTV) { return null; } return ( diff --git a/RNTester/js/RNTesterExampleList.js b/RNTester/js/RNTesterExampleList.js index c9ccce1a88a0f2..325a5bce88a50c 100644 --- a/RNTester/js/RNTesterExampleList.js +++ b/RNTester/js/RNTesterExampleList.js @@ -80,7 +80,7 @@ class RNTesterExampleList extends React.Component { * comment and run Flow. */ this.props.disableSearch || (filterRegex.test(example.module.title) && - (!Platform.isTVOS || example.supportsTVOS)); + (!Platform.isTV || example.supportsTVOS)); const sections = [ { diff --git a/RNTester/js/TVEventHandlerExample.js b/RNTester/js/TVEventHandlerExample.js index 177614e7cf6726..757a27ef9466cb 100644 --- a/RNTester/js/TVEventHandlerExample.js +++ b/RNTester/js/TVEventHandlerExample.js @@ -74,7 +74,7 @@ class TVEventHandlerView extends React.Component< } render() { - if (Platform.isTVOS) { + if (Platform.isTV) { return ( {}}> diff --git a/RNTester/js/TextExample.ios.js b/RNTester/js/TextExample.ios.js index 6fdd942d4b84a0..52274d7c032c16 100644 --- a/RNTester/js/TextExample.ios.js +++ b/RNTester/js/TextExample.ios.js @@ -324,12 +324,12 @@ exports.examples = [ render: function() { return ( - + Cochin Cochin bold @@ -338,12 +338,12 @@ exports.examples = [ Helvetica bold - + Verdana Verdana bold @@ -817,14 +817,14 @@ exports.examples = [ Small Caps{'\n'} Old Style nums 0123456789{'\n'} Lining nums 0123456789{'\n'} From f50ce0850d4c8986b383c6399415bcf98e39d73c Mon Sep 17 00:00:00 2001 From: Eli White Date: Sun, 10 Jun 2018 14:17:13 -0700 Subject: [PATCH 16/22] Passing forwardedRef to Slider Reviewed By: sahrens Differential Revision: D8345883 fbshipit-source-id: d2affdba14d38593541e591fe72006c76fca166f --- Libraries/Components/Slider/Slider.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Libraries/Components/Slider/Slider.js b/Libraries/Components/Slider/Slider.js index aacfb14f34cb47..d9efe0170d8dfd 100644 --- a/Libraries/Components/Slider/Slider.js +++ b/Libraries/Components/Slider/Slider.js @@ -194,10 +194,8 @@ type Props = $ReadOnly<{| * */ const Slider = ( - props: $ReadOnly<{| - ...Props, - forwardedRef?: ?React.Ref<'RCTActivityIndicatorView'>, - |}>, + props: Props, + forwardedRef?: ?React.Ref<'RCTActivityIndicatorView'>, ) => { const style = StyleSheet.compose( styles.slider, @@ -230,6 +228,7 @@ const Slider = ( return ( { - return ; -}); +const SliderWithRef = React.forwardRef(Slider); SliderWithRef.defaultProps = { disabled: false, From 6b1bb018043aaf9d55aa23ca74120dfeb94a463c Mon Sep 17 00:00:00 2001 From: Eli White Date: Sun, 10 Jun 2018 15:09:41 -0700 Subject: [PATCH 17/22] Enable Flow for bezier Reviewed By: sahrens Differential Revision: D8346102 fbshipit-source-id: bb1a2eccb5472bf6f3fe113303ad96cf3f386cab --- Libraries/Animated/src/__tests__/bezier-test.js | 4 ++-- Libraries/Animated/src/bezier.js | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Libraries/Animated/src/__tests__/bezier-test.js b/Libraries/Animated/src/__tests__/bezier-test.js index 46c7f043b331e2..e9f00a7d214878 100644 --- a/Libraries/Animated/src/__tests__/bezier-test.js +++ b/Libraries/Animated/src/__tests__/bezier-test.js @@ -3,8 +3,8 @@ * https://github.com/gre/bezier-easing * * @copyright 2014-2015 Gaetan Renaudeau. MIT License. - * @noflow * @emails oncall+react_native + * @flow * @format */ @@ -39,7 +39,7 @@ function allEquals(be1, be2, samples, assertion) { function repeat(n) { return function(f) { for (let i = 0; i < n; ++i) { - f(i); + f(); } }; } diff --git a/Libraries/Animated/src/bezier.js b/Libraries/Animated/src/bezier.js index 41a83b545f7254..15f8e2dc1b686f 100644 --- a/Libraries/Animated/src/bezier.js +++ b/Libraries/Animated/src/bezier.js @@ -2,9 +2,9 @@ * BezierEasing - use bezier curve for transition easing function * https://github.com/gre/bezier-easing * + * @flow * @format * @copyright 2014-2015 Gaƫtan Renaudeau. MIT License. - * @noflow */ 'use strict'; @@ -71,9 +71,13 @@ function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) { return aGuessT; } -module.exports = function bezier(mX1, mY1, mX2, mY2) { +module.exports = function bezier( + mX1: number, + mY1: number, + mX2: number, + mY2: number, +) { if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) { - // eslint-disable-line yoda throw new Error('bezier x values must be in [0, 1] range'); } @@ -123,7 +127,7 @@ module.exports = function bezier(mX1, mY1, mX2, mY2) { } } - return function BezierEasing(x) { + return function BezierEasing(x: number): number { if (mX1 === mY1 && mX2 === mY2) { return x; // linear } From a51e8b19cc4dc36dee42ac95278b883c06b2e40f Mon Sep 17 00:00:00 2001 From: Eli White Date: Sun, 10 Jun 2018 15:34:37 -0700 Subject: [PATCH 18/22] Don't pass additional args to requireNativeComponent in .android.js files Reviewed By: sahrens Differential Revision: D8345921 fbshipit-source-id: 187048ad4c1b361f0b99b993052bdcaf47a266db --- .../Components/CheckBox/CheckBox.android.js | 10 ++------- .../DrawerLayoutAndroid.android.js | 5 +---- .../Picker/PickerAndroid.android.js | 21 +++---------------- .../ProgressBarAndroid.android.js | 11 +--------- .../Components/TabBarIOS/TabBarItemIOS.ios.js | 2 +- .../ToolbarAndroid/ToolbarAndroid.android.js | 7 +------ .../ViewPager/ViewPagerAndroid.android.js | 7 ++----- .../Components/WebView/WebView.android.js | 14 +------------ Libraries/Components/WebView/WebView.ios.js | 18 +--------------- Libraries/Image/Image.android.js | 19 +++-------------- .../js/SubviewsClippingTestModule.js | 3 +-- 11 files changed, 17 insertions(+), 100 deletions(-) diff --git a/Libraries/Components/CheckBox/CheckBox.android.js b/Libraries/Components/CheckBox/CheckBox.android.js index 5417a0e811debe..0c7f13decd8c13 100644 --- a/Libraries/Components/CheckBox/CheckBox.android.js +++ b/Libraries/Components/CheckBox/CheckBox.android.js @@ -18,6 +18,8 @@ const ViewPropTypes = require('ViewPropTypes'); const createReactClass = require('create-react-class'); const requireNativeComponent = require('requireNativeComponent'); +const RCTCheckBox = requireNativeComponent('AndroidCheckBox'); + type DefaultProps = { value: boolean, disabled: boolean, @@ -155,12 +157,4 @@ let styles = StyleSheet.create({ }, }); -let RCTCheckBox = requireNativeComponent('AndroidCheckBox', CheckBox, { - nativeOnly: { - onChange: true, - on: true, - enabled: true, - }, -}); - module.exports = CheckBox; diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index 6b983cb2ad27f9..d4b3fa9f7f63d0 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -321,9 +321,6 @@ const styles = StyleSheet.create({ }); // The View that contains both the actual drawer and the main view -const AndroidDrawerLayout = requireNativeComponent( - 'AndroidDrawerLayout', - DrawerLayoutAndroid, -); +const AndroidDrawerLayout = requireNativeComponent('AndroidDrawerLayout'); module.exports = DrawerLayoutAndroid; diff --git a/Libraries/Components/Picker/PickerAndroid.android.js b/Libraries/Components/Picker/PickerAndroid.android.js index c0ce723e479abb..1f80aa3928d05c 100644 --- a/Libraries/Components/Picker/PickerAndroid.android.js +++ b/Libraries/Components/Picker/PickerAndroid.android.js @@ -21,6 +21,9 @@ const ViewStylePropTypes = require('ViewStylePropTypes'); const processColor = require('processColor'); const requireNativeComponent = require('requireNativeComponent'); +const DropdownPicker = requireNativeComponent('AndroidDropdownPicker'); +const DialogPicker = requireNativeComponent('AndroidDialogPicker'); + const REF_PICKER = 'picker'; const MODE_DROPDOWN = 'dropdown'; @@ -158,22 +161,4 @@ const styles = StyleSheet.create({ }, }); -const cfg = { - nativeOnly: { - items: true, - selected: true, - }, -}; - -const DropdownPicker = requireNativeComponent( - 'AndroidDropdownPicker', - PickerAndroid, - cfg, -); -const DialogPicker = requireNativeComponent( - 'AndroidDialogPicker', - PickerAndroid, - cfg, -); - module.exports = PickerAndroid; diff --git a/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js b/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js index 9ee432f56bd5a2..7ea083dd0f19f8 100644 --- a/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js +++ b/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js @@ -12,7 +12,6 @@ const ColorPropType = require('ColorPropType'); const PropTypes = require('prop-types'); const React = require('React'); -const ReactNative = require('ReactNative'); const ViewPropTypes = require('ViewPropTypes'); const requireNativeComponent = require('requireNativeComponent'); @@ -115,15 +114,7 @@ class ProgressBarAndroid extends React.Component { } } -const AndroidProgressBar = requireNativeComponent( - 'AndroidProgressBar', - ProgressBarAndroid, - { - nativeOnly: { - animating: true, - }, - }, -); +const AndroidProgressBar = requireNativeComponent('AndroidProgressBar'); module.exports = React.forwardRef((props, ref) => ( diff --git a/Libraries/Components/TabBarIOS/TabBarItemIOS.ios.js b/Libraries/Components/TabBarIOS/TabBarItemIOS.ios.js index 44fb44da448681..b8825977a8cac6 100644 --- a/Libraries/Components/TabBarIOS/TabBarItemIOS.ios.js +++ b/Libraries/Components/TabBarIOS/TabBarItemIOS.ios.js @@ -143,6 +143,6 @@ const styles = StyleSheet.create({ }, }); -const RCTTabBarItem = requireNativeComponent('RCTTabBarItem', TabBarItemIOS); +const RCTTabBarItem = requireNativeComponent('RCTTabBarItem'); module.exports = TabBarItemIOS; diff --git a/Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js b/Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js index 5fc04a42530173..44bcfc03d8046e 100644 --- a/Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js +++ b/Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js @@ -13,7 +13,6 @@ const Image = require('Image'); const NativeMethodsMixin = require('NativeMethodsMixin'); const React = require('React'); const PropTypes = require('prop-types'); -const ReactNativeViewAttributes = require('ReactNativeViewAttributes'); const UIManager = require('UIManager'); const ViewPropTypes = require('ViewPropTypes'); const ColorPropType = require('ColorPropType'); @@ -207,10 +206,6 @@ const ToolbarAndroid = createReactClass({ }, }); -const NativeToolbar = requireNativeComponent('ToolbarAndroid', ToolbarAndroid, { - nativeOnly: { - nativeActions: true, - }, -}); +const NativeToolbar = requireNativeComponent('ToolbarAndroid'); module.exports = ToolbarAndroid; diff --git a/Libraries/Components/ViewPager/ViewPagerAndroid.android.js b/Libraries/Components/ViewPager/ViewPagerAndroid.android.js index 4b75cfb42d5219..2ccdd31b56365d 100644 --- a/Libraries/Components/ViewPager/ViewPagerAndroid.android.js +++ b/Libraries/Components/ViewPager/ViewPagerAndroid.android.js @@ -19,6 +19,8 @@ const ViewPropTypes = require('ViewPropTypes'); const dismissKeyboard = require('dismissKeyboard'); const requireNativeComponent = require('requireNativeComponent'); +const NativeAndroidViewPager = requireNativeComponent('AndroidViewPager'); + const VIEWPAGER_REF = 'viewPager'; type Event = Object; @@ -255,9 +257,4 @@ class ViewPagerAndroid extends React.Component<{ } } -const NativeAndroidViewPager = requireNativeComponent( - 'AndroidViewPager', - ViewPagerAndroid, -); - module.exports = ViewPagerAndroid; diff --git a/Libraries/Components/WebView/WebView.android.js b/Libraries/Components/WebView/WebView.android.js index 0d1c7b0c90d996..4d4b65fb11fdc8 100644 --- a/Libraries/Components/WebView/WebView.android.js +++ b/Libraries/Components/WebView/WebView.android.js @@ -43,14 +43,6 @@ const defaultRenderLoading = () => ( * Renders a native WebView. */ class WebView extends React.Component { - static get extraNativeComponentConfig() { - return { - nativeOnly: { - messagingEnabled: PropTypes.bool, - }, - }; - } - static propTypes = { ...ViewPropTypes, renderError: PropTypes.func, @@ -464,11 +456,7 @@ class WebView extends React.Component { }; } -const RCTWebView = requireNativeComponent( - 'RCTWebView', - WebView, - WebView.extraNativeComponentConfig, -); +const RCTWebView = requireNativeComponent('RCTWebView'); const styles = StyleSheet.create({ container: { diff --git a/Libraries/Components/WebView/WebView.ios.js b/Libraries/Components/WebView/WebView.ios.js index 8d78103d70134d..ca91bc3b877edc 100644 --- a/Libraries/Components/WebView/WebView.ios.js +++ b/Libraries/Components/WebView/WebView.ios.js @@ -109,18 +109,6 @@ const defaultRenderError = (errorDomain, errorCode, errorDesc) => ( class WebView extends React.Component { static JSNavigationScheme = JSNavigationScheme; static NavigationType = NavigationType; - static get extraNativeComponentConfig() { - return { - nativeOnly: { - onLoadingStart: true, - onLoadingError: true, - onLoadingFinish: true, - onMessage: true, - messagingEnabled: PropTypes.bool, - }, - }; - } - static propTypes = { ...ViewPropTypes, @@ -651,11 +639,7 @@ class WebView extends React.Component { }; } -const RCTWebView = requireNativeComponent( - 'RCTWebView', - WebView, - WebView.extraNativeComponentConfig, -); +const RCTWebView = requireNativeComponent('RCTWebView'); const styles = StyleSheet.create({ container: { diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index cf87d4bc782ead..350bba68ea8934 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -29,6 +29,9 @@ const resolveAssetSource = require('resolveAssetSource'); const {ImageLoader} = NativeModules; +const RKImage = requireNativeComponent('RCTImageView'); +const RCTTextInlineImage = requireNativeComponent('RCTTextInlineImage'); + let _requestId = 1; function generateRequestId() { return _requestId++; @@ -278,20 +281,4 @@ const styles = StyleSheet.create({ }, }); -const cfg = { - nativeOnly: { - src: true, - headers: true, - defaultSrc: true, - loadingIndicatorSrc: true, - shouldNotifyLoadEvents: true, - }, -}; -const RKImage = requireNativeComponent('RCTImageView', Image, cfg); -const RCTTextInlineImage = requireNativeComponent( - 'RCTTextInlineImage', - Image, - cfg, -); - module.exports = Image; diff --git a/ReactAndroid/src/androidTest/js/SubviewsClippingTestModule.js b/ReactAndroid/src/androidTest/js/SubviewsClippingTestModule.js index 9f19e0e390342a..312dcb2c5d633b 100644 --- a/ReactAndroid/src/androidTest/js/SubviewsClippingTestModule.js +++ b/ReactAndroid/src/androidTest/js/SubviewsClippingTestModule.js @@ -11,14 +11,13 @@ var BatchedBridge = require('BatchedBridge'); var React = require('React'); -var ReactNativeViewAttributes = require('ReactNativeViewAttributes'); var ScrollView = require('ScrollView'); var StyleSheet = require('StyleSheet'); var View = require('View'); var requireNativeComponent = require('requireNativeComponent'); -var ClippableView = requireNativeComponent('ClippableView', null); +var ClippableView = requireNativeComponent('ClippableView'); class ClippingSample1 extends React.Component { render() { From e315ec9891eb0bcb51afb0e797dbd49aa8f9ac71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= <165856+hramos@users.noreply.github.com> Date: Sun, 10 Jun 2018 16:53:22 -0700 Subject: [PATCH 19/22] Fix iOS e2e tests: bump react-native-babel-preset to ^5 (#19625) Summary: We opt in to version ^5 of the React Native Babel Preset, as required after the bump to Babel 7. This fixes the Objective-C end-to-end test failure in master. (Fixes #19538) See https://github.com/facebook/react-native/commit/34bd776af2f2529009188fced91083203a48fd40#commitcomment-29024085 for prior discussion. There have already been several changes made to the repo during the transition to Babel 7. This PR brings all tests back to green and allows us to move forward with the 0.56 branch cut. We also bump our tests to use Xcode 9.4.0 and iOS 11.4, the latest stable versions of both. Once the 0.56 branch makes it to stable, we can change `react-native-babel-preset@latest` on npm to point to `react-native-babel-preset@5.0.1` (or newer), and undo the change made to `init.js` we made as part of this diff. Wait for Circle CI to run: https://circleci.com/workflow-run/e39a66d7-bf8a-4b31-a22f-eef30a2c53bc [GENERAL] [BREAKING] [Babel] - Bump React Native Babel Preset version used by RN CLI to Babel v7 compliant release Closes https://github.com/facebook/react-native/pull/19625 Reviewed By: TheSavior Differential Revision: D8343861 Pulled By: hramos fbshipit-source-id: 42644d5b0bfb40a8bc592ae3461c5008deef8232 --- .circleci/config.yml | 50 ++++++++++++------- .../run-android-ci-instrumentation-tests.js | 8 +-- local-cli/init/init.js | 2 +- scripts/.tests.env | 2 +- scripts/objc-test-ios.sh | 7 +-- scripts/objc-test-tvos.sh | 7 +-- scripts/objc-test.sh | 2 +- scripts/run-ci-e2e-tests.js | 50 +++++++++++++------ 8 files changed, 84 insertions(+), 44 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f77c7392272bb2..185be9135eb451 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -198,7 +198,7 @@ aliases: # eslint sometimes runs into trouble generating the reports - &run-lint-checks name: Lint code - command: scripts/circleci/exec_swallow_error.sh yarn lint --format junit -o ~/react-native/reports/junit/js-lint-results.xml + command: scripts/circleci/exec_swallow_error.sh yarn lint --format junit -o ~/react-native/reports/junit/eslint/results.xml when: always - &run-flow-checks @@ -274,6 +274,14 @@ aliases: mkdir -p ~/react-native/reports/junit/ mkdir -p ~/react-native/reports/outputs/ + - &boot-simulator-iphone + name: Boot iPhone Simulator + command: xcrun simctl boot "iPhone 5s" || true + + - &boot-simulator-appletv + name: Boot Apple TV Simulator + command: xcrun simctl boot "Apple TV" || true + - &run-objc-ios-tests name: iOS Test Suite command: ./scripts/objc-test-ios.sh test @@ -282,9 +290,13 @@ aliases: name: tvOS Test Suite command: ./scripts/objc-test-tvos.sh test + - &run-e2e-tests + name: End-to-End Test Suite + command: node ./scripts/run-ci-e2e-tests.js --ios --tvos --js --retries 3; + - &run-objc-ios-e2e-tests name: iOS End-to-End Test Suite - command: node ./scripts/run-ci-e2e-tests.js --ios --js --retries 3; + command: node ./scripts/run-ci-e2e-tests.js --ios --retries 3; - &run-objc-tvos-e2e-tests name: tvOS End-to-End Test Suite @@ -374,8 +386,7 @@ jobs: - attach_workspace: at: ~/react-native - - run: xcrun instruments -w "iPhone 5s (11.4)" || true - # See https://github.com/Homebrew/homebrew-core/issues/26358. + - run: *boot-simulator-iphone - run: brew install watchman - run: *run-objc-ios-tests @@ -389,8 +400,7 @@ jobs: - attach_workspace: at: ~/react-native - - run: xcrun instruments -w "Apple TV (11.4)" || true - # See https://github.com/Homebrew/homebrew-core/issues/26358. + - run: *boot-simulator-appletv - run: brew install watchman - run: *run-objc-tvos-tests @@ -398,13 +408,27 @@ jobs: path: ~/react-native/reports/junit # Runs end to end tests - test_ios_e2e: + test_end_to_end: <<: *macos_defaults steps: - attach_workspace: at: ~/react-native - - run: xcrun instruments -w "iPhone 5s (11.4)" || true + - run: *boot-simulator-iphone + + - run: + name: Configure Environment Variables + command: | + echo 'export PATH=/usr/local/opt/node@8/bin:$PATH' >> $BASH_ENV + source $BASH_ENV + + - run: + name: Install Node 8 + command: | + brew install node@8 + brew link node@8 + node -v + - run: *run-objc-ios-e2e-tests - store_test_results: @@ -623,7 +647,7 @@ workflows: - checkout_code # End-to-end tests - - test_ios_e2e: + - test_end_to_end: filters: *filter-ignore-gh-pages requires: - checkout_code @@ -670,11 +694,3 @@ workflows: # filters: *filter-ignore-gh-pages # requires: # - checkout_code - -experimental: - notify: - webhooks: - - url: https://code.facebook.com/circle/webhook/ - branches: - only: - - master diff --git a/ContainerShip/scripts/run-android-ci-instrumentation-tests.js b/ContainerShip/scripts/run-android-ci-instrumentation-tests.js index 706159c4902bc4..c16c7990ed317d 100644 --- a/ContainerShip/scripts/run-android-ci-instrumentation-tests.js +++ b/ContainerShip/scripts/run-android-ci-instrumentation-tests.js @@ -28,7 +28,7 @@ const path = require('path'); const colors = { GREEN: '\x1b[32m', RED: '\x1b[31m', - RESET: '\x1b[0m' + RESET: '\x1b[0m', }; const test_opts = { @@ -41,7 +41,7 @@ const test_opts = { TEST_TIMEOUT: parseInt(argv['test-timeout'] || 1000 * 60 * 10), OFFSET: argv.offset, - COUNT: argv.count + COUNT: argv.count, }; let max_test_class_length = Number.NEGATIVE_INFINITY; @@ -88,7 +88,7 @@ return async.mapSeries(testClasses, (clazz, callback) => { return async.retry(test_opts.RETRIES, (retryCb) => { const test_process = child_process.spawn('./ContainerShip/scripts/run-instrumentation-tests-via-adb-shell.sh', [test_opts.PACKAGE, clazz], { - stdio: 'inherit' + stdio: 'inherit', }); const timeout = setTimeout(() => { @@ -112,7 +112,7 @@ return async.mapSeries(testClasses, (clazz, callback) => { }, (err) => { return callback(null, { name: clazz, - status: err ? 'failure' : 'success' + status: err ? 'failure' : 'success', }); }); }, (err, results) => { diff --git a/local-cli/init/init.js b/local-cli/init/init.js index 17273f9881d847..d7497a4a828476 100644 --- a/local-cli/init/init.js +++ b/local-cli/init/init.js @@ -99,7 +99,7 @@ function generateProject(destinationRoot, newProjectName, options) { }); } if (!options['skip-jest']) { - const jestDeps = `jest babel-jest babel-preset-react-native react-test-renderer@${reactVersion}`; + const jestDeps = `jest babel-jest babel-preset-react-native@^5 react-test-renderer@${reactVersion}`; if (yarnVersion) { console.log('Adding Jest...'); execSync(`yarn add ${jestDeps} --dev --exact`, {stdio: 'inherit'}); diff --git a/scripts/.tests.env b/scripts/.tests.env index a03f487abe4d73..285578295970c9 100644 --- a/scripts/.tests.env +++ b/scripts/.tests.env @@ -17,7 +17,7 @@ export AVD_NAME="testAVD" export AVD_ABI=x86 ## IOS ## -export IOS_TARGET_OS="11.3" +export IOS_TARGET_OS="11.4" export IOS_DEVICE="iPhone 5s" export SCHEME="RNTester" diff --git a/scripts/objc-test-ios.sh b/scripts/objc-test-ios.sh index eaa4f7a8686511..d466f877540add 100755 --- a/scripts/objc-test-ios.sh +++ b/scripts/objc-test-ios.sh @@ -13,9 +13,10 @@ ROOT=$(dirname "$SCRIPTS") cd "$ROOT" -SCHEME="RNTester" -SDK="iphonesimulator" -DESTINATION="platform=iOS Simulator,name=iPhone 5s,OS=10.3.1" +export TEST_NAME="iOS" +export SCHEME="RNTester" +export SDK="iphonesimulator" +export DESTINATION="platform=iOS Simulator,name=iPhone 5s,OS=11.4" # If there's a "test" argument, pass it to the test script. . ./scripts/objc-test.sh $1 diff --git a/scripts/objc-test-tvos.sh b/scripts/objc-test-tvos.sh index 9d17f7defeb6c2..98016598df0ff4 100755 --- a/scripts/objc-test-tvos.sh +++ b/scripts/objc-test-tvos.sh @@ -13,9 +13,10 @@ ROOT=$(dirname "$SCRIPTS") cd "$ROOT" -SCHEME="RNTester-tvOS" -SDK="appletvsimulator" -DESTINATION="platform=tvOS Simulator,name=Apple TV 1080p,OS=10.2" +export TEST_NAME="tvOS" +export SCHEME="RNTester-tvOS" +export SDK="appletvsimulator" +export DESTINATION="platform=tvOS Simulator,name=Apple TV,OS=11.4" # If there's a "test" argument, pass it to the test script. . ./scripts/objc-test.sh $1 diff --git a/scripts/objc-test.sh b/scripts/objc-test.sh index f2c0459989daaa..c2a9a94d182e7b 100755 --- a/scripts/objc-test.sh +++ b/scripts/objc-test.sh @@ -79,7 +79,7 @@ xcodebuild \ -sdk $SDK \ -destination "$DESTINATION" \ build test \ - | xcpretty --report junit --output ~/react-native/reports/junit/objc-xcodebuild-results.xml + | xcpretty --report junit --output "$HOME/react-native/reports/junit/$TEST_NAME/results.xml" else diff --git a/scripts/run-ci-e2e-tests.js b/scripts/run-ci-e2e-tests.js index f3096c083a2821..ba436a27ad46a7 100644 --- a/scripts/run-ci-e2e-tests.js +++ b/scripts/run-ci-e2e-tests.js @@ -104,8 +104,8 @@ try { cd('EndToEndTest'); if (argv.android) { - echo('Running an Android e2e test'); - echo('Installing e2e framework'); + echo('Running an Android end-to-end test'); + echo('Installing end-to-end framework'); if ( tryExecNTimes( () => @@ -155,14 +155,14 @@ try { SERVER_PID = packagerProcess.pid; // wait a bit to allow packager to startup exec('sleep 15s'); - echo('Executing android e2e test'); + echo('Executing android end-to-end test'); if ( tryExecNTimes(() => { exec('sleep 10s'); return exec('node node_modules/.bin/_mocha android-e2e-test.js').code; }, numberOfRetries) ) { - echo('Failed to run Android e2e tests'); + echo('Failed to run Android end-to-end tests'); echo('Most likely the code is broken'); exitCode = 1; throw Error(exitCode); @@ -171,7 +171,7 @@ try { if (argv.ios || argv.tvos) { var iosTestType = argv.tvos ? 'tvOS' : 'iOS'; - echo('Running the ' + iosTestType + 'app'); + echo('Running the ' + iosTestType + ' app'); cd('ios'); // Make sure we installed local version of react-native if (!test('-e', path.join('EndToEndTest', path.basename(MARKER_IOS)))) { @@ -193,22 +193,44 @@ try { 'response=$(curl --write-out %{http_code} --silent --output /dev/null localhost:8081/index.bundle?platform=ios&dev=true)', ); echo(`Starting packager server, ${SERVER_PID}`); - echo('Executing ' + iosTestType + ' e2e test'); + echo('Executing ' + iosTestType + ' end-to-end test'); if ( tryExecNTimes(() => { exec('sleep 10s'); + let destination = 'platform=iOS Simulator,name=iPhone 5s,OS=11.4'; + let sdk = 'iphonesimulator'; + let scheme = 'EndToEndTest'; + if (argv.tvos) { - return exec( - 'xcodebuild -destination "platform=tvOS Simulator,name=Apple TV 1080p,OS=10.0" -scheme EndToEndTest-tvOS -sdk appletvsimulator test | xcpretty && exit ${PIPESTATUS[0]}', - ).code; - } else { - return exec( - 'xcodebuild -destination "platform=iOS Simulator,name=iPhone 5s,OS=10.3.1" -scheme EndToEndTest -sdk iphonesimulator test | xcpretty && exit ${PIPESTATUS[0]}', - ).code; + destination = 'platform=tvOS Simulator,name=Apple TV,OS=11.4'; + sdk = 'appletvsimulator'; + scheme = 'EndToEndTest-tvOS'; } + + return exec( + [ + 'xcodebuild', + '-destination', + `"${destination}"`, + '-scheme', + `"${scheme}"`, + '-sdk', + sdk, + 'test', + ].join(' ') + + ' | ' + + [ + 'xcpretty', + '--report', + 'junit', + '--output', + `"~/react-native/reports/junit/${iosTestType}-e2e/results.xml"`, + ].join(' ') + + ' && exit ${PIPESTATUS[0]}', + ).code; }, numberOfRetries) ) { - echo('Failed to run ' + iosTestType + ' e2e tests'); + echo('Failed to run ' + iosTestType + ' end-to-end tests'); echo('Most likely the code is broken'); exitCode = 1; throw Error(exitCode); From 3bed272a620ac806a6142327013265ea8138641a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Sun, 10 Jun 2018 17:43:36 -0700 Subject: [PATCH 20/22] Upgrade to Flow v0.74.0 Reviewed By: panagosg7 Differential Revision: D8322344 fbshipit-source-id: 1208528009785f7f797201777287af525d0a9ca1 --- .flowconfig | 2 +- local-cli/templates/HelloWorld/_flowconfig | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.flowconfig b/.flowconfig index 10c13ea400f5ec..32624ea479b9da 100644 --- a/.flowconfig +++ b/.flowconfig @@ -74,4 +74,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError [version] -^0.73.0 +^0.74.0 diff --git a/local-cli/templates/HelloWorld/_flowconfig b/local-cli/templates/HelloWorld/_flowconfig index 49487641bc4147..2f3267d3164c73 100644 --- a/local-cli/templates/HelloWorld/_flowconfig +++ b/local-cli/templates/HelloWorld/_flowconfig @@ -51,4 +51,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError [version] -^0.73.0 +^0.74.0 diff --git a/package.json b/package.json index db192e67092c6f..16554be62ee184 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.73.0", + "flow-bin": "^0.74.0", "jest": "23.1.0", "jest-junit": "4.0.0", "prettier": "1.13.4", From 4aeefa54844b87a0a2aafa2726447d139d1ac89f Mon Sep 17 00:00:00 2001 From: Eli White Date: Sun, 10 Jun 2018 22:26:00 -0700 Subject: [PATCH 21/22] Open source Flow definition for Jest Reviewed By: sahrens Differential Revision: D8347198 fbshipit-source-id: 0b6194bfd14bad09db7dcd462f0bf342c9c6fe44 --- flow/jest.js | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 flow/jest.js diff --git a/flow/jest.js b/flow/jest.js new file mode 100644 index 00000000000000..7f6b795732556c --- /dev/null +++ b/flow/jest.js @@ -0,0 +1,179 @@ +/** + * 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. + * + * Modified from https://raw.githubusercontent.com/flowtype/flow-typed/e3b0f3034929e0f0fb85c790450a201b380ac2fd/definitions/npm/jest_v17.x.x/flow_v0.33.x-/jest_v17.x.x.js + * Duplicated from www/flow/shared/jest.js + * @flow + * @format + */ + +'use strict'; + +type JestMockFn = { + (...args: Array): any, + mock: { + calls: Array>, + instances: mixed, + }, + mockClear(): Function, + mockReset(): Function, + mockImplementation(fn: Function): JestMockFn, + mockImplementationOnce(fn: Function): JestMockFn, + mockReturnThis(): void, + mockReturnValue(value: any): JestMockFn, + mockReturnValueOnce(value: any): JestMockFn, +}; + +type JestAsymmetricEqualityType = { + asymmetricMatch(value: mixed): boolean, +}; + +type JestCallsType = { + allArgs(): mixed, + all(): mixed, + any(): boolean, + count(): number, + first(): mixed, + mostRecent(): mixed, + reset(): void, +}; + +type JestClockType = { + install(): void, + mockDate(date: Date): void, + tick(): void, + uninstall(): void, +}; + +type JestMatcherResult = { + message?: string | (() => string), + pass: boolean, +}; + +type JestMatcher = (actual: any, expected: any) => JestMatcherResult; + +type JestPromiseType = { + /** + * Use rejects to unwrap the reason of a rejected promise so any other + * matcher can be chained. If the promise is fulfilled the assertion fails. + */ + rejects: JestExpectType, + /** + * Use resolves to unwrap the value of a fulfilled promise so any other + * matcher can be chained. If the promise is rejected the assertion fails. + */ + resolves: JestExpectType, +}; + +type JestExpectType = { + not: JestExpectType, + lastCalledWith(...args: Array): void, + toBe(value: any): void, + toBeCalled(): void, + toBeCalledWith(...args: Array): void, + toBeCloseTo(num: number, delta: any): void, + toBeDefined(): void, + toBeFalsy(): void, + toBeGreaterThan(number: number): void, + toBeGreaterThanOrEqual(number: number): void, + toBeLessThan(number: number): void, + toBeLessThanOrEqual(number: number): void, + toBeInstanceOf(cls: Class<*>): void, + toBeNull(): void, + toBeTruthy(): void, + toBeUndefined(): void, + toContain(item: any): void, + toContainEqual(item: any): void, + toEqual(value: any): void, + toHaveBeenCalled(): void, + toHaveBeenCalledTimes(number: number): void, + toHaveBeenCalledWith(...args: Array): void, + toHaveProperty(path: string, value?: any): void, + toMatch(regexp: RegExp): void, + toMatchObject(object: Object): void, + toMatchSnapshot(): void, + toThrow(message?: string | Error | Class): void, + toThrowError(message?: string | Error | Class | RegExp): void, + toThrowErrorMatchingSnapshot(): void, +}; + +type JestSpyType = { + calls: JestCallsType, +}; + +declare function afterEach(fn: Function): void; +declare function beforeEach(fn: Function): void; +declare function afterAll(fn: Function): void; +declare function beforeAll(fn: Function): void; +declare function describe(name: string, fn: Function): void; +declare var it: { + (name: string, fn: Function): ?Promise, + only(name: string, fn: Function): ?Promise, + skip(name: string, fn: Function): ?Promise, +}; +declare function fit(name: string, fn: Function): ?Promise; +declare function pit(name: string, fn: () => Promise): Promise; +declare var test: typeof it; +declare var xdescribe: typeof describe; +declare var fdescribe: typeof describe; +declare var xit: typeof it; +declare var xtest: typeof it; + +declare var expect: { + (value: any): JestExpectType & JestPromiseType, + any: any, + extend(matchers: {[name: string]: JestMatcher}): void, + objectContaining(any): void, +}; +declare function fail(message?: string): void; + +// TODO handle return type +// http://jasmine.github.io/2.4/introduction.html#section-Spies +declare function spyOn(value: mixed, method: string): Object; + +type Jest = { + autoMockOff(): Jest, + autoMockOn(): Jest, + resetAllMocks(): Jest, + clearAllTimers(): void, + currentTestPath(): void, + disableAutomock(): Jest, + doMock(moduleName: string, moduleFactory?: any): void, + dontMock(moduleName: string): Jest, + enableAutomock(): Jest, + fn(implementation?: Function): JestMockFn, + genMockFromModule(moduleName: string): any, + isMockFunction(fn: Function): boolean, + mock( + moduleName: string, + moduleFactory?: any, + options?: {virtual?: boolean}, + ): Jest, + resetModuleRegistry(): Jest, // undocumented alias for resetModuleRegistry + resetModules(): Jest, + restoreAllMocks(): Jest, + runAllTicks(): Jest, + runAllTimers(): Jest, + runTimersToTime(msToRun: number): Jest, + runOnlyPendingTimers(): Jest, + setMock(moduleName: string, moduleExports: any): Jest, + unmock(moduleName: string): Jest, + useFakeTimers(): Jest, + useRealTimers(): Jest, +}; + +declare var jest: Jest; + +declare var jasmine: { + DEFAULT_TIMEOUT_INTERVAL: number, + any(value: mixed): JestAsymmetricEqualityType, + anything(): void, + arrayContaining(value: Array): void, + clock(): JestClockType, + createSpy(name: string): JestSpyType, + objectContaining(value: Object): void, + stringMatching(value: string): void, +}; From c3c5c3cbce24a31f73ae6339e377ee76ca6401ad Mon Sep 17 00:00:00 2001 From: Vince Mi Date: Mon, 11 Jun 2018 04:07:38 -0700 Subject: [PATCH 22/22] Add back deprecated getParent methods for non-breaking API change (#775) Summary: I'm not totally sure what I'm doing so if this needs changes let me know. Closes https://github.com/facebook/yoga/pull/775 Reviewed By: emilsjolander Differential Revision: D8331892 Pulled By: passy fbshipit-source-id: eb1023e666322d2472e4081fd4a4e72a7b43d049 --- ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java | 5 ++--- ReactCommon/yoga/yoga/YGNode.cpp | 4 ++++ ReactCommon/yoga/yoga/YGNode.h | 2 ++ ReactCommon/yoga/yoga/Yoga.cpp | 4 ++++ ReactCommon/yoga/yoga/Yoga.h | 1 + 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java index fdb5b4be5017c1..90caf8f81e0131 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java @@ -234,15 +234,14 @@ public YogaNode removeChildAt(int i) { * {@link YogaNode} is shared between two or more YogaTrees. */ @Nullable - public - YogaNode getOwner() { + public YogaNode getOwner() { return mOwner; } /** @deprecated Use #getOwner() instead. This will be removed in the next version. */ @Deprecated @Nullable - YogaNode getParent() { + public YogaNode getParent() { return getOwner(); } diff --git a/ReactCommon/yoga/yoga/YGNode.cpp b/ReactCommon/yoga/yoga/YGNode.cpp index 64a47d356a373f..16f9e4d0092eca 100644 --- a/ReactCommon/yoga/yoga/YGNode.cpp +++ b/ReactCommon/yoga/yoga/YGNode.cpp @@ -53,6 +53,10 @@ YGNodeRef YGNode::getOwner() const { return owner_; } +YGNodeRef YGNode::getParent() const { + return getOwner(); +} + YGVector YGNode::getChildren() const { return children_; } diff --git a/ReactCommon/yoga/yoga/YGNode.h b/ReactCommon/yoga/yoga/YGNode.h index 96541a575eeb20..e3562bb605299b 100644 --- a/ReactCommon/yoga/yoga/YGNode.h +++ b/ReactCommon/yoga/yoga/YGNode.h @@ -78,6 +78,8 @@ struct YGNode { // to one YogaTree or nullptr when the YGNode is shared between two or more // YogaTrees. YGNodeRef getOwner() const; + // Deprecated, use getOwner() instead. + YGNodeRef getParent() const; YGVector getChildren() const; uint32_t getChildrenCount() const; YGNodeRef getChild(uint32_t index) const; diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index a927ef556c4734..c6a8ffd2ea1e48 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -535,6 +535,10 @@ YGNodeRef YGNodeGetOwner(const YGNodeRef node) { return node->getOwner(); } +YGNodeRef YGNodeGetParent(const YGNodeRef node) { + return node->getOwner(); +} + void YGNodeMarkDirty(const YGNodeRef node) { YGAssertWithNode( node, diff --git a/ReactCommon/yoga/yoga/Yoga.h b/ReactCommon/yoga/yoga/Yoga.h index 25eb0eb6f5a821..a9fc89d7df4d2c 100644 --- a/ReactCommon/yoga/yoga/Yoga.h +++ b/ReactCommon/yoga/yoga/Yoga.h @@ -92,6 +92,7 @@ WIN_EXPORT void YGNodeRemoveChild(const YGNodeRef node, const YGNodeRef child); WIN_EXPORT void YGNodeRemoveAllChildren(const YGNodeRef node); WIN_EXPORT YGNodeRef YGNodeGetChild(const YGNodeRef node, const uint32_t index); WIN_EXPORT YGNodeRef YGNodeGetOwner(const YGNodeRef node); +WIN_EXPORT YGNodeRef YGNodeGetParent(const YGNodeRef node); WIN_EXPORT uint32_t YGNodeGetChildCount(const YGNodeRef node); WIN_EXPORT void YGNodeSetChildren( YGNodeRef const owner,