From 8b4f5073a18d919a39c64c428f58b11059d1b47a Mon Sep 17 00:00:00 2001 From: Andrei Shikov Date: Wed, 1 Sep 2021 07:29:32 -0700 Subject: [PATCH 01/22] Log created views with mounting errors Summary: Displays views from the surface mounting manager after we hit a crash during mounting. This change should help with debugging mounting crashes (e.g. when view is added before removal) Changelog: [Internal] Reviewed By: cortinico Differential Revision: D30681339 fbshipit-source-id: f83cecaf8e418a2fa5aa0713513c51bb1be77013 --- .../fabric/mounting/MountItemDispatcher.java | 10 +++++++++- .../mounting/SurfaceMountingManager.java | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java index 2370e84ba2..ca2c7df44f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java @@ -13,6 +13,7 @@ import static com.facebook.react.fabric.FabricUIManager.ENABLE_FABRIC_LOGS; import static com.facebook.react.fabric.FabricUIManager.IS_DEVELOPMENT_ENVIRONMENT; import android.os.SystemClock; +import android.view.View; import androidx.annotation.AnyThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -274,10 +275,17 @@ public class MountItemDispatcher { executeOrEnqueue(mountItem); } catch (Throwable e) { // If there's an exception, we want to log diagnostics in prod and rethrow. - FLog.e(TAG, "dispatchMountItems: caught exception, displaying all MountItems", e); + FLog.e(TAG, "dispatchMountItems: caught exception, displaying mount state", e); for (MountItem m : mountItemsToDispatch) { printMountItem(m, "dispatchMountItems: mountItem"); } + if (mountItem.getSurfaceId() != View.NO_ID) { + SurfaceMountingManager surfaceManager = + mMountingManager.getSurfaceManager(mountItem.getSurfaceId()); + if (surfaceManager != null) { + surfaceManager.printSurfaceState(); + } + } if (ReactIgnorableMountingException.isIgnorable(e)) { ReactSoftExceptionLogger.logSoftException(TAG, e); diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java index 1f05f824c8..f93d1c20dc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java @@ -963,6 +963,25 @@ public class SurfaceMountingManager { return (ViewGroupManager) viewState.mViewManager; } + public void printSurfaceState() { + FLog.e(TAG, "Views created for surface {%d}:", getSurfaceId()); + for (ViewState viewState : mTagToViewState.values()) { + String viewManagerName = + viewState.mViewManager != null ? viewState.mViewManager.getName() : null; + @Nullable View view = viewState.mView; + @Nullable View parent = view != null ? (View) view.getParent() : null; + @Nullable Integer parentTag = parent != null ? parent.getId() : null; + + FLog.e( + TAG, + "<%s id=%d parentTag=%s isRoot=%b />", + viewManagerName, + viewState.mReactTag, + parentTag, + viewState.mIsRoot); + } + } + /** * This class holds view state for react tags. Objects of this class are stored into the {@link * #mTagToViewState}, and they should be updated in the same thread. From 329b026f3a48a4228a89696540ba459276f9a2c2 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 1 Sep 2021 08:03:06 -0700 Subject: [PATCH 02/22] Switch order of search libraries to fix M1 build error Summary: changelog: Resolve Xcode 13 build error on M1 Macs for projects created from RN template Reviewed By: fkgozali Differential Revision: D30693466 fbshipit-source-id: f0b4fd471de38119d636c8e337831aa4d4599c4e --- packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj | 4 ++-- template/ios/HelloWorld.xcodeproj/project.pbxproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj index d526edbc7d..51a0c03e36 100644 --- a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj +++ b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj @@ -783,10 +783,10 @@ "@executable_path/Frameworks", ); LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", "$(inherited)", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", - "\"$(SDKROOT)/usr/lib/swift\"", ); "LIBRARY_SEARCH_PATHS[arch=*]" = "$(inherited)"; OTHER_LDFLAGS = ( @@ -818,10 +818,10 @@ "@executable_path/Frameworks", ); LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", "$(inherited)", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", - "\"$(SDKROOT)/usr/lib/swift\"", ); OTHER_LDFLAGS = ( "$(inherited)", diff --git a/template/ios/HelloWorld.xcodeproj/project.pbxproj b/template/ios/HelloWorld.xcodeproj/project.pbxproj index b05416f419..fbe9f29272 100644 --- a/template/ios/HelloWorld.xcodeproj/project.pbxproj +++ b/template/ios/HelloWorld.xcodeproj/project.pbxproj @@ -435,10 +435,10 @@ "$(inherited)", ); LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"", "\"$(inherited)\"", - "\"$(SDKROOT)/usr/lib/swift\"", ); MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; @@ -493,10 +493,10 @@ "$(inherited)", ); LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"", "\"$(inherited)\"", - "\"$(SDKROOT)/usr/lib/swift\"", ); MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; From 3e6eedaedb75f736aea170ed4a3544ecc7c33c4d Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 1 Sep 2021 10:08:25 -0700 Subject: [PATCH 03/22] Use surfaceId type instead of int in PropsParserContext Summary: changelog: [internal] Use surfaceId type instead of raw int type in PropsParserContext Reviewed By: RSNara Differential Revision: D30667540 fbshipit-source-id: 2bf890b892851e785318e3566692ac72ec782b91 --- .../react/renderer/attributedstring/AttributedString.h | 1 - ReactCommon/react/renderer/attributedstring/TextAttributes.h | 2 +- ReactCommon/react/renderer/core/ConcreteShadowNode.h | 1 + ReactCommon/react/renderer/core/Props.h | 1 + ReactCommon/react/renderer/core/PropsParserContext.h | 5 +++-- ReactCommon/react/renderer/core/ReactPrimitives.h | 2 -- ReactCommon/react/renderer/core/ShadowNodeFamily.h | 1 + 7 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ReactCommon/react/renderer/attributedstring/AttributedString.h b/ReactCommon/react/renderer/attributedstring/AttributedString.h index f3ed792238..a1058c510b 100644 --- a/ReactCommon/react/renderer/attributedstring/AttributedString.h +++ b/ReactCommon/react/renderer/attributedstring/AttributedString.h @@ -11,7 +11,6 @@ #include #include -#include #include #include #include diff --git a/ReactCommon/react/renderer/attributedstring/TextAttributes.h b/ReactCommon/react/renderer/attributedstring/TextAttributes.h index 87bbffc30e..b7f07b962d 100644 --- a/ReactCommon/react/renderer/attributedstring/TextAttributes.h +++ b/ReactCommon/react/renderer/attributedstring/TextAttributes.h @@ -10,8 +10,8 @@ #include #include +#include #include -#include #include #include #include diff --git a/ReactCommon/react/renderer/core/ConcreteShadowNode.h b/ReactCommon/react/renderer/core/ConcreteShadowNode.h index d441f326a0..8ad8820f59 100644 --- a/ReactCommon/react/renderer/core/ConcreteShadowNode.h +++ b/ReactCommon/react/renderer/core/ConcreteShadowNode.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff --git a/ReactCommon/react/renderer/core/Props.h b/ReactCommon/react/renderer/core/Props.h index 3321310b43..5d99a0139a 100644 --- a/ReactCommon/react/renderer/core/Props.h +++ b/ReactCommon/react/renderer/core/Props.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include diff --git a/ReactCommon/react/renderer/core/PropsParserContext.h b/ReactCommon/react/renderer/core/PropsParserContext.h index 9b9d10d2dc..df4b16d70a 100644 --- a/ReactCommon/react/renderer/core/PropsParserContext.h +++ b/ReactCommon/react/renderer/core/PropsParserContext.h @@ -7,6 +7,7 @@ #pragma once +#include #include namespace facebook { @@ -20,8 +21,8 @@ struct PropsParserContext { PropsParserContext(const PropsParserContext &) = delete; PropsParserContext &operator=(const PropsParserContext &) = delete; - int surfaceId; // TODO: use SurfaceId type - const ContextContainer &contextContainer; + SurfaceId const surfaceId; + ContextContainer const &contextContainer; }; } // namespace react diff --git a/ReactCommon/react/renderer/core/ReactPrimitives.h b/ReactCommon/react/renderer/core/ReactPrimitives.h index 4954fcfff9..28738394bf 100644 --- a/ReactCommon/react/renderer/core/ReactPrimitives.h +++ b/ReactCommon/react/renderer/core/ReactPrimitives.h @@ -8,8 +8,6 @@ #pragma once #include -#include -#include #include #include diff --git a/ReactCommon/react/renderer/core/ShadowNodeFamily.h b/ReactCommon/react/renderer/core/ShadowNodeFamily.h index 2f57666c17..07746e3550 100644 --- a/ReactCommon/react/renderer/core/ShadowNodeFamily.h +++ b/ReactCommon/react/renderer/core/ShadowNodeFamily.h @@ -10,6 +10,7 @@ #include #include +#include #include #include From 66deb8a9c074007a5a0a5ac495853b1246f7047a Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 1 Sep 2021 10:08:25 -0700 Subject: [PATCH 04/22] Pass surfaceId to PropsParserContext when created though native animated Summary: changelog: [internal] Pass surfaceId to PropsParserContext instead of placeholder -1. Reviewed By: RSNara Differential Revision: D30667846 fbshipit-source-id: bed98ad6c829c1346d8eb9e68d7beeb6696d6c4a --- React/Fabric/Mounting/RCTMountingManager.mm | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/React/Fabric/Mounting/RCTMountingManager.mm b/React/Fabric/Mounting/RCTMountingManager.mm index beb1ed2b66..f09ae72ce4 100644 --- a/React/Fabric/Mounting/RCTMountingManager.mm +++ b/React/Fabric/Mounting/RCTMountingManager.mm @@ -10,6 +10,7 @@ #import #import +#import #import #import #import @@ -26,6 +27,18 @@ using namespace facebook::react; +static SurfaceId RCTSurfaceIdForView(UIView *view) +{ + do { + if (RCTIsReactRootView(@(view.tag))) { + return view.tag; + } + view = view.superview; + } while (view != nil); + + return -1; +} + static void RCTPerformMountInstructions( ShadowViewMutationList const &mutations, RCTComponentViewRegistry *registry, @@ -282,9 +295,10 @@ static void RCTPerformMountInstructions( { RCTAssertMainQueue(); UIView *componentView = [_componentViewRegistry findComponentViewWithTag:reactTag]; + SurfaceId surfaceId = RCTSurfaceIdForView(componentView); SharedProps oldProps = [componentView props]; SharedProps newProps = componentDescriptor.cloneProps( - PropsParserContext{-1, *_contextContainer.get()}, oldProps, RawProps(convertIdToFollyDynamic(props))); + PropsParserContext{surfaceId, *_contextContainer.get()}, oldProps, RawProps(convertIdToFollyDynamic(props))); NSSet *propKeys = componentView.propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN ?: [NSSet new]; propKeys = [propKeys setByAddingObjectsFromArray:props.allKeys]; From 569c1cdce9848ad9d2fb03e0ef2edd901723d844 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 1 Sep 2021 10:08:25 -0700 Subject: [PATCH 05/22] Remove unused property _rootTag RCTPropsAnimatedNode Summary: changelog: [internal] `_rootTag` is never assigned to and never read, let's remove it. Reviewed By: RSNara Differential Revision: D30667860 fbshipit-source-id: f4b89ebe6b6d26559188b0e19682f5ac765d40b6 --- Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m | 3 --- 1 file changed, 3 deletions(-) diff --git a/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m b/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m index 102234798b..91acd7dcba 100644 --- a/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m +++ b/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m @@ -16,7 +16,6 @@ @implementation RCTPropsAnimatedNode { NSNumber *_connectedViewTag; - NSNumber *_rootTag; NSString *_connectedViewName; __weak RCTBridge *_bridge; __weak id _surfacePresenter; @@ -48,7 +47,6 @@ _connectedViewTag = viewTag; _connectedViewName = viewName; _managedByFabric = RCTUIManagerTypeForTagIsFabric(viewTag); - _rootTag = nil; } - (void)disconnectFromView:(NSNumber *)viewTag @@ -58,7 +56,6 @@ _connectedViewTag = nil; _connectedViewName = nil; _managedByFabric = NO; - _rootTag = nil; } - (void)updateView From dbda1917cc10a2bb304bc65b3f54ac1c07243a30 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 1 Sep 2021 11:17:41 -0700 Subject: [PATCH 06/22] Make RuntimeScheduler module compile in C++ 14 Summary: changelog: [internal] Don't use C++ 17 features in RuntimeScheduler module as it needs to be imported into C++14 module. Also removes redundant dependency. Reviewed By: ShikaSD Differential Revision: D30485642 fbshipit-source-id: 0a20f85c596eebe193affc815c8ca851fc72e46d --- ReactCommon/react/renderer/runtimescheduler/BUCK | 1 - .../react/renderer/runtimescheduler/RuntimeScheduler.cpp | 6 ++++-- .../react/renderer/runtimescheduler/RuntimeScheduler.h | 6 ++++-- .../renderer/runtimescheduler/RuntimeSchedulerBinding.cpp | 7 ++++--- .../renderer/runtimescheduler/RuntimeSchedulerBinding.h | 6 ++++-- .../renderer/runtimescheduler/RuntimeSchedulerClock.h | 6 ++++-- .../react/renderer/runtimescheduler/SchedulerPriority.h | 7 ++++--- ReactCommon/react/renderer/runtimescheduler/Task.cpp | 6 ++++-- ReactCommon/react/renderer/runtimescheduler/Task.h | 6 ++++-- ReactCommon/react/renderer/runtimescheduler/primitives.h | 6 ++++-- 10 files changed, 36 insertions(+), 21 deletions(-) diff --git a/ReactCommon/react/renderer/runtimescheduler/BUCK b/ReactCommon/react/renderer/runtimescheduler/BUCK index 7cdf02a763..8303728982 100644 --- a/ReactCommon/react/renderer/runtimescheduler/BUCK +++ b/ReactCommon/react/renderer/runtimescheduler/BUCK @@ -50,7 +50,6 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ - react_native_xplat_target("react/renderer/core:core"), react_native_xplat_target("runtimeexecutor:runtimeexecutor"), react_native_xplat_target("react/renderer/debug:debug"), react_native_xplat_target("better:better"), diff --git a/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp b/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp index d1550bc85b..fd47ab4303 100644 --- a/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp +++ b/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp @@ -7,7 +7,8 @@ #include "RuntimeScheduler.h" -namespace facebook::react { +namespace facebook { +namespace react { #pragma mark - Public @@ -113,4 +114,5 @@ void RuntimeScheduler::startWorkLoop(jsi::Runtime &runtime) const { isPerformingWork_ = false; } -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h b/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h index b5dad38ae2..5d18a7d9ea 100644 --- a/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h +++ b/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h @@ -14,7 +14,8 @@ #include #include -namespace facebook::react { +namespace facebook { +namespace react { class RuntimeScheduler final { public: @@ -100,4 +101,5 @@ class RuntimeScheduler final { mutable bool isPerformingWork_{false}; }; -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp index 05a3d3395a..92525118e2 100644 --- a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp +++ b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp @@ -10,11 +10,11 @@ #include "primitives.h" #include -#include #include #include -namespace facebook::react { +namespace facebook { +namespace react { std::shared_ptr RuntimeSchedulerBinding::createAndInstallIfNeeded( @@ -167,4 +167,5 @@ jsi::Value RuntimeSchedulerBinding::get( return jsi::Value::undefined(); } -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h index cc4544d6a8..27c1ad9f31 100644 --- a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h +++ b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h @@ -10,7 +10,8 @@ #include #include -namespace facebook::react { +namespace facebook { +namespace react { /* * Exposes RuntimeScheduler to JavaScript realm. @@ -39,4 +40,5 @@ class RuntimeSchedulerBinding : public jsi::HostObject { std::shared_ptr runtimeScheduler_; }; -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerClock.h b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerClock.h index 25e8b327db..51652ee0a0 100644 --- a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerClock.h +++ b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerClock.h @@ -9,7 +9,8 @@ #include -namespace facebook::react { +namespace facebook { +namespace react { /* * Represents a monotonic clock suitable for measuring intervals. @@ -19,4 +20,5 @@ using RuntimeSchedulerClock = std::chrono::steady_clock; using RuntimeSchedulerTimePoint = RuntimeSchedulerClock::time_point; using RuntimeSchedulerDuration = RuntimeSchedulerClock::duration; -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h b/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h index 4b5a1b7eab..329fe252aa 100644 --- a/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h +++ b/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h @@ -8,10 +8,10 @@ #pragma once #include -#include #include -namespace facebook::react { +namespace facebook { +namespace react { enum class SchedulerPriority : int { ImmediatePriority = 1, @@ -61,4 +61,5 @@ static inline std::chrono::milliseconds timeoutForSchedulerPriority( } } -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/Task.cpp b/ReactCommon/react/renderer/runtimescheduler/Task.cpp index b44d9719a1..bd87944afa 100644 --- a/ReactCommon/react/renderer/runtimescheduler/Task.cpp +++ b/ReactCommon/react/renderer/runtimescheduler/Task.cpp @@ -7,7 +7,8 @@ #include "RuntimeScheduler.h" -namespace facebook::react { +namespace facebook { +namespace react { Task::Task( SchedulerPriority priority, @@ -32,4 +33,5 @@ jsi::Value Task::execute(jsi::Runtime &runtime) { return result; } -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/Task.h b/ReactCommon/react/renderer/runtimescheduler/Task.h index 74c387636e..87676d5db7 100644 --- a/ReactCommon/react/renderer/runtimescheduler/Task.h +++ b/ReactCommon/react/renderer/runtimescheduler/Task.h @@ -12,7 +12,8 @@ #include #include -namespace facebook::react { +namespace facebook { +namespace react { class RuntimeScheduler; class TaskPriorityComparer; @@ -43,4 +44,5 @@ class TaskPriorityComparer { } }; -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/primitives.h b/ReactCommon/react/renderer/runtimescheduler/primitives.h index 7679494145..2283b4cad2 100644 --- a/ReactCommon/react/renderer/runtimescheduler/primitives.h +++ b/ReactCommon/react/renderer/runtimescheduler/primitives.h @@ -11,7 +11,8 @@ #include #include -namespace facebook::react { +namespace facebook { +namespace react { struct TaskWrapper : public jsi::HostObject { TaskWrapper(std::shared_ptr const &task) : task(task) {} @@ -36,4 +37,5 @@ inline static std::shared_ptr taskFromValue( return value.getObject(runtime).getHostObject(runtime)->task; } -} // namespace facebook::react +} // namespace react +} // namespace facebook From e2e39808d35d87b8d828062f53cb980d26e4a78c Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 1 Sep 2021 11:17:41 -0700 Subject: [PATCH 07/22] Remove RuntimeSchedulerManager Summary: Changelog: [internal] Remove RuntimeSchedulerManager on Android in favor of different way to initialise RuntimeScheduler. Reviewed By: ShikaSD Differential Revision: D30486975 fbshipit-source-id: 9fe38de12be452bd9d2c92bb54cf5933ce7555b5 --- .../src/main/java/com/facebook/react/BUCK | 1 - .../facebook/react/ReactInstanceManager.java | 6 --- .../com/facebook/react/runtimescheduler/BUCK | 20 -------- .../RuntimeSchedulerManager.java | 39 ---------------- .../react/runtimescheduler/jni/Android.mk | 34 -------------- .../facebook/react/runtimescheduler/jni/BUCK | 35 -------------- .../react/runtimescheduler/jni/OnLoad.cpp | 15 ------ .../jni/RuntimeSchedulerManager.cpp | 46 ------------------- .../jni/RuntimeSchedulerManager.h | 40 ---------------- 9 files changed, 236 deletions(-) delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/BUCK delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/RuntimeSchedulerManager.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/Android.mk delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/BUCK delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/OnLoad.cpp delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.cpp delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.h diff --git a/ReactAndroid/src/main/java/com/facebook/react/BUCK b/ReactAndroid/src/main/java/com/facebook/react/BUCK index b550756ae1..a32feeb61c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/BUCK @@ -49,7 +49,6 @@ rn_android_library( react_native_target("java/com/facebook/react/config:config"), react_native_target("java/com/facebook/react/turbomodule/core:core"), react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"), - react_native_target("java/com/facebook/react/runtimescheduler:runtimescheduler"), ], exported_deps = [ react_native_target("java/com/facebook/react/modules/core:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index d73c8f7e1e..4c8a8f9797 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -92,7 +92,6 @@ import com.facebook.react.modules.core.ReactChoreographer; import com.facebook.react.modules.debug.interfaces.DeveloperSettings; import com.facebook.react.modules.fabric.ReactFabric; import com.facebook.react.packagerconnection.RequestHandler; -import com.facebook.react.runtimescheduler.RuntimeSchedulerManager; import com.facebook.react.surface.ReactStage; import com.facebook.react.turbomodule.core.TurboModuleManager; import com.facebook.react.turbomodule.core.TurboModuleManagerDelegate; @@ -167,7 +166,6 @@ public class ReactInstanceManager { private final boolean mUseDeveloperSupport; private final boolean mRequireActivity; private @Nullable ComponentNameResolverManager mComponentNameResolverManager; - private @Nullable RuntimeSchedulerManager mRuntimeSchedulerManager; private final @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener; private final Object mReactContextLock = new Object(); private @Nullable volatile ReactContext mCurrentReactContext; @@ -759,7 +757,6 @@ public class ReactInstanceManager { mViewManagerNames = null; } mComponentNameResolverManager = null; - mRuntimeSchedulerManager = null; FLog.d(ReactConstants.TAG, "ReactInstanceManager has been destroyed"); } @@ -1394,9 +1391,6 @@ public class ReactInstanceManager { }); catalystInstance.setGlobalVariable("__fbStaticViewConfig", "true"); } - if (ReactFeatureFlags.enableRuntimeScheduler) { - mRuntimeSchedulerManager = new RuntimeSchedulerManager(catalystInstance.getRuntimeExecutor()); - } ReactMarker.logMarker(ReactMarkerConstants.PRE_RUN_JS_BUNDLE_START); Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "runJSBundle"); diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/BUCK b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/BUCK deleted file mode 100644 index a68079db76..0000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/BUCK +++ /dev/null @@ -1,20 +0,0 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") - -rn_android_library( - name = "runtimescheduler", - srcs = glob(["**/*.java"]), - autoglob = False, - is_androidx = True, - labels = ["supermodule:xplat/default/public.react_native.infra"], - visibility = [ - "PUBLIC", - ], - deps = [ - react_native_target("java/com/facebook/react/runtimescheduler/jni:jni"), - react_native_dep("third-party/android/androidx:annotation"), - react_native_dep("third-party/java/infer-annotations:infer-annotations"), - react_native_dep("libraries/fbjni:java"), - react_native_target("java/com/facebook/react/bridge:bridge"), - react_native_dep("libraries/soloader/java/com/facebook/soloader:soloader"), - ], -) diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/RuntimeSchedulerManager.java b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/RuntimeSchedulerManager.java deleted file mode 100644 index d7846b568c..0000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/RuntimeSchedulerManager.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.runtimescheduler; - -import com.facebook.jni.HybridData; -import com.facebook.proguard.annotations.DoNotStrip; -import com.facebook.proguard.annotations.DoNotStripAny; -import com.facebook.react.bridge.RuntimeExecutor; -import com.facebook.soloader.SoLoader; - -@DoNotStripAny -public class RuntimeSchedulerManager { - - static { - staticInit(); - } - - @DoNotStrip - @SuppressWarnings("unused") - private final HybridData mHybridData; - - public RuntimeSchedulerManager(RuntimeExecutor runtimeExecutor) { - mHybridData = initHybrid(runtimeExecutor); - installJSIBindings(); - } - - private native HybridData initHybrid(RuntimeExecutor runtimeExecutor); - - private native void installJSIBindings(); - - private static void staticInit() { - SoLoader.loadLibrary("runtimeschedulerjni"); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/Android.mk b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/Android.mk deleted file mode 100644 index bb4e320112..0000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/Android.mk +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := runtimeschedulerjni - -LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) - -LOCAL_SHARED_LIBRARIES := libglog libfb libfbjni libglog_init libreact_render_runtimescheduler librrc_native - -LOCAL_STATIC_LIBRARIES := - -LOCAL_C_INCLUDES := $(LOCAL_PATH)/ - -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ - -LOCAL_CFLAGS := \ - -DLOG_TAG=\"ReacTNative\" - -LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall - -include $(BUILD_SHARED_LIBRARY) - -$(call import-module,fbgloginit) -$(call import-module,fb) -$(call import-module,fbjni) -$(call import-module,glog) - -$(call import-module,react/renderer/runtimescheduler) diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/BUCK b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/BUCK deleted file mode 100644 index 426b06a139..0000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/BUCK +++ /dev/null @@ -1,35 +0,0 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "react_native_target", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob") - -rn_xplat_cxx_library( - name = "jni", - srcs = glob(["*.cpp"]), - headers = glob(["*.h"]), - header_namespace = "", - exported_headers = subdir_glob( - [ - ("", "**/*.h"), - ], - prefix = "react/runtimescheduler", - ), - compiler_flags = [ - "-fexceptions", - "-frtti", - "-std=c++17", - "-Wall", - ], - fbandroid_allow_jni_merging = True, - labels = ["supermodule:xplat/default/public.react_native.infra"], - platforms = ANDROID, - preprocessor_flags = [ - "-DLOG_TAG=\"ReactNative\"", - "-DWITH_FBSYSTRACE=1", - ], - soname = "libruntimeschedulerjni.$(ext)", - visibility = ["PUBLIC"], - deps = [ - react_native_xplat_target("react/renderer/runtimescheduler:runtimescheduler"), - react_native_xplat_target("runtimeexecutor:runtimeexecutor"), - react_native_target("jni/react/jni:jni"), - FBJNI_TARGET, - ], -) diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/OnLoad.cpp b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/OnLoad.cpp deleted file mode 100644 index 189de80dfc..0000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/OnLoad.cpp +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include - -#include "RuntimeSchedulerManager.h" - -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { - return facebook::jni::initialize( - vm, [] { facebook::react::RuntimeSchedulerManager::registerNatives(); }); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.cpp b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.cpp deleted file mode 100644 index 2b0d893370..0000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include -#include -#include -#include - -#include "RuntimeSchedulerManager.h" - -namespace facebook { -namespace react { - -RuntimeSchedulerManager::RuntimeSchedulerManager( - RuntimeExecutor runtimeExecutor) - : runtimeExecutor_(runtimeExecutor) {} - -jni::local_ref -RuntimeSchedulerManager::initHybrid( - jni::alias_ref, - jni::alias_ref runtimeExecutor) { - return makeCxxInstance(runtimeExecutor->cthis()->get()); -} - -void RuntimeSchedulerManager::registerNatives() { - registerHybrid({ - makeNativeMethod("initHybrid", RuntimeSchedulerManager::initHybrid), - makeNativeMethod( - "installJSIBindings", RuntimeSchedulerManager::installJSIBindings), - }); -} - -void RuntimeSchedulerManager::installJSIBindings() { - runtimeExecutor_([runtimeExecutor = runtimeExecutor_](jsi::Runtime &runtime) { - auto runtimeScheduler = std::make_shared(runtimeExecutor); - RuntimeSchedulerBinding::createAndInstallIfNeeded( - runtime, runtimeScheduler); - }); -} - -} // namespace react -} // namespace facebook diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.h b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.h deleted file mode 100644 index 6456c7176f..0000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include - -namespace facebook { -namespace react { - -class RuntimeSchedulerManager - : public facebook::jni::HybridClass { - public: - static auto constexpr kJavaDescriptor = - "Lcom/facebook/react/runtimescheduler/RuntimeSchedulerManager;"; - - static facebook::jni::local_ref initHybrid( - jni::alias_ref, - facebook::jni::alias_ref runtimeExecutor); - - static void registerNatives(); - - private: - friend HybridBase; - RuntimeExecutor runtimeExecutor_; - - void installJSIBindings(); - - explicit RuntimeSchedulerManager(RuntimeExecutor runtimeExecutor); -}; - -} // namespace react -} // namespace facebook From c360b1d92b69e1d298b390ec88c4d29c1023945a Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Wed, 1 Sep 2021 14:50:38 -0700 Subject: [PATCH 08/22] Fix non selectable Text in FlatList (#28952) Summary: This issue fixes https://github.com/facebook/react-native/issues/26264 fixes https://github.com/facebook/react-native/issues/27107 Text is not selectable inside a FlatList on Android. The solution is to invalidate the ReactTextView after a change of the selectable prop. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future and make the Text selectable. ## Changelog [Android] [Fixed] - Fix non selectable Text in FlatList Pull Request resolved: https://github.com/facebook/react-native/pull/28952 Test Plan: **
CLICK TO OPEN TESTS RESULTS**

The issue was demonstrated in the following [snack](https://snack.expo.io/fabrizio.bertoglio/selectable-bug-in-flatlist) (more info in issue https://github.com/facebook/react-native/issues/26264). The solution is: 1) Calling `invalidate()` from [setSelectableText][1] after changing the `selectable` prop and `mSelectableText` value. [`invalidate()`](https://developer.android.com/reference/android/view/View#invalidate()) triggers the `onDraw` callback. [1]: https://github.com/fabriziobertoglio1987/react-native/blob/8027524947cafd5cbdc492e4ef9c92b346fe23fc/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java#L427-L430 2) calling `setTextIsSelectable(mSelectableText);` from the [`onDraw`][2] callback [2]: https://github.com/fabriziobertoglio1987/react-native/blob/8027524947cafd5cbdc492e4ef9c92b346fe23fc/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java#L456-L460 The example below is availabe in RNTester FlatList example. Two options (`onPressDisabled` and `textSelectable`) have been added to test the functionality inside a FlatList.

Reviewed By: ShikaSD Differential Revision: D30000870 Pulled By: lunaleaps fbshipit-source-id: 4851a294960df0af057d006793aa9ba97c51e3f9 --- .../react/views/text/ReactTextView.java | 8 +++++++ .../js/components/ListExampleShared.js | 4 +++- .../js/examples/FlatList/FlatListExample.js | 23 ++++++++++++++++++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index 7ce861de7b..64135eda4f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -56,6 +56,7 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie private boolean mAdjustsFontSizeToFit = false; private int mLinkifyMaskType = 0; private boolean mNotifyOnInlineViewLayout; + private boolean mTextIsSelectable = false; private ReactViewBackgroundManager mReactBackgroundManager; private Spannable mSpanned; @@ -433,9 +434,16 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie } } + @Override + public void setTextIsSelectable(boolean selectable) { + mTextIsSelectable = selectable; + super.setTextIsSelectable(selectable); + } + @Override public void onAttachedToWindow() { super.onAttachedToWindow(); + setTextIsSelectable(mTextIsSelectable); if (mContainsImages && getText() instanceof Spanned) { Spanned text = (Spanned) getText(); TextInlineImageSpan[] spans = text.getSpans(0, text.length(), TextInlineImageSpan.class); diff --git a/packages/rn-tester/js/components/ListExampleShared.js b/packages/rn-tester/js/components/ListExampleShared.js index 2312ee69c2..158590e4ad 100644 --- a/packages/rn-tester/js/components/ListExampleShared.js +++ b/packages/rn-tester/js/components/ListExampleShared.js @@ -57,13 +57,14 @@ class ItemComponent extends React.PureComponent<{ onPress: (key: string) => void, onShowUnderlay?: () => void, onHideUnderlay?: () => void, + textSelectable?: ?boolean, ... }> { _onPress = () => { this.props.onPress(this.props.item.key); }; render(): React.Node { - const {fixedHeight, horizontal, item} = this.props; + const {fixedHeight, horizontal, item, textSelectable} = this.props; const itemHash = Math.abs(hashCode(item.title)); const imgSource = THUMB_URLS[itemHash % THUMB_URLS.length]; return ( @@ -81,6 +82,7 @@ class ItemComponent extends React.PureComponent<{ {!item.noImage && } {item.title} - {item.text} diff --git a/packages/rn-tester/js/examples/FlatList/FlatListExample.js b/packages/rn-tester/js/examples/FlatList/FlatListExample.js index 4606d68090..93d7eb2de4 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatListExample.js +++ b/packages/rn-tester/js/examples/FlatList/FlatListExample.js @@ -59,6 +59,8 @@ type State = {| empty: boolean, useFlatListItemComponent: boolean, fadingEdgeLength: number, + onPressDisabled: boolean, + textSelectable: boolean, |}; class FlatListExample extends React.PureComponent { @@ -74,6 +76,8 @@ class FlatListExample extends React.PureComponent { empty: false, useFlatListItemComponent: false, fadingEdgeLength: 0, + onPressDisabled: false, + textSelectable: true, }; _onChangeFilterText = filterText => { @@ -161,6 +165,16 @@ class FlatListExample extends React.PureComponent { this.state.debug, this._setBooleanValue('debug'), )} + {renderSmallSwitchOption( + 'onPress Disabled', + this.state.onPressDisabled, + this._setBooleanValue('onPressDisabled'), + )} + {renderSmallSwitchOption( + 'Text Selectable', + this.state.textSelectable, + this._setBooleanValue('textSelectable'), + )} {renderSmallSwitchOption( 'Use FlatListItemComponent', this.state.useFlatListItemComponent, @@ -236,6 +250,12 @@ class FlatListExample extends React.PureComponent { data: state.data.concat(genItemData(100, state.data.length)), })); }; + _onPressCallback = () => { + const {onPressDisabled} = this.state; + const warning = () => console.log('onPress disabled'); + const onPressAction = onPressDisabled ? warning : this._pressItem; + return onPressAction; + }; _onRefresh = () => Alert.alert('onRefresh: nothing to refresh :P'); _renderItemComponent = () => { const flatListPropKey = this.state.useFlatListItemComponent @@ -253,9 +273,10 @@ class FlatListExample extends React.PureComponent { item={item} horizontal={this.state.horizontal} fixedHeight={this.state.fixedHeight} - onPress={this._pressItem} + onPress={this._onPressCallback()} onShowUnderlay={separators.highlight} onHideUnderlay={separators.unhighlight} + textSelectable={this.state.textSelectable} /> ); }, From 4384c32aad6a6b815504da710d19288954af190e Mon Sep 17 00:00:00 2001 From: "Aaron (Li Bo) Tao" Date: Thu, 2 Sep 2021 02:38:21 -0700 Subject: [PATCH 09/22] revert to class component of ScrollViewStickyHeader Summary: Changelog: [Internal][Changed] - revert to class component of ScrollViewStickyHeader. There is a redbox error during unmount in the functional version Reviewed By: lunaleaps Differential Revision: D30705974 fbshipit-source-id: b564c522b0026db0b334cc834a80bbbe9cd261e2 --- .../ScrollView/ScrollViewStickyHeader.js | 534 +++++++++--------- 1 file changed, 275 insertions(+), 259 deletions(-) diff --git a/Libraries/Components/ScrollView/ScrollViewStickyHeader.js b/Libraries/Components/ScrollView/ScrollViewStickyHeader.js index f530be6116..ea21ce221b 100644 --- a/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +++ b/Libraries/Components/ScrollView/ScrollViewStickyHeader.js @@ -4,25 +4,29 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow strict-local + * @flow * @format */ -import type {LayoutEvent} from '../../Types/CoreEventTypes'; -import setAndForwardRef from 'react-native/Libraries/Utilities/setAndForwardRef'; -import Platform from '../../Utilities/Platform'; -import StyleSheet from '../../StyleSheet/StyleSheet'; -import Animated from '../../Animated/Animated'; -import * as React from 'react'; -import {useEffect, useMemo, useRef, useCallback} from 'react'; +import AnimatedImplementation from '../../Animated/AnimatedImplementation'; +import AnimatedAddition from '../../Animated/nodes/AnimatedAddition'; +import AnimatedDiffClamp from '../../Animated/nodes/AnimatedDiffClamp'; +import AnimatedNode from '../../Animated/nodes/AnimatedNode'; -const AnimatedView = Animated.View; +import * as React from 'react'; +import StyleSheet from '../../StyleSheet/StyleSheet'; +import View from '../View/View'; +import Platform from '../../Utilities/Platform'; + +import type {LayoutEvent} from '../../Types/CoreEventTypes'; + +const AnimatedView = AnimatedImplementation.createAnimatedComponent(View); export type Props = $ReadOnly<{ - children?: React.Element<$FlowFixMe>, + children?: React.Element, nextHeaderLayoutY: ?number, onLayout: (event: LayoutEvent) => void, - scrollAnimatedValue: Animated.Value, + scrollAnimatedValue: AnimatedImplementation.Value, // Will cause sticky headers to stick at the bottom of the ScrollView instead // of the top. inverted: ?boolean, @@ -32,275 +36,287 @@ export type Props = $ReadOnly<{ hiddenOnScroll?: ?boolean, }>; -const ScrollViewStickyHeaderWithForwardedRef: React.AbstractComponent< - Props, - $ReadOnly<{ - setNextHeaderY: number => void, - ...$Exact>, - }>, -> = React.forwardRef(function ScrollViewStickyHeader(props, forwardedRef) { - const { - inverted, - scrollViewHeight, - hiddenOnScroll, - scrollAnimatedValue, - nextHeaderLayoutY: _nextHeaderLayoutY, - } = props; +type State = { + measured: boolean, + layoutY: number, + layoutHeight: number, + nextHeaderLayoutY: ?number, + translateY: ?number, + ... +}; - const [measured, setMeasured] = React.useState(false); - const [layoutY, setLayoutY] = React.useState(0); - const [layoutHeight, setLayoutHeight] = React.useState(0); - const [translateY, setTranslateY] = React.useState(null); - const [nextHeaderLayoutY, setNextHeaderLayoutY] = React.useState( - _nextHeaderLayoutY, - ); - const [isFabric, setIsFabric] = React.useState(false); +class ScrollViewStickyHeader extends React.Component { + state: State = { + measured: false, + layoutY: 0, + layoutHeight: 0, + nextHeaderLayoutY: this.props.nextHeaderLayoutY, + translateY: null, + }; - const componentRef = React.useRef>(); - const _setNativeRef = setAndForwardRef({ - getForwardedRef: () => forwardedRef, - setLocalRef: ref => { - componentRef.current = ref; - if (ref) { - ref.setNextHeaderY = value => { - setNextHeaderLayoutY(value); - }; - setIsFabric( - !!( - // An internal transform mangles variables with leading "_" as private. - // eslint-disable-next-line dot-notation - ref['_internalInstanceHandle']?.stateNode?.canonical - ), - ); - } - }, - }); + _translateY: ?AnimatedNode = null; + _shouldRecreateTranslateY: boolean = true; + _haveReceivedInitialZeroTranslateY: boolean = true; + _ref: any; // TODO T53738161: flow type this, and the whole file - const offset = useMemo( - () => - hiddenOnScroll === true - ? Animated.diffClamp( - scrollAnimatedValue - .interpolate({ - extrapolateLeft: 'clamp', - inputRange: [layoutY, layoutY + 1], - outputRange: ([0, 1]: Array), - }) - .interpolate({ - inputRange: [0, 1], - outputRange: ([0, -1]: Array), - }), - -layoutHeight, - 0, - ) - : null, - [scrollAnimatedValue, layoutHeight, layoutY, hiddenOnScroll], - ); + // Fabric-only: + _timer: ?TimeoutID; + _animatedValueListenerId: string; + _animatedValueListener: (valueObject: $ReadOnly<{|value: number|}>) => void; + _debounceTimeout: number = Platform.OS === 'android' ? 15 : 64; - const [ - animatedTranslateY, - setAnimatedTranslateY, - ] = React.useState(() => { - const inputRange: Array = [-1, 0]; - const outputRange: Array = [0, 0]; - const initialTranslateY: Animated.Interpolation = scrollAnimatedValue.interpolate( - { - inputRange, - outputRange, - }, - ); + setNextHeaderY: (y: number) => void = (y: number): void => { + this._shouldRecreateTranslateY = true; + this.setState({nextHeaderLayoutY: y}); + }; - if (offset != null) { - return Animated.add(initialTranslateY, offset); + componentWillUnmount() { + if (this._translateY != null && this._animatedValueListenerId != null) { + this._translateY.removeListener(this._animatedValueListenerId); } - return initialTranslateY; - }); - - const _haveReceivedInitialZeroTranslateY = useRef(true); - const _timer = useRef(null); - - useEffect(() => { - if (translateY !== 0 && translateY != null) { - _haveReceivedInitialZeroTranslateY.current = false; + if (this._timer) { + clearTimeout(this._timer); } - }, [translateY]); + } - // This is called whenever the (Interpolated) Animated Value - // updates, which is several times per frame during scrolling. - // To ensure that the Fabric ShadowTree has the most recent - // translate style of this node, we debounce the value and then - // pass it through to the underlying node during render. - // This is: - // 1. Only an issue in Fabric. - // 2. Worse in Android than iOS. In Android, but not iOS, you - // can touch and move your finger slightly and still trigger - // a "tap" event. In iOS, moving will cancel the tap in - // both Fabric and non-Fabric. On Android when you move - // your finger, the hit-detection moves from the Android - // platform to JS, so we need the ShadowTree to have knowledge - // of the current position. - const animatedValueListener = useCallback( - ({value}) => { - const _debounceTimeout: number = Platform.OS === 'android' ? 15 : 64; - // When the AnimatedInterpolation is recreated, it always initializes - // to a value of zero and emits a value change of 0 to its listeners. - if (value === 0 && !_haveReceivedInitialZeroTranslateY.current) { - _haveReceivedInitialZeroTranslateY.current = true; - return; - } - if (_timer.current != null) { - clearTimeout(_timer.current); - } - _timer.current = setTimeout(() => { - if (value !== translateY) { - setTranslateY(value); + UNSAFE_componentWillReceiveProps(nextProps: Props) { + if ( + nextProps.scrollViewHeight !== this.props.scrollViewHeight || + nextProps.scrollAnimatedValue !== this.props.scrollAnimatedValue || + nextProps.inverted !== this.props.inverted + ) { + this._shouldRecreateTranslateY = true; + } + } + + updateTranslateListener( + translateY: AnimatedImplementation.Interpolation, + isFabric: boolean, + offset: AnimatedDiffClamp | null, + ) { + if (this._translateY != null && this._animatedValueListenerId != null) { + this._translateY.removeListener(this._animatedValueListenerId); + } + offset + ? (this._translateY = new AnimatedAddition(translateY, offset)) + : (this._translateY = translateY); + + this._shouldRecreateTranslateY = false; + + if (!isFabric) { + return; + } + + if (!this._animatedValueListener) { + // This is called whenever the (Interpolated) Animated Value + // updates, which is several times per frame during scrolling. + // To ensure that the Fabric ShadowTree has the most recent + // translate style of this node, we debounce the value and then + // pass it through to the underlying node during render. + // This is: + // 1. Only an issue in Fabric. + // 2. Worse in Android than iOS. In Android, but not iOS, you + // can touch and move your finger slightly and still trigger + // a "tap" event. In iOS, moving will cancel the tap in + // both Fabric and non-Fabric. On Android when you move + // your finger, the hit-detection moves from the Android + // platform to JS, so we need the ShadowTree to have knowledge + // of the current position. + this._animatedValueListener = ({value}) => { + // When the AnimatedInterpolation is recreated, it always initializes + // to a value of zero and emits a value change of 0 to its listeners. + if (value === 0 && !this._haveReceivedInitialZeroTranslateY) { + this._haveReceivedInitialZeroTranslateY = true; + return; } - }, _debounceTimeout); - }, - [translateY], - ); - - useEffect(() => { - const inputRange: Array = [-1, 0]; - const outputRange: Array = [0, 0]; - - if (measured) { - if (inverted === true) { - // The interpolation looks like: - // - Negative scroll: no translation - // - `stickStartPoint` is the point at which the header will start sticking. - // It is calculated using the ScrollView viewport height so it is a the bottom. - // - Headers that are in the initial viewport will never stick, `stickStartPoint` - // will be negative. - // - From 0 to `stickStartPoint` no translation. This will cause the header - // to scroll normally until it reaches the top of the scroll view. - // - From `stickStartPoint` to when the next header y hits the bottom edge of the header: translate - // equally to scroll. This will cause the header to stay at the top of the scroll view. - // - Past the collision with the next header y: no more translation. This will cause the - // header to continue scrolling up and make room for the next sticky header. - // In the case that there is no next header just translate equally to - // scroll indefinitely. - if (scrollViewHeight != null) { - const stickStartPoint = layoutY + layoutHeight - scrollViewHeight; - if (stickStartPoint > 0) { - inputRange.push(stickStartPoint); - outputRange.push(0); - inputRange.push(stickStartPoint + 1); - outputRange.push(1); - // If the next sticky header has not loaded yet (probably windowing) or is the last - // we can just keep it sticked forever. - const collisionPoint = - (nextHeaderLayoutY || 0) - layoutHeight - scrollViewHeight; - if (collisionPoint > stickStartPoint) { - inputRange.push(collisionPoint, collisionPoint + 1); - outputRange.push( - collisionPoint - stickStartPoint, - collisionPoint - stickStartPoint, - ); - } + if (this._timer) { + clearTimeout(this._timer); + } + this._timer = setTimeout(() => { + if (value !== this.state.translateY) { + this.setState({ + translateY: value, + }); } - } - } else { - // The interpolation looks like: - // - Negative scroll: no translation - // - From 0 to the y of the header: no translation. This will cause the header - // to scroll normally until it reaches the top of the scroll view. - // - From header y to when the next header y hits the bottom edge of the header: translate - // equally to scroll. This will cause the header to stay at the top of the scroll view. - // - Past the collision with the next header y: no more translation. This will cause the - // header to continue scrolling up and make room for the next sticky header. - // In the case that there is no next header just translate equally to - // scroll indefinitely. - inputRange.push(layoutY); - outputRange.push(0); - // If the next sticky header has not loaded yet (probably windowing) or is the last - // we can just keep it sticked forever. - const collisionPoint = (nextHeaderLayoutY || 0) - layoutHeight; - if (collisionPoint >= layoutY) { - inputRange.push(collisionPoint, collisionPoint + 1); - outputRange.push(collisionPoint - layoutY, collisionPoint - layoutY); - } else { - inputRange.push(layoutY + 1); - outputRange.push(1); - } - } + }, this._debounceTimeout); + }; + } + if (this.state.translateY !== 0 && this.state.translateY != null) { + this._haveReceivedInitialZeroTranslateY = false; + } + this._animatedValueListenerId = translateY.addListener( + this._animatedValueListener, + ); + } + + _onLayout = event => { + const layoutY = event.nativeEvent.layout.y; + const layoutHeight = event.nativeEvent.layout.height; + const measured = true; + + if ( + layoutY !== this.state.layoutY || + layoutHeight !== this.state.layoutHeight || + measured !== this.state.measured + ) { + this._shouldRecreateTranslateY = true; } - let newAnimatedTranslateY: Animated.Node = scrollAnimatedValue.interpolate({ - inputRange, - outputRange, + this.setState({ + measured, + layoutY, + layoutHeight, }); - if (offset != null) { - newAnimatedTranslateY = Animated.add(newAnimatedTranslateY, offset); - } - - // add the event listener - let animatedListenerId; - if (isFabric) { - animatedListenerId = newAnimatedTranslateY.addListener( - animatedValueListener, - ); - } - - setAnimatedTranslateY(newAnimatedTranslateY); - - // clean up the event listener and timer - return () => { - if (animatedListenerId) { - newAnimatedTranslateY.removeListener(animatedListenerId); - } - if (_timer.current != null) { - clearTimeout(_timer.current); - } - }; - }, [nextHeaderLayoutY, measured, layoutHeight, layoutY, scrollViewHeight, scrollAnimatedValue, inverted, offset, animatedValueListener, isFabric]); - - const _onLayout = (event: LayoutEvent) => { - setLayoutY(event.nativeEvent.layout.y); - setLayoutHeight(event.nativeEvent.layout.height); - setMeasured(true); - - props.onLayout(event); - const child = React.Children.only(props.children); + this.props.onLayout(event); + const child = React.Children.only(this.props.children); if (child.props.onLayout) { child.props.onLayout(event); } }; - const child = React.Children.only(props.children); + _setComponentRef = ref => { + this._ref = ref; + }; - // TODO T68319535: remove this if NativeAnimated is rewritten for Fabric - const passthroughAnimatedPropExplicitValues = - isFabric && translateY != null - ? { - style: {transform: [{translateY: translateY}]}, + render(): React.Node { + // Fabric Detection + const isFabric = !!( + // An internal transform mangles variables with leading "_" as private. + // eslint-disable-next-line dot-notation + (this._ref && this._ref['_internalInstanceHandle']?.stateNode?.canonical) + ); + // Initially and in the case of updated props or layout, we + // recreate this interpolated value. Otherwise, we do not recreate + // when there are state changes. + if (this._shouldRecreateTranslateY) { + const {inverted, scrollViewHeight} = this.props; + const {measured, layoutHeight, layoutY, nextHeaderLayoutY} = this.state; + const inputRange: Array = [-1, 0]; + const outputRange: Array = [0, 0]; + + if (measured) { + if (inverted) { + // The interpolation looks like: + // - Negative scroll: no translation + // - `stickStartPoint` is the point at which the header will start sticking. + // It is calculated using the ScrollView viewport height so it is a the bottom. + // - Headers that are in the initial viewport will never stick, `stickStartPoint` + // will be negative. + // - From 0 to `stickStartPoint` no translation. This will cause the header + // to scroll normally until it reaches the top of the scroll view. + // - From `stickStartPoint` to when the next header y hits the bottom edge of the header: translate + // equally to scroll. This will cause the header to stay at the top of the scroll view. + // - Past the collision with the next header y: no more translation. This will cause the + // header to continue scrolling up and make room for the next sticky header. + // In the case that there is no next header just translate equally to + // scroll indefinitely. + if (scrollViewHeight != null) { + const stickStartPoint = layoutY + layoutHeight - scrollViewHeight; + if (stickStartPoint > 0) { + inputRange.push(stickStartPoint); + outputRange.push(0); + inputRange.push(stickStartPoint + 1); + outputRange.push(1); + // If the next sticky header has not loaded yet (probably windowing) or is the last + // we can just keep it sticked forever. + const collisionPoint = + (nextHeaderLayoutY || 0) - layoutHeight - scrollViewHeight; + if (collisionPoint > stickStartPoint) { + inputRange.push(collisionPoint, collisionPoint + 1); + outputRange.push( + collisionPoint - stickStartPoint, + collisionPoint - stickStartPoint, + ); + } + } + } + } else { + // The interpolation looks like: + // - Negative scroll: no translation + // - From 0 to the y of the header: no translation. This will cause the header + // to scroll normally until it reaches the top of the scroll view. + // - From header y to when the next header y hits the bottom edge of the header: translate + // equally to scroll. This will cause the header to stay at the top of the scroll view. + // - Past the collision with the next header y: no more translation. This will cause the + // header to continue scrolling up and make room for the next sticky header. + // In the case that there is no next header just translate equally to + // scroll indefinitely. + inputRange.push(layoutY); + outputRange.push(0); + // If the next sticky header has not loaded yet (probably windowing) or is the last + // we can just keep it sticked forever. + const collisionPoint = (nextHeaderLayoutY || 0) - layoutHeight; + if (collisionPoint >= layoutY) { + inputRange.push(collisionPoint, collisionPoint + 1); + outputRange.push( + collisionPoint - layoutY, + collisionPoint - layoutY, + ); + } else { + inputRange.push(layoutY + 1); + outputRange.push(1); + } } - : null; + } - return ( - /* $FlowFixMe[prop-missing] passthroughAnimatedPropExplicitValues isn't properly - included in the Animated.View flow type. */ - - {React.cloneElement(child, { - style: styles.fill, // We transfer the child style to the wrapper. - onLayout: undefined, // we call this manually through our this._onLayout - })} - - ); -}); + this.updateTranslateListener( + this.props.scrollAnimatedValue.interpolate({ + inputRange, + outputRange, + }), + isFabric, + this.props.hiddenOnScroll + ? new AnimatedDiffClamp( + this.props.scrollAnimatedValue + .interpolate({ + extrapolateLeft: 'clamp', + inputRange: [layoutY, layoutY + 1], + outputRange: ([0, 1]: Array), + }) + .interpolate({ + inputRange: [0, 1], + outputRange: ([0, -1]: Array), + }), + -this.state.layoutHeight, + 0, + ) + : null, + ); + } + + const child = React.Children.only(this.props.children); + + // TODO T68319535: remove this if NativeAnimated is rewritten for Fabric + const passthroughAnimatedPropExplicitValues = + isFabric && this.state.translateY != null + ? { + style: {transform: [{translateY: this.state.translateY}]}, + } + : null; + + return ( + + {React.cloneElement(child, { + style: styles.fill, // We transfer the child style to the wrapper. + onLayout: undefined, // we call this manually through our this._onLayout + })} + + ); + } +} const styles = StyleSheet.create({ header: { @@ -312,4 +328,4 @@ const styles = StyleSheet.create({ }, }); -export default ScrollViewStickyHeaderWithForwardedRef; +module.exports = ScrollViewStickyHeader; From 6a2b6c2f3ef63cf0ff733daf75005ee32eebdd00 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Thu, 2 Sep 2021 04:30:01 -0700 Subject: [PATCH 10/22] Bump Kotlin to 1.4.32 (#32137) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/32137 Bumping the minor version of Kotlin. I don't expect any major breakage. Changelog: [Android] [Changed] - Bumped Kotlin to 1.4.32 Reviewed By: ShikaSD Differential Revision: D30698315 fbshipit-source-id: e1de6251c1c17c490700298540dea5b48d034e3c --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e785ec12c9..223dcfb79c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,4 +6,4 @@ org.gradle.parallel=true ANDROID_NDK_VERSION=21.4.7075529 android.useAndroidX=true -kotlin_version=1.4.21 +kotlin_version=1.4.32 From b1120c6a6513ec24568abc6bbe60dd57ef1dec96 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Thu, 2 Sep 2021 04:30:01 -0700 Subject: [PATCH 11/22] Bump Gradle to 7.1.1 (#32138) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/32138 This is a follow up to the Gradle bump: D30486612 (https://github.com/facebook/react-native/commit/85249cafe8870ab8f47c38569b106555ce2f8527) Changelog: [Android] [Changed] - Bumped Gradle to 7.1.1 Reviewed By: ShikaSD Differential Revision: D30698411 fbshipit-source-id: ae51499c36380dca6763abeaf04ab3d6ca37456d --- gradle/wrapper/gradle-wrapper.properties | 2 +- .../android/gradle/wrapper/gradle-wrapper.properties | 2 +- template/android/gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 29e4134576..af7be50b10 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/react-native-codegen/android/gradle/wrapper/gradle-wrapper.properties b/packages/react-native-codegen/android/gradle/wrapper/gradle-wrapper.properties index 29e4134576..af7be50b10 100644 --- a/packages/react-native-codegen/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/react-native-codegen/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/template/android/gradle/wrapper/gradle-wrapper.properties b/template/android/gradle/wrapper/gradle-wrapper.properties index 29e4134576..af7be50b10 100644 --- a/template/android/gradle/wrapper/gradle-wrapper.properties +++ b/template/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 99f3a6a56e04a73744dfff004613307d6b5aa8d0 Mon Sep 17 00:00:00 2001 From: Pieter Vanderwerff Date: Thu, 2 Sep 2021 11:38:52 -0700 Subject: [PATCH 12/22] Deploy 0.159.0 to xplat Summary: Changelog: [Internal] Reviewed By: mroch Differential Revision: D30712727 fbshipit-source-id: 21db45b834cf902619743871e7f076fceff46053 --- .flowconfig | 2 +- .flowconfig.android | 2 +- package.json | 2 +- repo-config/package.json | 2 +- template/_flowconfig | 2 +- yarn.lock | 8 ++++---- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.flowconfig b/.flowconfig index c7aa3f075c..e6ad16c7bc 100644 --- a/.flowconfig +++ b/.flowconfig @@ -71,4 +71,4 @@ untyped-import untyped-type-import [version] -^0.158.0 +^0.159.0 diff --git a/.flowconfig.android b/.flowconfig.android index 96b2747763..53110b81ff 100644 --- a/.flowconfig.android +++ b/.flowconfig.android @@ -71,4 +71,4 @@ untyped-import untyped-type-import [version] -^0.158.0 +^0.159.0 diff --git a/package.json b/package.json index f8d1e77291..5c651a3d53 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,7 @@ "ws": "^6.1.4" }, "devDependencies": { - "flow-bin": "^0.158.0", + "flow-bin": "^0.159.0", "react": "17.0.2" }, "detox": { diff --git a/repo-config/package.json b/repo-config/package.json index bc6712214e..c09bf529a5 100644 --- a/repo-config/package.json +++ b/repo-config/package.json @@ -36,7 +36,7 @@ "eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-react-native": "3.10.0", "eslint-plugin-relay": "1.8.1", - "flow-bin": "^0.158.0", + "flow-bin": "^0.159.0", "jest": "^26.6.3", "jest-junit": "^10.0.0", "jscodeshift": "^0.11.0", diff --git a/template/_flowconfig b/template/_flowconfig index 4320b7070e..cb5247b72a 100644 --- a/template/_flowconfig +++ b/template/_flowconfig @@ -62,4 +62,4 @@ untyped-import untyped-type-import [version] -^0.158.0 +^0.159.0 diff --git a/yarn.lock b/yarn.lock index c19efec0b0..5f5e62cfb9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3028,10 +3028,10 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== -flow-bin@^0.158.0: - version "0.158.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.158.0.tgz#0a09763d41eb8ec7135ced6a3b9f8fa370a393d8" - integrity sha512-Gk5md8XTwk/M+J5M+rFyS1LJfFen6ldY60jM9+meWixlKf4b0vwdoUO8R7oo471pze+GY+blrnskUeqLDxFJfg== +flow-bin@^0.159.0: + version "0.159.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.159.0.tgz#f788480d54db6da021e3440648c1dbb5dbc8aee8" + integrity sha512-5SugX7mOdfruzn2/+42DF74bxJO2SGmSEzCvTH9wOoBi98Ie87D5Hmb9OoGfwAE5SnXJmB6OCwN2WDiJe4lI+w== flow-parser@0.*, flow-parser@^0.121.0: version "0.121.0" From c13eb781fec49ada04ba3a2d691a029842785e3c Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Thu, 2 Sep 2021 12:02:44 -0700 Subject: [PATCH 13/22] Exclude OpenSSL-Universal flipper dependency from release builds (#31938) Summary: Use the same technique as other flipper transitive deps to make sure it is excluded from release builds. ## Changelog [iOS][Fixed] - Exclude OpenSSL-Universal flipper dependency from release builds Pull Request resolved: https://github.com/facebook/react-native/pull/31938 Test Plan: Tested in an app that it still builds and works. Reviewed By: mweststrate Differential Revision: D30674216 Pulled By: yungsters fbshipit-source-id: f2ab5154c80036e6df90d1a98882cc4b85734485 --- scripts/react_native_pods.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index 2325ad33c5..dd3d60ca25 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -79,6 +79,7 @@ def use_flipper!(versions = {}, configurations: ['Debug']) versions['Flipper-Glog'] ||= '0.3.6' versions['Flipper-PeerTalk'] ||= '0.0.4' versions['Flipper-RSocket'] ||= '1.4.3' + versions['OpenSSL-Universal'] ||= '1.1.180' pod 'FlipperKit', versions['Flipper'], :configurations => configurations pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configurations => configurations pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configurations => configurations @@ -102,6 +103,7 @@ def use_flipper!(versions = {}, configurations: ['Debug']) pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configurations => configurations pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configurations => configurations pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configurations => configurations + pod 'OpenSSL-Universal', versions['OpenSSL-Universal'], :configurations => configurations end def has_pod(installer, name) From a40f973f58609ca717fac63bc501d5cf93b748ad Mon Sep 17 00:00:00 2001 From: Ashoat Tevosyan Date: Thu, 2 Sep 2021 12:15:04 -0700 Subject: [PATCH 14/22] Remove custom Hermes config for Android (#31900) Summary: Right now, `react-native` on Android passes in an explicit Hermes config when initializes Hermes. The upcoming version of Hermes shipping with React Native 0.66 will handle this default config itself, so there's no need to override it from Android anymore. Changelog: [Android][Changed] - Hermes initialization will no longer need an explicit configuration. Pull Request resolved: https://github.com/facebook/react-native/pull/31900 Test Plan: I compiled and ran a React Native app using the Android build, making sure to build `ReactAndroid` from source. I confirmed that the config was actually being applied by testing how much memory an application could eat before being killed. Reviewed By: sshic Differential Revision: D30675510 Pulled By: yungsters fbshipit-source-id: 5eef056893b72ddd433ee808eb08d0eb56f22f72 --- .../com/facebook/hermes/reactexecutor/BUCK | 16 -------- .../hermes/reactexecutor/HermesExecutor.java | 9 ++--- .../reactexecutor/HermesExecutorFactory.java | 12 +----- .../facebook/hermes/reactexecutor/OnLoad.cpp | 40 +------------------ .../hermes/reactexecutor/RuntimeConfig.java | 19 --------- 5 files changed, 5 insertions(+), 91 deletions(-) delete mode 100644 ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK index fca40c1027..f305aa4fe0 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK @@ -17,22 +17,6 @@ rn_android_library( react_native_target("java/com/facebook/hermes/instrumentation:hermes_samplingprofiler"), react_native_target("java/com/facebook/react/bridge:bridge"), ":jni", - ":runtimeconfig", - ], -) - -rn_android_library( - name = "runtimeconfig", - srcs = [ - "RuntimeConfig.java", - ], - autoglob = False, - visibility = [ - "PUBLIC", - ], - deps = [ - react_native_dep("third-party/java/jsr-305:jsr-305"), - react_native_target("java/com/facebook/hermes/instrumentation:instrumentation"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java index 7519f2146f..cdee2c9ef8 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java @@ -10,7 +10,6 @@ package com.facebook.hermes.reactexecutor; import com.facebook.jni.HybridData; import com.facebook.react.bridge.JavaScriptExecutor; import com.facebook.soloader.SoLoader; -import javax.annotation.Nullable; public class HermesExecutor extends JavaScriptExecutor { private static String mode_; @@ -27,8 +26,8 @@ public class HermesExecutor extends JavaScriptExecutor { } } - HermesExecutor(@Nullable RuntimeConfig config) { - super(config == null ? initHybridDefaultConfig() : initHybrid(config.heapSizeMB)); + HermesExecutor() { + super(initHybrid()); } @Override @@ -45,7 +44,5 @@ public class HermesExecutor extends JavaScriptExecutor { */ public static native boolean canLoadFile(String path); - private static native HybridData initHybridDefaultConfig(); - - private static native HybridData initHybrid(long heapSizeMB); + private static native HybridData initHybrid(); } diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java index 976af80b1e..a2686dba3a 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java @@ -14,19 +14,9 @@ import com.facebook.react.bridge.JavaScriptExecutorFactory; public class HermesExecutorFactory implements JavaScriptExecutorFactory { private static final String TAG = "Hermes"; - private final RuntimeConfig mConfig; - - public HermesExecutorFactory() { - this(new RuntimeConfig(1024)); - } - - public HermesExecutorFactory(RuntimeConfig config) { - mConfig = config; - } - @Override public JavaScriptExecutor create() { - return new HermesExecutor(mConfig); + return new HermesExecutor(); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp index 56a9f58949..f02a1b1906 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp @@ -10,8 +10,6 @@ #include #include #include -#include -#include #include #include #include @@ -30,26 +28,6 @@ static void hermesFatalHandler(const std::string &reason) { static std::once_flag flag; -static ::hermes::vm::RuntimeConfig makeRuntimeConfig(jlong heapSizeMB) { - namespace vm = ::hermes::vm; - auto gcConfigBuilder = - vm::GCConfig::Builder() - .withName("RN") - // For the next two arguments: avoid GC before TTI by initializing the - // runtime to allocate directly in the old generation, but revert to - // normal operation when we reach the (first) TTI point. - .withAllocInYoung(false) - .withRevertToYGAtTTI(true); - - if (heapSizeMB > 0) { - gcConfigBuilder.withMaxHeapSize(heapSizeMB << 20); - } - - return vm::RuntimeConfig::Builder() - .withGCConfig(gcConfigBuilder.build()) - .build(); -} - static void installBindings(jsi::Runtime &runtime) { react::Logger androidLogger = static_cast( @@ -67,8 +45,7 @@ class HermesExecutorHolder static constexpr auto kJavaDescriptor = "Lcom/facebook/hermes/reactexecutor/HermesExecutor;"; - static jni::local_ref initHybridDefaultConfig( - jni::alias_ref) { + static jni::local_ref initHybrid(jni::alias_ref) { JReactMarker::setLogPerfMarkerIfNeeded(); std::call_once(flag, []() { @@ -78,18 +55,6 @@ class HermesExecutorHolder std::make_unique(installBindings)); } - static jni::local_ref initHybrid( - jni::alias_ref, - jlong heapSizeMB) { - JReactMarker::setLogPerfMarkerIfNeeded(); - auto runtimeConfig = makeRuntimeConfig(heapSizeMB); - std::call_once(flag, []() { - facebook::hermes::HermesRuntime::setFatalHandler(hermesFatalHandler); - }); - return makeCxxInstance(std::make_unique( - installBindings, JSIExecutor::defaultTimeoutInvoker, runtimeConfig)); - } - static bool canLoadFile(jni::alias_ref, const std::string &path) { return true; } @@ -97,9 +62,6 @@ class HermesExecutorHolder static void registerNatives() { registerHybrid( {makeNativeMethod("initHybrid", HermesExecutorHolder::initHybrid), - makeNativeMethod( - "initHybridDefaultConfig", - HermesExecutorHolder::initHybridDefaultConfig), makeNativeMethod("canLoadFile", HermesExecutorHolder::canLoadFile)}); } diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java deleted file mode 100644 index fec7c457bc..0000000000 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.hermes.reactexecutor; - -/** Holds runtime configuration for a Hermes VM instance (master or snapshot). */ -public final class RuntimeConfig { - public long heapSizeMB; - - RuntimeConfig() {} - - RuntimeConfig(long heapSizeMB) { - this.heapSizeMB = heapSizeMB; - } -} From 7edf9274cf6d3398075c19cd1cb020a5d6a346a2 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Thu, 2 Sep 2021 12:36:17 -0700 Subject: [PATCH 15/22] Fix keyboardDismissMode="on-drag" on Android (#31943) Summary: Fixes https://github.com/facebook/react-native/issues/23364 The current logic using `_isTouching` does not work because `_handleTouchCancel` is always called before scroll events begin. This means `_isTouching` is always false. To fix it I moved the logic to `_handleScrollBeginDrag` which is only called once when scroll drag beings. This accomplishes the expected behavior and is better than keeping it in onScroll where it would be called for each scroll event. ## Changelog [Android] [Fixed] - Fix keyboardDismissMode="on-drag" on Android Pull Request resolved: https://github.com/facebook/react-native/pull/31943 Test Plan: Tested in an app that on-drag does not work before and works after this patch. Reviewed By: sshic Differential Revision: D30674276 Pulled By: yungsters fbshipit-source-id: aa0bd605809fa01518f70fbf323c06e32c76ed1d --- Libraries/Components/ScrollView/ScrollView.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index e497288b1b..696781ffbe 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -1178,11 +1178,6 @@ class ScrollView extends React.Component { ); } } - if (Platform.OS === 'android') { - if (this.props.keyboardDismissMode === 'on-drag' && this._isTouching) { - dismissKeyboard(); - } - } this._observedScrollSinceBecomingResponder = true; this.props.onScroll && this.props.onScroll(e); }; @@ -1299,6 +1294,14 @@ class ScrollView extends React.Component { */ _handleScrollBeginDrag: (e: ScrollEvent) => void = (e: ScrollEvent) => { FrameRateLogger.beginScroll(); // TODO: track all scrolls after implementing onScrollEndAnimation + + if ( + Platform.OS === 'android' && + this.props.keyboardDismissMode === 'on-drag' + ) { + dismissKeyboard(); + } + this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e); }; From 455433f481bf5f743a3330a9a46edda5fc69da69 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Thu, 2 Sep 2021 13:17:53 -0700 Subject: [PATCH 16/22] Revert D30675510: Remove custom Hermes config for Android Differential Revision: D30675510 (https://github.com/facebook/react-native/commit/a40f973f58609ca717fac63bc501d5cf93b748ad) Original commit changeset: 5eef056893b7 fbshipit-source-id: 25db31c4fbe938d92bba8b0bfe6523bced1524f0 --- .../com/facebook/hermes/reactexecutor/BUCK | 16 ++++++++ .../hermes/reactexecutor/HermesExecutor.java | 9 +++-- .../reactexecutor/HermesExecutorFactory.java | 12 +++++- .../facebook/hermes/reactexecutor/OnLoad.cpp | 40 ++++++++++++++++++- .../hermes/reactexecutor/RuntimeConfig.java | 19 +++++++++ 5 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK index f305aa4fe0..fca40c1027 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK @@ -17,6 +17,22 @@ rn_android_library( react_native_target("java/com/facebook/hermes/instrumentation:hermes_samplingprofiler"), react_native_target("java/com/facebook/react/bridge:bridge"), ":jni", + ":runtimeconfig", + ], +) + +rn_android_library( + name = "runtimeconfig", + srcs = [ + "RuntimeConfig.java", + ], + autoglob = False, + visibility = [ + "PUBLIC", + ], + deps = [ + react_native_dep("third-party/java/jsr-305:jsr-305"), + react_native_target("java/com/facebook/hermes/instrumentation:instrumentation"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java index cdee2c9ef8..7519f2146f 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java @@ -10,6 +10,7 @@ package com.facebook.hermes.reactexecutor; import com.facebook.jni.HybridData; import com.facebook.react.bridge.JavaScriptExecutor; import com.facebook.soloader.SoLoader; +import javax.annotation.Nullable; public class HermesExecutor extends JavaScriptExecutor { private static String mode_; @@ -26,8 +27,8 @@ public class HermesExecutor extends JavaScriptExecutor { } } - HermesExecutor() { - super(initHybrid()); + HermesExecutor(@Nullable RuntimeConfig config) { + super(config == null ? initHybridDefaultConfig() : initHybrid(config.heapSizeMB)); } @Override @@ -44,5 +45,7 @@ public class HermesExecutor extends JavaScriptExecutor { */ public static native boolean canLoadFile(String path); - private static native HybridData initHybrid(); + private static native HybridData initHybridDefaultConfig(); + + private static native HybridData initHybrid(long heapSizeMB); } diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java index a2686dba3a..976af80b1e 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java @@ -14,9 +14,19 @@ import com.facebook.react.bridge.JavaScriptExecutorFactory; public class HermesExecutorFactory implements JavaScriptExecutorFactory { private static final String TAG = "Hermes"; + private final RuntimeConfig mConfig; + + public HermesExecutorFactory() { + this(new RuntimeConfig(1024)); + } + + public HermesExecutorFactory(RuntimeConfig config) { + mConfig = config; + } + @Override public JavaScriptExecutor create() { - return new HermesExecutor(); + return new HermesExecutor(mConfig); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp index f02a1b1906..56a9f58949 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -28,6 +30,26 @@ static void hermesFatalHandler(const std::string &reason) { static std::once_flag flag; +static ::hermes::vm::RuntimeConfig makeRuntimeConfig(jlong heapSizeMB) { + namespace vm = ::hermes::vm; + auto gcConfigBuilder = + vm::GCConfig::Builder() + .withName("RN") + // For the next two arguments: avoid GC before TTI by initializing the + // runtime to allocate directly in the old generation, but revert to + // normal operation when we reach the (first) TTI point. + .withAllocInYoung(false) + .withRevertToYGAtTTI(true); + + if (heapSizeMB > 0) { + gcConfigBuilder.withMaxHeapSize(heapSizeMB << 20); + } + + return vm::RuntimeConfig::Builder() + .withGCConfig(gcConfigBuilder.build()) + .build(); +} + static void installBindings(jsi::Runtime &runtime) { react::Logger androidLogger = static_cast( @@ -45,7 +67,8 @@ class HermesExecutorHolder static constexpr auto kJavaDescriptor = "Lcom/facebook/hermes/reactexecutor/HermesExecutor;"; - static jni::local_ref initHybrid(jni::alias_ref) { + static jni::local_ref initHybridDefaultConfig( + jni::alias_ref) { JReactMarker::setLogPerfMarkerIfNeeded(); std::call_once(flag, []() { @@ -55,6 +78,18 @@ class HermesExecutorHolder std::make_unique(installBindings)); } + static jni::local_ref initHybrid( + jni::alias_ref, + jlong heapSizeMB) { + JReactMarker::setLogPerfMarkerIfNeeded(); + auto runtimeConfig = makeRuntimeConfig(heapSizeMB); + std::call_once(flag, []() { + facebook::hermes::HermesRuntime::setFatalHandler(hermesFatalHandler); + }); + return makeCxxInstance(std::make_unique( + installBindings, JSIExecutor::defaultTimeoutInvoker, runtimeConfig)); + } + static bool canLoadFile(jni::alias_ref, const std::string &path) { return true; } @@ -62,6 +97,9 @@ class HermesExecutorHolder static void registerNatives() { registerHybrid( {makeNativeMethod("initHybrid", HermesExecutorHolder::initHybrid), + makeNativeMethod( + "initHybridDefaultConfig", + HermesExecutorHolder::initHybridDefaultConfig), makeNativeMethod("canLoadFile", HermesExecutorHolder::canLoadFile)}); } diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java new file mode 100644 index 0000000000..fec7c457bc --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.hermes.reactexecutor; + +/** Holds runtime configuration for a Hermes VM instance (master or snapshot). */ +public final class RuntimeConfig { + public long heapSizeMB; + + RuntimeConfig() {} + + RuntimeConfig(long heapSizeMB) { + this.heapSizeMB = heapSizeMB; + } +} From a909ba20db84480c3ac699f0689d5757509b1668 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 2 Sep 2021 16:48:53 -0700 Subject: [PATCH 17/22] Remove !RCTRootView.bridge check from FBReactRootViewController Summary: Users of RCTRootView access the bridge from it, to see if it's nil or not. ## Changes - Instead of exposing the bridge from RCTRootView for this use-case, we're now exposing a property on RCTRootView: hasBridge. This will be false in bridgeless mode, and true in bridge mode. ## Benefits This takes us one step closer towards removing RCTBridge leakage through RCTRootView. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D30434885 fbshipit-source-id: 02f50e16831852b5049a626e8b08d59a90b2059a --- React/Base/RCTRootView.h | 5 +++++ React/Base/RCTRootView.m | 5 +++++ .../SurfaceHostingView/RCTSurfaceHostingProxyRootView.h | 1 + .../SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm | 5 +++++ 4 files changed, 16 insertions(+) diff --git a/React/Base/RCTRootView.h b/React/Base/RCTRootView.h index f555e234c7..5074c54bda 100644 --- a/React/Base/RCTRootView.h +++ b/React/Base/RCTRootView.h @@ -75,6 +75,11 @@ extern initialProperties:(nullable NSDictionary *)initialProperties launchOptions:(nullable NSDictionary *)launchOptions; +/** + * This API allows RCTRootView users to know if the root view is backed by the bridge. + */ +@property (nonatomic, readonly) BOOL hasBridge; + /** * The name of the JavaScript module to execute within the * specified scriptURL (required). Setting this will not have diff --git a/React/Base/RCTRootView.m b/React/Base/RCTRootView.m index 7e8a3804d1..c5c5881739 100644 --- a/React/Base/RCTRootView.m +++ b/React/Base/RCTRootView.m @@ -116,6 +116,11 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame) RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder) +- (BOOL)hasBridge +{ + return _bridge != nil; +} + #pragma mark - passThroughTouches - (BOOL)passThroughTouches diff --git a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h index 8e34cd7583..3d90371965 100644 --- a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h +++ b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h @@ -26,6 +26,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy, readonly) NSString *moduleName; @property (nonatomic, strong, readonly) RCTBridge *bridge; +@property (nonatomic, readonly) BOOL hasBridge; @property (nonatomic, copy, readwrite) NSDictionary *appProperties; @property (nonatomic, assign) RCTRootViewSizeFlexibility sizeFlexibility; @property (nonatomic, weak) id delegate; diff --git a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm index 50f4e745fb..2f69e6d493 100644 --- a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm +++ b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm @@ -93,6 +93,11 @@ static RCTRootViewSizeFlexibility convertToRootViewSizeFlexibility(RCTSurfaceSiz return [self initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties]; } +- (BOOL)hasBridge +{ + return _bridge != nil; +} + RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame) RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder) From bfead74e69f69fac6ae87110737e8935d293922e Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 2 Sep 2021 16:48:53 -0700 Subject: [PATCH 18/22] Allow RCTRootView users to require NativeModules without the bridge Summary: RCTRootVeiw exports the bridge. One reason why is to allow users of RCTRootView users to access NativeModules. ## Changes - RCTBridge now exports the RCTModuleRegistry - RCTRootView now exports the RCTModuleRegistry exported by the bridge - Users of RCTRootView use the RCTModuleRegistry exported by RCTRootView to access NativeModules ## Benefits Down the line, we'll change how RCTRootView gets the RCTModuleRegistry (i.e: it won't use the bridge in bridgeless mode). Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D30434886 fbshipit-source-id: 875fce24d2fd9ee6350f128c8612e613e61e390e --- React/Base/RCTBridge+Private.h | 8 ++++++++ React/Base/RCTBridge.m | 5 +++++ React/Base/RCTRootView.h | 8 ++++++++ React/Base/RCTRootView.m | 5 +++++ .../SurfaceHostingView/RCTSurfaceHostingProxyRootView.h | 1 + .../SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm | 6 ++++++ React/CxxBridge/RCTCxxBridge.mm | 5 +++++ 7 files changed, 38 insertions(+) diff --git a/React/Base/RCTBridge+Private.h b/React/Base/RCTBridge+Private.h index 70a20f0b00..9dd96a5cd1 100644 --- a/React/Base/RCTBridge+Private.h +++ b/React/Base/RCTBridge+Private.h @@ -7,6 +7,7 @@ #import +@class RCTModuleRegistry; @class RCTModuleData; @protocol RCTJavaScriptExecutor; @@ -62,6 +63,13 @@ RCT_EXTERN void RCTRegisterModule(Class); */ @property (nonatomic, strong, readwrite) NSURL *bundleURL; +/** + * An object that allows one to require NativeModules/TurboModules. + * RCTModuleRegistry is implemented in bridgeless mode and bridge mode. + * Used by RCTRootView. + */ +@property (nonatomic, strong, readonly) RCTModuleRegistry *moduleRegistry; + @end @interface RCTBridge (RCTCxxBridge) diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index 850c78c135..10503261d7 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -257,6 +257,11 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init) }); } +- (RCTModuleRegistry *)moduleRegistry +{ + return self.batchedBridge.moduleRegistry; +} + - (NSArray *)moduleClasses { return self.batchedBridge.moduleClasses; diff --git a/React/Base/RCTRootView.h b/React/Base/RCTRootView.h index 5074c54bda..27eec8bf3d 100644 --- a/React/Base/RCTRootView.h +++ b/React/Base/RCTRootView.h @@ -8,6 +8,8 @@ #import #import +#import +#import @protocol RCTRootViewDelegate; @@ -80,6 +82,12 @@ extern */ @property (nonatomic, readonly) BOOL hasBridge; +/** + * This API allows users of RCTRootView to access other NativeModules, without + * directly accessing the bridge. + */ +@property (nonatomic, strong, readonly) RCTModuleRegistry *moduleRegistry; + /** * The name of the JavaScript module to execute within the * specified scriptURL (required). Setting this will not have diff --git a/React/Base/RCTRootView.m b/React/Base/RCTRootView.m index c5c5881739..a8a8c2ccfa 100644 --- a/React/Base/RCTRootView.m +++ b/React/Base/RCTRootView.m @@ -121,6 +121,11 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder) return _bridge != nil; } +- (RCTModuleRegistry *)moduleRegistry +{ + return _bridge.moduleRegistry; +} + #pragma mark - passThroughTouches - (BOOL)passThroughTouches diff --git a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h index 3d90371965..110b6e4f23 100644 --- a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h +++ b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h @@ -27,6 +27,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy, readonly) NSString *moduleName; @property (nonatomic, strong, readonly) RCTBridge *bridge; @property (nonatomic, readonly) BOOL hasBridge; +@property (nonatomic, strong, readonly) RCTModuleRegistry *moduleRegistry; @property (nonatomic, copy, readwrite) NSDictionary *appProperties; @property (nonatomic, assign) RCTRootViewSizeFlexibility sizeFlexibility; @property (nonatomic, weak) id delegate; diff --git a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm index 2f69e6d493..6ca24ae80b 100644 --- a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm +++ b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm @@ -10,6 +10,7 @@ #import #import "RCTAssert.h" +#import "RCTBridge+Private.h" #import "RCTBridge.h" #import "RCTLog.h" #import "RCTPerformanceLogger.h" @@ -98,6 +99,11 @@ static RCTRootViewSizeFlexibility convertToRootViewSizeFlexibility(RCTSurfaceSiz return _bridge != nil; } +- (RCTModuleRegistry *)moduleRegistry +{ + return _bridge.moduleRegistry; +} + RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame) RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder) diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index 0f1a601f4a..a33b656d9c 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -244,6 +244,11 @@ struct RCTInstanceCallback : public InstanceCallback { @synthesize performanceLogger = _performanceLogger; @synthesize valid = _valid; +- (RCTModuleRegistry *)moduleRegistry +{ + return _objCModuleRegistry; +} + - (void)setRCTTurboModuleRegistry:(id)turboModuleRegistry { _turboModuleRegistry = turboModuleRegistry; From 9f69c922cbfcd08bbdfa16c36bd57153d77b9b1b Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 2 Sep 2021 16:48:53 -0700 Subject: [PATCH 19/22] Remove RCTRootView.bridge usage from RCTBaseViewController Summary: RCTBaseViewController uses RCTRootView.bridge to call RCTViewEventEmitter.emit. ## Changes - RCTEventDispatcher now exposes a method to dispatch RCTViewEventEmitter events. - RCTRootView (for paper), and RCTSurfaceHostingProxyRootView (for fabric and bridgeless mode) now exports the RCTEventDispatcher by grabbing it from the bridge - RCTBaseViewController now uses the event dispatcher exported from RCTRootView to dispatch the RCTViewEventEmitter event. ## Benefits - RCTBaseViewController no longer uses the bridge to dispatch RCTViewEventEmitter events - In the future, we'll make RCTSurfaceHostingProxyRootView work with bridgeless mode, which'll allow us to remove the bridge/bridgeless fork in RCTBaseViewController. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D30434884 fbshipit-source-id: d961a56ac2abc08a661f8fe7c37926f219b731d0 --- React/Base/RCTEventDispatcherProtocol.h | 2 ++ React/Base/RCTRootView.h | 2 ++ React/Base/RCTRootView.m | 5 +++++ .../SurfaceHostingView/RCTSurfaceHostingProxyRootView.h | 1 + .../SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm | 5 +++++ React/CoreModules/RCTEventDispatcher.mm | 5 +++++ 6 files changed, 20 insertions(+) diff --git a/React/Base/RCTEventDispatcherProtocol.h b/React/Base/RCTEventDispatcherProtocol.h index 9e54ccbf18..913cf85228 100644 --- a/React/Base/RCTEventDispatcherProtocol.h +++ b/React/Base/RCTEventDispatcherProtocol.h @@ -81,6 +81,8 @@ typedef NS_ENUM(NSInteger, RCTTextEventType) { */ @protocol RCTEventDispatcherProtocol +- (void)sendViewEventWithName:(NSString *)name reactTag:(NSNumber *)reactTag; + /** * Deprecated, do not use. */ diff --git a/React/Base/RCTRootView.h b/React/Base/RCTRootView.h index 27eec8bf3d..dd56345315 100644 --- a/React/Base/RCTRootView.h +++ b/React/Base/RCTRootView.h @@ -88,6 +88,8 @@ extern */ @property (nonatomic, strong, readonly) RCTModuleRegistry *moduleRegistry; +@property (nonatomic, strong, readonly) id eventDispatcher; + /** * The name of the JavaScript module to execute within the * specified scriptURL (required). Setting this will not have diff --git a/React/Base/RCTRootView.m b/React/Base/RCTRootView.m index a8a8c2ccfa..4da26ee42b 100644 --- a/React/Base/RCTRootView.m +++ b/React/Base/RCTRootView.m @@ -126,6 +126,11 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder) return _bridge.moduleRegistry; } +- (id)eventDispatcher +{ + return [self.moduleRegistry moduleForName:"EventDispatcher"]; +} + #pragma mark - passThroughTouches - (BOOL)passThroughTouches diff --git a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h index 110b6e4f23..7a42041d0f 100644 --- a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h +++ b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h @@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong, readonly) RCTBridge *bridge; @property (nonatomic, readonly) BOOL hasBridge; @property (nonatomic, strong, readonly) RCTModuleRegistry *moduleRegistry; +@property (nonatomic, strong, readonly) id eventDispatcher; @property (nonatomic, copy, readwrite) NSDictionary *appProperties; @property (nonatomic, assign) RCTRootViewSizeFlexibility sizeFlexibility; @property (nonatomic, weak) id delegate; diff --git a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm index 6ca24ae80b..ad12ace6dd 100644 --- a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm +++ b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm @@ -104,6 +104,11 @@ static RCTRootViewSizeFlexibility convertToRootViewSizeFlexibility(RCTSurfaceSiz return _bridge.moduleRegistry; } +- (id)eventDispatcher +{ + return [self.moduleRegistry moduleForName:"EventDispatcher"]; +} + RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame) RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder) diff --git a/React/CoreModules/RCTEventDispatcher.mm b/React/CoreModules/RCTEventDispatcher.mm index d9c6905389..5b2dad2d61 100644 --- a/React/CoreModules/RCTEventDispatcher.mm +++ b/React/CoreModules/RCTEventDispatcher.mm @@ -56,6 +56,11 @@ RCT_EXPORT_MODULE() _observersLock = [NSLock new]; } +- (void)sendViewEventWithName:(NSString *)name reactTag:(NSNumber *)reactTag +{ + [_callableJSModules invokeModule:@"RCTViewEventEmitter" method:@"emit" withArgs:@[ name, RCTNullIfNil(reactTag) ]]; +} + - (void)sendAppEventWithName:(NSString *)name body:(id)body { [_callableJSModules invokeModule:@"RCTNativeAppEventEmitter" From a8ac5ea32676dedb17b63069a0c83ddf71746888 Mon Sep 17 00:00:00 2001 From: Xuan Huang Date: Thu, 2 Sep 2021 17:02:48 -0700 Subject: [PATCH 20/22] Revert the Android specific max heap size GCConfig Summary: Changelog: [Category][Internal] This diff reverts the [Androids-specific heap size overrides](github.com/facebook/react-native/commit/63d20d3b1ef35cb4398d63d62f631f7f5d2935c7#diff-4c59ddca85e294a90a0e1bd15ed323ff4e130911d9642680dde44aacbcd7d32c) after [Hermes has changed its default max heap size to 3GiB](https://github.com/facebook/hermes/commit/5f2b47d0be6281fd2605d24efc0b43af42b4033d). You can read about more context there. Reviewed By: yungsters Differential Revision: D30726067 fbshipit-source-id: 1bcc93fdf4da817f3b3d60bd09c6a5a64166eb7e --- .../hermes/reactexecutor/HermesExecutorFactory.java | 2 +- .../com/facebook/hermes/reactexecutor/RuntimeConfig.java | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java index 976af80b1e..ce09abba96 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java @@ -17,7 +17,7 @@ public class HermesExecutorFactory implements JavaScriptExecutorFactory { private final RuntimeConfig mConfig; public HermesExecutorFactory() { - this(new RuntimeConfig(1024)); + this(null); } public HermesExecutorFactory(RuntimeConfig config) { diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java index fec7c457bc..a3e91b8cce 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java @@ -10,10 +10,4 @@ package com.facebook.hermes.reactexecutor; /** Holds runtime configuration for a Hermes VM instance (master or snapshot). */ public final class RuntimeConfig { public long heapSizeMB; - - RuntimeConfig() {} - - RuntimeConfig(long heapSizeMB) { - this.heapSizeMB = heapSizeMB; - } } From 66bd1e9c2c5c12d8652847b068ea149e790259cf Mon Sep 17 00:00:00 2001 From: Xuan Huang Date: Thu, 2 Sep 2021 17:55:31 -0700 Subject: [PATCH 21/22] Bump Hermes npm to 0.9.0 Summary: Changelog: [General][Changed] - Bump Hermes to 0.9.0 allow-large-files Reviewed By: lunaleaps Differential Revision: D30726474 fbshipit-source-id: 742cf68b046d8768e83e00d754e8efcc97586c00 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 5c651a3d53..97747f06de 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "anser": "^1.4.9", "base64-js": "^1.1.2", "event-target-shim": "^5.0.1", - "hermes-engine": "~0.8.0", + "hermes-engine": "~0.9.0", "invariant": "^2.2.4", "jsc-android": "^250230.2.1", "metro-babel-register": "0.66.2", diff --git a/yarn.lock b/yarn.lock index 5f5e62cfb9..59cfe9134a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3297,10 +3297,10 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hermes-engine@~0.8.0: - version "0.8.1" - resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.8.1.tgz#b6d0d70508ac5add2d198304502fb968cdecb8b2" - integrity sha512-as9Iccj/qrqqtDmfYUHbOIjt5xsQbUB6pjNIW3i1+RVr+pCAdz5S8/Jry778mz3rJWplYzHWdR1u1xQSYfBRYw== +hermes-engine@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.9.0.tgz#84d9cfe84e8f6b1b2020d6e71b350cec84ed982f" + integrity sha512-r7U+Y4P2Qg/igFVZN+DpT7JFfXUn1MM4dFne8aW+cCrF6RRymof+VqrUHs1kl07j8h8V2CNesU19RKgWbr3qPw== hermes-parser@0.4.7: version "0.4.7" From 8e66f0b35b5ec1054994f7048ef3e66002544197 Mon Sep 17 00:00:00 2001 From: Xuan Huang Date: Thu, 2 Sep 2021 18:41:29 -0700 Subject: [PATCH 22/22] Bump Hermes pod to 0.9.0 Summary: Changelog: [General][Changed] - Bump Hermes to 0.9.0 (Note: this ignores all push blocking failures!) Reviewed By: lunaleaps Differential Revision: D30726473 fbshipit-source-id: add4149454b3f0333f3c1cb8b5d632371fd1bd80 --- packages/rn-tester/Podfile.lock | 3 ++- scripts/react_native_pods.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 9fb2a10be8..265d84a185 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -738,6 +738,7 @@ DEPENDENCIES: - FlipperKit/FlipperKitUserDefaultsPlugin (= 0.99.0) - FlipperKit/SKIOSNetworkPlugin (= 0.99.0) - glog (from `../../third-party-podspecs/glog.podspec`) + - OpenSSL-Universal (= 1.1.180) - RCT-Folly (from `../../third-party-podspecs/RCT-Folly.podspec`) - RCT-Folly/Fabric (from `../../third-party-podspecs/RCT-Folly.podspec`) - RCTRequired (from `../../Libraries/RCTRequired`) @@ -918,6 +919,6 @@ SPEC CHECKSUMS: Yoga: c0d06f5380d34e939f55420669a60fe08b79bd75 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: ae3037f2256663bd77e3b1cffcac23908027fdb1 +PODFILE CHECKSUM: 5cc47caddf8a8bf3fe9ea873886352846aee027a COCOAPODS: 1.10.1 diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index dd3d60ca25..0853df7e45 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -65,7 +65,7 @@ def use_react_native! (options={}) if hermes_enabled pod 'React-hermes', :path => "#{prefix}/ReactCommon/hermes" - pod 'hermes-engine' + pod 'hermes-engine', '~> 0.9.0' pod 'libevent', '~> 2.1.12' end end